]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: stamp tags and flags in build info
authorJay Conrod <jayconrod@google.com>
Tue, 12 Oct 2021 22:08:54 +0000 (15:08 -0700)
committerJay Conrod <jayconrod@google.com>
Thu, 14 Oct 2021 18:44:48 +0000 (18:44 +0000)
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 <jayconrod@google.com>
Run-TryBot: Jay Conrod <jayconrod@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
src/cmd/go/alldocs.go
src/cmd/go/go_test.go
src/cmd/go/internal/cfg/cfg.go
src/cmd/go/internal/load/flag.go
src/cmd/go/internal/load/pkg.go
src/cmd/go/internal/work/build.go
src/cmd/go/testdata/script/version_build_settings.txt [new file with mode: 0644]

index b6ea5a370123dc8e4b495383b47f1af1aa4d8cfe..d04ba04a533fa33ae5c572806f7eaa8a45a7c92d 100644 (file)
 //
 //     -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
 //             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'
index 07e99628965bde494161d3a3a46d296ee95298e5..d67d01aa1e664dc92e8d97883a601b522ddfd72f 100644 (file)
@@ -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")
        }
index e1bf11fce284a944128526fb107d457c78f5bfe6..37e9b2666e88bee419a275886f26257e129cc3b7 100644 (file)
@@ -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()
index 4e0cb5bc19ef76bd43899380599854ccc73ca5f5..d0d5716c3fc2dcd4a77a5dbc323e7710dfc38125 100644 (file)
@@ -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 "<PerPackageFlag>" }
+func (f *PerPackageFlag) String() string { return f.raw }
 
 // Present reports whether the flag appeared on the command line.
 func (f *PerPackageFlag) Present() bool {
index 473fa7a9d6f9d05f18723b3442f099fbff7f6482..716994b3adbe7419107016a81562a4c4ae08552e 100644 (file)
@@ -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()
index 114abab16c1524b933df7af511619b1a1c3033af..e10f647a6d323e86279e961677451fc3c715c55f 100644 (file)
@@ -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 (file)
index 0000000..7e93643
--- /dev/null
@@ -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() {}