From: Jay Conrod Date: Tue, 12 Oct 2021 22:08:54 +0000 (-0700) Subject: cmd/go: stamp tags and flags in build info X-Git-Tag: go1.18beta1~898 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=0fd0639e4c429e147d33bfc42654fcd651f4449f;p=gostls13.git cmd/go: stamp tags and flags in build info Toolchain flags (like -gcflags), build tags (including race and msan), and cgo variables (including CGO_ENABLED, CGO_CPPFLAGS and others) are now stamped into binaries. For #37475 Change-Id: I9023e682c0618f91805434946c6bc937536b69bb Reviewed-on: https://go-review.googlesource.com/c/go/+/355493 Trust: Jay Conrod Run-TryBot: Jay Conrod TryBot-Result: Go Bot Reviewed-by: Bryan C. Mills --- diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index b6ea5a3701..d04ba04a53 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -131,6 +131,11 @@ // // -asmflags '[pattern=]arg list' // arguments to pass on each go tool asm invocation. +// -buildinfo +// Whether to stamp binaries with build flags. By default, the compiler name +// (gc or gccgo), toolchain flags (like -gcflags), and environment variables +// containing flags (like CGO_CFLAGS) are stamped into binaries. Use +// -buildinfo=false to omit build information. See also -buildvcs. // -buildmode mode // build mode to use. See 'go help buildmode' for more. // -buildvcs @@ -138,7 +143,7 @@ // version control information is stamped into a binary if the main package // and the main module containing it are in the repository containing the // current directory (if there is a repository). Use -buildvcs=false to -// omit version control information. +// omit version control information. See also -buildinfo. // -compiler name // name of compiler to use, as in runtime.Compiler (gccgo or gc). // -gccgoflags '[pattern=]arg list' diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index 07e9962896..d67d01aa1e 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -1380,7 +1380,7 @@ func TestLdFlagsLongArgumentsIssue42295(t *testing.T) { for buf.Len() < sys.ExecArgLengthLimit+1 { buf.WriteString(testStr) } - tg.run("run", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go")) + tg.run("run", "-buildinfo=false", "-ldflags", fmt.Sprintf(`-X "main.extern=%s"`, buf.String()), tg.path("main.go")) if tg.stderr.String() != buf.String() { t.Errorf("strings differ") } diff --git a/src/cmd/go/internal/cfg/cfg.go b/src/cmd/go/internal/cfg/cfg.go index e1bf11fce2..37e9b2666e 100644 --- a/src/cmd/go/internal/cfg/cfg.go +++ b/src/cmd/go/internal/cfg/cfg.go @@ -25,6 +25,7 @@ import ( // These are general "build flags" used by build and other commands. var ( BuildA bool // -a flag + BuildBuildinfo bool // -buildinfo flag BuildBuildmode string // -buildmode flag BuildBuildvcs bool // -buildvcs flag BuildContext = defaultContext() diff --git a/src/cmd/go/internal/load/flag.go b/src/cmd/go/internal/load/flag.go index 4e0cb5bc19..d0d5716c3f 100644 --- a/src/cmd/go/internal/load/flag.go +++ b/src/cmd/go/internal/load/flag.go @@ -22,6 +22,7 @@ var ( // that allows specifying different effective flags for different packages. // See 'go help build' for more details about per-package flags. type PerPackageFlag struct { + raw string present bool values []ppfValue } @@ -39,6 +40,7 @@ func (f *PerPackageFlag) Set(v string) error { // set is the implementation of Set, taking a cwd (current working directory) for easier testing. func (f *PerPackageFlag) set(v, cwd string) error { + f.raw = v f.present = true match := func(p *Package) bool { return p.Internal.CmdlinePkg || p.Internal.CmdlineFiles } // default predicate with no pattern // For backwards compatibility with earlier flag splitting, ignore spaces around flags. @@ -72,9 +74,7 @@ func (f *PerPackageFlag) set(v, cwd string) error { return nil } -// String is required to implement flag.Value. -// It is not used, because cmd/go never calls flag.PrintDefaults. -func (f *PerPackageFlag) String() string { return "" } +func (f *PerPackageFlag) String() string { return f.raw } // Present reports whether the flag appeared on the command line. func (f *PerPackageFlag) Present() bool { diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 473fa7a9d6..716994b3ad 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -2268,6 +2268,35 @@ func (p *Package) setBuildInfo() { Main: main, Deps: deps, } + appendSetting := func(key, value string) { + info.Settings = append(info.Settings, debug.BuildSetting{Key: key, Value: value}) + } + + // Add command-line flags relevant to the build. + // This is informational, not an exhaustive list. + if cfg.BuildBuildinfo { + appendSetting("compiler", cfg.BuildContext.Compiler) + if BuildAsmflags.present { + appendSetting("asmflags", BuildAsmflags.String()) + } + if BuildGcflags.present && cfg.BuildContext.Compiler == "gc" { + appendSetting("gcflags", BuildGcflags.String()) + } + if BuildGccgoflags.present && cfg.BuildContext.Compiler == "gccgo" { + appendSetting("gccgoflags", BuildGccgoflags.String()) + } + if BuildLdflags.present { + appendSetting("ldflags", BuildLdflags.String()) + } + tags := append(cfg.BuildContext.BuildTags, cfg.BuildContext.ToolTags...) + appendSetting("tags", strings.Join(tags, ",")) + appendSetting("CGO_ENABLED", strconv.FormatBool(cfg.BuildContext.CgoEnabled)) + if cfg.BuildContext.CgoEnabled { + for _, name := range []string{"CGO_CPPFLAGS", "CGO_CFLAGS", "CGO_CXXFLAGS", "CGO_LDFLAGS"} { + appendSetting(name, cfg.Getenv(name)) + } + } + } // Add VCS status if all conditions are true: // @@ -2328,10 +2357,10 @@ func (p *Package) setBuildInfo() { setVCSError(err) return } - info.Settings = []debug.BuildSetting{ + info.Settings = append(info.Settings, []debug.BuildSetting{ {Key: vcsCmd.Cmd + "revision", Value: st.Revision}, {Key: vcsCmd.Cmd + "uncommitted", Value: strconv.FormatBool(st.Uncommitted)}, - } + }...) } text, err := info.MarshalText() diff --git a/src/cmd/go/internal/work/build.go b/src/cmd/go/internal/work/build.go index 114abab16c..e10f647a6d 100644 --- a/src/cmd/go/internal/work/build.go +++ b/src/cmd/go/internal/work/build.go @@ -85,6 +85,11 @@ and test commands: -asmflags '[pattern=]arg list' arguments to pass on each go tool asm invocation. + -buildinfo + Whether to stamp binaries with build flags. By default, the compiler name + (gc or gccgo), toolchain flags (like -gcflags), and environment variables + containing flags (like CGO_CFLAGS) are stamped into binaries. Use + -buildinfo=false to omit build information. See also -buildvcs. -buildmode mode build mode to use. See 'go help buildmode' for more. -buildvcs @@ -92,7 +97,7 @@ and test commands: version control information is stamped into a binary if the main package and the main module containing it are in the repository containing the current directory (if there is a repository). Use -buildvcs=false to - omit version control information. + omit version control information. See also -buildinfo. -compiler name name of compiler to use, as in runtime.Compiler (gccgo or gc). -gccgoflags '[pattern=]arg list' @@ -308,6 +313,7 @@ func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) { cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "") cmd.Flag.BoolVar(&cfg.BuildTrimpath, "trimpath", false, "") cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "") + cmd.Flag.BoolVar(&cfg.BuildBuildinfo, "buildinfo", true, "") cmd.Flag.BoolVar(&cfg.BuildBuildvcs, "buildvcs", true, "") // Undocumented, unstable debugging flags. diff --git a/src/cmd/go/testdata/script/version_build_settings.txt b/src/cmd/go/testdata/script/version_build_settings.txt new file mode 100644 index 0000000000..7e93643b9f --- /dev/null +++ b/src/cmd/go/testdata/script/version_build_settings.txt @@ -0,0 +1,66 @@ +[short] skip + +# Compiler name is always added. +go build +go version -m m$GOEXE +stdout '^\tbuild\tcompiler\tgc$' +! stdout asmflags|gcflags|ldflags|gccgoflags + +# Toolchain flags are added if present. +# The raw flags are included, with package patterns if specified. +go build -asmflags=all=-spectre=all +go version -m m$GOEXE +stdout '^\tbuild\tasmflags\tall=-spectre=all$' + +go build -gcflags=all=-spectre=all +go version -m m$GOEXE +stdout '^\tbuild\tgcflags\tall=-spectre=all$' + +go build -ldflags=-w +go version -m m$GOEXE +stdout '^\tbuild\tldflags\t-w$' + +# gccgoflags are not added when gc is used, and vice versa. +# TODO: test gccgo. +go build -gccgoflags=all=UNUSED +go version -m m$GOEXE +! stdout gccgoflags + +# Build and tool tags are added but not release tags. +# "race" is included with build tags but not "cgo". +go build -tags=a,b +go version -m m$GOEXE +stdout '^\tbuild\ttags\ta,b(,goexperiment\.[a-z0-9]+)*$' +[race] go build -race +[race] go version -m m$GOEXE +[race] stdout '^\tbuild\ttags\t.*race.*$' + +# CGO flags are separate settings. +# CGO_ENABLED is always present. +# Other flags are added if CGO_ENABLED is true. +env CGO_ENABLED=0 +go build +go version -m m$GOEXE +stdout '^\tbuild\tCGO_ENABLED\tfalse$' +! stdout CGO_CPPFLAGS|CGO_CFLAGS|CGO_CXXFLAGS|CGO_LDFLAGS +[cgo] env CGO_ENABLED=1 +[cgo] env CGO_CPPFLAGS=-DFROM_CPPFLAGS=1 +[cgo] env CGO_CFLAGS=-DFROM_CFLAGS=1 +[cgo] env CGO_CXXFLAGS=-DFROM_CXXFLAGS=1 +[cgo] env CGO_LDFLAGS=-L/extra/dir/does/not/exist +[cgo] go build +[cgo] go version -m m$GOEXE +[cgo] stdout '^\tbuild\tCGO_ENABLED\ttrue$' +[cgo] stdout '^\tbuild\tCGO_CPPFLAGS\t-DFROM_CPPFLAGS=1$' +[cgo] stdout '^\tbuild\tCGO_CFLAGS\t-DFROM_CFLAGS=1$' +[cgo] stdout '^\tbuild\tCGO_CXXFLAGS\t-DFROM_CXXFLAGS=1$' +[cgo] stdout '^\tbuild\tCGO_LDFLAGS\t-L/extra/dir/does/not/exist$' + +-- go.mod -- +module example.com/m + +go 1.18 +-- m.go -- +package main + +func main() {}