From b78bce08e3715aed96109a67849bbe6c334515f3 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Sun, 16 Jul 2017 13:42:12 -0400 Subject: [PATCH] cmd/go: ignore -linkmode=external during cmd/cgo build 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 --- src/cmd/go/internal/work/build.go | 34 ++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index ef0824625a..0a1783ed2f 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -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") -- 2.48.1