]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: put computed GOROOT in built binaries
authorDavid Crawshaw <crawshaw@golang.org>
Sun, 3 Sep 2017 16:33:56 +0000 (12:33 -0400)
committerDavid Crawshaw <crawshaw@golang.org>
Sat, 9 Sep 2017 16:59:35 +0000 (16:59 +0000)
As of CL 42533, cmd/go will recompute its GOROOT based on the
location of its own executable. This CL plumbs that computed GOROOT
into every binary it builds using the linker -X flag. This
means binaries built with a moved cmd/go will report the GOROOT
they were built in from runtime.GOROOT().

Fixes #21313

Change-Id: I6c2c559f40f2a0c867ab60cf47c6dbc73ae5e28a
Reviewed-on: https://go-review.googlesource.com/61310
Run-TryBot: David Crawshaw <crawshaw@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/dist/buildruntime.go
src/cmd/go/go_test.go
src/cmd/go/internal/work/build.go
src/cmd/go/testdata/print_goroot.go [new file with mode: 0644]

index b885a79228ea7715db60fe9c2943137ee51c616e..836b2ef31c4e4c438da0e70bc88d49cffff78e00 100644 (file)
@@ -17,7 +17,8 @@ import (
 // mkzversion writes zversion.go:
 //
 //     package sys
-//     const DefaultGoroot = <goroot>
+//     var DefaultGoroot = <goroot>
+//
 //     const TheVersion = <version>
 //     const Goexperiment = <goexperiment>
 //     const StackGuardMultiplier = <multiplier value>
@@ -28,7 +29,7 @@ func mkzversion(dir, file string) {
                        "\n"+
                        "package sys\n"+
                        "\n"+
-                       "const DefaultGoroot = `%s`\n"+
+                       "var DefaultGoroot = `%s`\n\n"+
                        "const TheVersion = `%s`\n"+
                        "const Goexperiment = `%s`\n"+
                        "const StackGuardMultiplier = %d\n\n", goroot_final, findgoversion(), os.Getenv("GOEXPERIMENT"), stackGuardMultiplier())
index 87810ad6cb53bce6fdafa656aed228ae0d5cb8db..3908fe8823213a740753c25480b736bfda84ee8a 100644 (file)
@@ -4163,7 +4163,7 @@ func TestExecutableGOROOT(t *testing.T) {
                if err != nil {
                        t.Fatal(err)
                }
-               m := regexp.MustCompile("const DefaultGoroot = `([^`]+)`").FindStringSubmatch(string(data))
+               m := regexp.MustCompile("var DefaultGoroot = `([^`]+)`").FindStringSubmatch(string(data))
                if m == nil {
                        t.Fatal("cannot find DefaultGoroot in ../../runtime/internal/sys/zversion.go")
                }
@@ -4188,6 +4188,43 @@ func TestExecutableGOROOT(t *testing.T) {
                }
                check(t, symGoTool, newRoot)
        })
+
+       tg.must(os.RemoveAll(tg.path("new/pkg")))
+
+       // Binaries built in the new tree should report the
+       // new tree when they call runtime.GOROOT().
+       // This is implemented by having the go tool pass a -X option
+       // to the linker setting runtime/internal/sys.DefaultGoroot.
+       t.Run("RuntimeGoroot", func(t *testing.T) {
+               // Build a working GOROOT the easy way, with symlinks.
+               testenv.MustHaveSymlink(t)
+               if err := os.Symlink(filepath.Join(testGOROOT, "src"), tg.path("new/src")); err != nil {
+                       t.Fatal(err)
+               }
+               if err := os.Symlink(filepath.Join(testGOROOT, "pkg"), tg.path("new/pkg")); err != nil {
+                       t.Fatal(err)
+               }
+
+               cmd := exec.Command(newGoTool, "run", "testdata/print_goroot.go")
+               cmd.Env = env
+               out, err := cmd.CombinedOutput()
+               if err != nil {
+                       t.Fatalf("%s run testdata/print_goroot.go: %v, %s", newGoTool, err, out)
+               }
+               goroot, err := filepath.EvalSymlinks(strings.TrimSpace(string(out)))
+               if err != nil {
+                       t.Fatal(err)
+               }
+               want, err := filepath.EvalSymlinks(tg.path("new"))
+               if err != nil {
+                       t.Fatal(err)
+               }
+               if !strings.EqualFold(goroot, want) {
+                       t.Errorf("go run testdata/print_goroot.go:\nhave %s\nwant %s", goroot, want)
+               } else {
+                       t.Logf("go run testdata/print_goroot.go: %s", goroot)
+               }
+       })
 }
 
 func TestNeedVersion(t *testing.T) {
index 6b9c5114736835c91fb8bebfabb4163ca124df5d..7cb11aa4221a2c6af451933ec1c5e8c337da13aa 100644 (file)
@@ -2536,6 +2536,9 @@ func (gcToolchain) ld(b *Builder, root *Action, out string, allactions []*Action
        if cfg.BuildBuildmode == "plugin" {
                ldflags = append(ldflags, "-pluginpath", load.PluginPath(root.Package))
        }
+       if cfg.GOROOT != runtime.GOROOT() {
+               ldflags = append(ldflags, "-X=runtime/internal/sys.DefaultGoroot="+cfg.GOROOT)
+       }
 
        // If the user has not specified the -extld option, then specify the
        // appropriate linker. In case of C++ code, use the compiler named
diff --git a/src/cmd/go/testdata/print_goroot.go b/src/cmd/go/testdata/print_goroot.go
new file mode 100644 (file)
index 0000000..5477291
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+import "runtime"
+
+func main() {
+       println(runtime.GOROOT())
+}