]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: ignore -linkmode=external during cmd/cgo build
authorRuss Cox <rsc@golang.org>
Sun, 16 Jul 2017 17:42:12 +0000 (13:42 -0400)
committerRuss Cox <rsc@golang.org>
Tue, 3 Oct 2017 19:58:10 +0000 (19:58 +0000)
cmd/cgo is special among the build tools because it is (re)built on demand
when needed for a package using cgo, to avoid additional bootstrap logic
elsewhere. (This is in contrast to cmd/compile, cmd/link, and so on, which
must be specially built before even invoking the go command.)

When the go command starts using content-based decisions about staleness,
it is important that the build of cmd/cgo never use -linkmode=external,
because that depends on runtime/cgo, which in turn depends on cmd/cgo.

Change-Id: I72a2be748606d1ed4b93a54f2a5c7084e87d5fbc
Reviewed-on: https://go-review.googlesource.com/67310
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/cmd/go/internal/work/build.go

index ef0824625a4830d82380d2b6992560c86f656602..0a1783ed2fb0efe82948c650113ba5f0158049cc 100644 (file)
@@ -2573,12 +2573,23 @@ func (gcToolchain) ld(b *Builder, root *Action, out, importcfg string, allaction
        } else {
                compiler = envList("CC", cfg.DefaultCC)
        }
-       ldflags = setextld(ldflags, compiler)
        ldflags = append(ldflags, "-buildmode="+ldBuildmode)
        if root.Package.Internal.BuildID != "" {
                ldflags = append(ldflags, "-buildid="+root.Package.Internal.BuildID)
        }
        ldflags = append(ldflags, cfg.BuildLdflags...)
+       if root.Package.Goroot {
+               // Cannot force -linkmode=external inside GOROOT.
+               // cmd/cgo cannot be linkmode=external,
+               // because that implies having runtime/cgo available,
+               // and runtime/cgo is built using cmd/cgo.
+               // It's possible the restriction can be limited to just cmd/cgo,
+               // but the whole-GOROOT prohibition matches the similar
+               // logic in ../load/pkg.go that decides whether to add an
+               // implicit runtime/cgo dependency.
+               ldflags = removeLinkmodeExternal(ldflags)
+       }
+       ldflags = setextld(ldflags, compiler)
 
        // On OS X when using external linking to build a shared library,
        // the argument passed here to -o ends up recorded in the final
@@ -2595,6 +2606,27 @@ func (gcToolchain) ld(b *Builder, root *Action, out, importcfg string, allaction
        return b.run(dir, root.Package.ImportPath, nil, cfg.BuildToolexec, base.Tool("link"), "-o", out, "-importcfg", importcfg, ldflags, mainpkg)
 }
 
+// removeLinkmodeExternal removes any attempt to set linkmode=external
+// from ldflags, modifies ldflags in place, and returns ldflags.
+func removeLinkmodeExternal(ldflags []string) []string {
+       out := ldflags[:0]
+       for i := 0; i < len(ldflags); i++ {
+               flag := ldflags[i]
+               if strings.HasPrefix(flag, "--") {
+                       flag = flag[1:]
+               }
+               if flag == "-linkmode" && i+1 < len(ldflags) && ldflags[i+1] == "external" {
+                       i++
+                       continue
+               }
+               if flag == "-linkmode=external" {
+                       continue
+               }
+               out = append(out, flag)
+       }
+       return out
+}
+
 func (gcToolchain) ldShared(b *Builder, toplevelactions []*Action, out, importcfg string, allactions []*Action) error {
        ldflags := []string{"-installsuffix", cfg.BuildContext.InstallSuffix}
        ldflags = append(ldflags, "-buildmode=shared")