mirror of https://github.com/golang/go.git
cmd/go: add -changed to query for non-defaults in the env
Fixes #34208
Change-Id: I8ec2d96262dcd7cbf870f6173690143c54190722
GitHub-Last-Rev: 6543df4784
GitHub-Pull-Request: golang/go#65655
Reviewed-on: https://go-review.googlesource.com/c/go/+/563137
Reviewed-by: Alan Donovan <adonovan@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
parent
d367b2a475
commit
6cd066f8b2
|
|
@ -8,6 +8,10 @@ Distributions that install the `go` command to a location other than
|
|||
`$GOROOT/bin/go` should install a symlink instead of relocating
|
||||
or copying the `go` binary.
|
||||
|
||||
The new go env `-changed` flag causes the command to print only
|
||||
those settings whose effective value differs from the default value
|
||||
that would be obtained in an empty environment with no prior uses of the `-w` flag.
|
||||
|
||||
### Vet {#vet}
|
||||
|
||||
The `go vet` subcommand now includes the
|
||||
|
|
|
|||
|
|
@ -456,7 +456,7 @@
|
|||
//
|
||||
// Usage:
|
||||
//
|
||||
// go env [-json] [-u] [-w] [var ...]
|
||||
// go env [-json] [-changed] [-u] [-w] [var ...]
|
||||
//
|
||||
// Env prints Go environment information.
|
||||
//
|
||||
|
|
@ -476,6 +476,10 @@
|
|||
// form NAME=VALUE and changes the default settings
|
||||
// of the named environment variables to the given values.
|
||||
//
|
||||
// The -changed flag prints only those settings whose effective
|
||||
// value differs from the default value that would be obtained in
|
||||
// an empty environment with no prior uses of the -w flag.
|
||||
//
|
||||
// For more about environment variables, see 'go help environment'.
|
||||
//
|
||||
// # Update packages to use new APIs
|
||||
|
|
|
|||
|
|
@ -196,7 +196,7 @@ func TestMain(m *testing.M) {
|
|||
defer removeAll(testTmpDir)
|
||||
}
|
||||
|
||||
testGOCACHE = cache.DefaultDir()
|
||||
testGOCACHE, _ = cache.DefaultDir()
|
||||
if testenv.HasGoBuild() {
|
||||
testBin = filepath.Join(testTmpDir, "testbin")
|
||||
if err := os.Mkdir(testBin, 0777); err != nil {
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ func printGoEnv(w io.Writer) {
|
|||
env := envcmd.MkEnv()
|
||||
env = append(env, envcmd.ExtraEnvVars()...)
|
||||
env = append(env, envcmd.ExtraEnvVarsCostly()...)
|
||||
envcmd.PrintEnv(w, env)
|
||||
envcmd.PrintEnv(w, env, false)
|
||||
}
|
||||
|
||||
func printGoDetails(w io.Writer) {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ See golang.org to learn more about Go.
|
|||
// initDefaultCache does the work of finding the default cache
|
||||
// the first time Default is called.
|
||||
func initDefaultCache() {
|
||||
dir := DefaultDir()
|
||||
dir, _ := DefaultDir()
|
||||
if dir == "off" {
|
||||
if defaultDirErr != nil {
|
||||
base.Fatalf("build cache is required, but could not be located: %v", defaultDirErr)
|
||||
|
|
@ -67,14 +67,16 @@ func initDefaultCache() {
|
|||
}
|
||||
|
||||
var (
|
||||
defaultDirOnce sync.Once
|
||||
defaultDir string
|
||||
defaultDirErr error
|
||||
defaultDirOnce sync.Once
|
||||
defaultDir string
|
||||
defaultDirChanged bool // effective value differs from $GOCACHE
|
||||
defaultDirErr error
|
||||
)
|
||||
|
||||
// DefaultDir returns the effective GOCACHE setting.
|
||||
// It returns "off" if the cache is disabled.
|
||||
func DefaultDir() string {
|
||||
// It returns "off" if the cache is disabled,
|
||||
// and reports whether the effective value differs from GOCACHE.
|
||||
func DefaultDir() (string, bool) {
|
||||
// Save the result of the first call to DefaultDir for later use in
|
||||
// initDefaultCache. cmd/go/main.go explicitly sets GOCACHE so that
|
||||
// subprocesses will inherit it, but that means initDefaultCache can't
|
||||
|
|
@ -82,10 +84,11 @@ func DefaultDir() string {
|
|||
|
||||
defaultDirOnce.Do(func() {
|
||||
defaultDir = cfg.Getenv("GOCACHE")
|
||||
if filepath.IsAbs(defaultDir) || defaultDir == "off" {
|
||||
return
|
||||
}
|
||||
if defaultDir != "" {
|
||||
defaultDirChanged = true
|
||||
if filepath.IsAbs(defaultDir) || defaultDir == "off" {
|
||||
return
|
||||
}
|
||||
defaultDir = "off"
|
||||
defaultDirErr = fmt.Errorf("GOCACHE is not an absolute path")
|
||||
return
|
||||
|
|
@ -95,11 +98,12 @@ func DefaultDir() string {
|
|||
dir, err := os.UserCacheDir()
|
||||
if err != nil {
|
||||
defaultDir = "off"
|
||||
defaultDirChanged = true
|
||||
defaultDirErr = fmt.Errorf("GOCACHE is not defined and %v", err)
|
||||
return
|
||||
}
|
||||
defaultDir = filepath.Join(dir, "go-build")
|
||||
})
|
||||
|
||||
return defaultDir
|
||||
return defaultDir, defaultDirChanged
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,9 @@ var (
|
|||
|
||||
// GoPathError is set when GOPATH is not set. it contains an
|
||||
// explanation why GOPATH is unset.
|
||||
GoPathError string
|
||||
GoPathError string
|
||||
GOPATHChanged bool
|
||||
CGOChanged bool
|
||||
)
|
||||
|
||||
func defaultContext() build.Context {
|
||||
|
|
@ -111,7 +113,7 @@ func defaultContext() build.Context {
|
|||
|
||||
// Override defaults computed in go/build with defaults
|
||||
// from go environment configuration file, if known.
|
||||
ctxt.GOPATH = envOr("GOPATH", gopath(ctxt))
|
||||
ctxt.GOPATH, GOPATHChanged = EnvOrAndChanged("GOPATH", gopath(ctxt))
|
||||
ctxt.GOOS = Goos
|
||||
ctxt.GOARCH = Goarch
|
||||
|
||||
|
|
@ -125,14 +127,16 @@ func defaultContext() build.Context {
|
|||
ctxt.ToolTags = save
|
||||
|
||||
// The go/build rule for whether cgo is enabled is:
|
||||
// 1. If $CGO_ENABLED is set, respect it.
|
||||
// 2. Otherwise, if this is a cross-compile, disable cgo.
|
||||
// 3. Otherwise, use built-in default for GOOS/GOARCH.
|
||||
// 1. If $CGO_ENABLED is set, respect it.
|
||||
// 2. Otherwise, if this is a cross-compile, disable cgo.
|
||||
// 3. Otherwise, use built-in default for GOOS/GOARCH.
|
||||
//
|
||||
// Recreate that logic here with the new GOOS/GOARCH setting.
|
||||
if v := Getenv("CGO_ENABLED"); v == "0" || v == "1" {
|
||||
ctxt.CgoEnabled = v[0] == '1'
|
||||
} else if ctxt.GOOS != runtime.GOOS || ctxt.GOARCH != runtime.GOARCH {
|
||||
ctxt.CgoEnabled = false
|
||||
// We need to run steps 2 and 3 to determine what the default value
|
||||
// of CgoEnabled would be for computing CGOChanged.
|
||||
defaultCgoEnabled := ctxt.CgoEnabled
|
||||
if ctxt.GOOS != runtime.GOOS || ctxt.GOARCH != runtime.GOARCH {
|
||||
defaultCgoEnabled = false
|
||||
} else {
|
||||
// Use built-in default cgo setting for GOOS/GOARCH.
|
||||
// Note that ctxt.GOOS/GOARCH are derived from the preference list
|
||||
|
|
@ -159,11 +163,16 @@ func defaultContext() build.Context {
|
|||
if os.Getenv("CC") == "" {
|
||||
cc := DefaultCC(ctxt.GOOS, ctxt.GOARCH)
|
||||
if _, err := LookPath(cc); err != nil {
|
||||
ctxt.CgoEnabled = false
|
||||
defaultCgoEnabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ctxt.CgoEnabled = defaultCgoEnabled
|
||||
if v := Getenv("CGO_ENABLED"); v == "0" || v == "1" {
|
||||
ctxt.CgoEnabled = v[0] == '1'
|
||||
}
|
||||
CGOChanged = ctxt.CgoEnabled != defaultCgoEnabled
|
||||
|
||||
ctxt.OpenFile = func(path string) (io.ReadCloser, error) {
|
||||
return fsys.Open(path)
|
||||
|
|
@ -262,8 +271,9 @@ func init() {
|
|||
|
||||
// An EnvVar is an environment variable Name=Value.
|
||||
type EnvVar struct {
|
||||
Name string
|
||||
Value string
|
||||
Name string
|
||||
Value string
|
||||
Changed bool // effective Value differs from default
|
||||
}
|
||||
|
||||
// OrigEnv is the original environment of the program at startup.
|
||||
|
|
@ -279,27 +289,28 @@ var envCache struct {
|
|||
m map[string]string
|
||||
}
|
||||
|
||||
// EnvFile returns the name of the Go environment configuration file.
|
||||
func EnvFile() (string, error) {
|
||||
// EnvFile returns the name of the Go environment configuration file,
|
||||
// and reports whether the effective value differs from the default.
|
||||
func EnvFile() (string, bool, error) {
|
||||
if file := os.Getenv("GOENV"); file != "" {
|
||||
if file == "off" {
|
||||
return "", fmt.Errorf("GOENV=off")
|
||||
return "", false, fmt.Errorf("GOENV=off")
|
||||
}
|
||||
return file, nil
|
||||
return file, true, nil
|
||||
}
|
||||
dir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", false, err
|
||||
}
|
||||
if dir == "" {
|
||||
return "", fmt.Errorf("missing user-config dir")
|
||||
return "", false, fmt.Errorf("missing user-config dir")
|
||||
}
|
||||
return filepath.Join(dir, "go/env"), nil
|
||||
return filepath.Join(dir, "go/env"), false, nil
|
||||
}
|
||||
|
||||
func initEnvCache() {
|
||||
envCache.m = make(map[string]string)
|
||||
if file, _ := EnvFile(); file != "" {
|
||||
if file, _, _ := EnvFile(); file != "" {
|
||||
readEnvFile(file, "user")
|
||||
}
|
||||
goroot := findGOROOT(envCache.m["GOROOT"])
|
||||
|
|
@ -397,57 +408,67 @@ var (
|
|||
GOROOTpkg string
|
||||
GOROOTsrc string
|
||||
|
||||
GOBIN = Getenv("GOBIN")
|
||||
GOMODCACHE = envOr("GOMODCACHE", gopathDir("pkg/mod"))
|
||||
GOBIN = Getenv("GOBIN")
|
||||
GOMODCACHE, GOMODCACHEChanged = EnvOrAndChanged("GOMODCACHE", gopathDir("pkg/mod"))
|
||||
|
||||
// Used in envcmd.MkEnv and build ID computations.
|
||||
GOARM = envOr("GOARM", fmt.Sprint(buildcfg.GOARM))
|
||||
GOARM64 = envOr("GOARM64", fmt.Sprint(buildcfg.GOARM64))
|
||||
GO386 = envOr("GO386", buildcfg.GO386)
|
||||
GOAMD64 = envOr("GOAMD64", fmt.Sprintf("%s%d", "v", buildcfg.GOAMD64))
|
||||
GOMIPS = envOr("GOMIPS", buildcfg.GOMIPS)
|
||||
GOMIPS64 = envOr("GOMIPS64", buildcfg.GOMIPS64)
|
||||
GOPPC64 = envOr("GOPPC64", fmt.Sprintf("%s%d", "power", buildcfg.GOPPC64))
|
||||
GORISCV64 = envOr("GORISCV64", fmt.Sprintf("rva%du64", buildcfg.GORISCV64))
|
||||
GOWASM = envOr("GOWASM", fmt.Sprint(buildcfg.GOWASM))
|
||||
GOARM64, goARM64Changed = EnvOrAndChanged("GOARM64", fmt.Sprint(buildcfg.GOARM64))
|
||||
GOARM, goARMChanged = EnvOrAndChanged("GOARM", fmt.Sprint(buildcfg.GOARM))
|
||||
GO386, go386Changed = EnvOrAndChanged("GO386", buildcfg.GO386)
|
||||
GOAMD64, goAMD64Changed = EnvOrAndChanged("GOAMD64", fmt.Sprintf("%s%d", "v", buildcfg.GOAMD64))
|
||||
GOMIPS, goMIPSChanged = EnvOrAndChanged("GOMIPS", buildcfg.GOMIPS)
|
||||
GOMIPS64, goMIPS64Changed = EnvOrAndChanged("GOMIPS64", buildcfg.GOMIPS64)
|
||||
GOPPC64, goPPC64Changed = EnvOrAndChanged("GOPPC64", fmt.Sprintf("%s%d", "power", buildcfg.GOPPC64))
|
||||
GORISCV64, goRISCV64Changed = EnvOrAndChanged("GORISCV64", fmt.Sprintf("rva%du64", buildcfg.GORISCV64))
|
||||
GOWASM, goWASMChanged = EnvOrAndChanged("GOWASM", fmt.Sprint(buildcfg.GOWASM))
|
||||
|
||||
GOPROXY = envOr("GOPROXY", "")
|
||||
GOSUMDB = envOr("GOSUMDB", "")
|
||||
GOPRIVATE = Getenv("GOPRIVATE")
|
||||
GONOPROXY = envOr("GONOPROXY", GOPRIVATE)
|
||||
GONOSUMDB = envOr("GONOSUMDB", GOPRIVATE)
|
||||
GOINSECURE = Getenv("GOINSECURE")
|
||||
GOVCS = Getenv("GOVCS")
|
||||
GOPROXY, GOPROXYChanged = EnvOrAndChanged("GOPROXY", "")
|
||||
GOSUMDB, GOSUMDBChanged = EnvOrAndChanged("GOSUMDB", "")
|
||||
GOPRIVATE = Getenv("GOPRIVATE")
|
||||
GONOPROXY, GONOPROXYChanged = EnvOrAndChanged("GONOPROXY", GOPRIVATE)
|
||||
GONOSUMDB, GONOSUMDBChanged = EnvOrAndChanged("GONOSUMDB", GOPRIVATE)
|
||||
GOINSECURE = Getenv("GOINSECURE")
|
||||
GOVCS = Getenv("GOVCS")
|
||||
)
|
||||
|
||||
// EnvOrAndChanged returns the environment variable value
|
||||
// and reports whether it differs from the default value.
|
||||
func EnvOrAndChanged(name, def string) (string, bool) {
|
||||
val := Getenv(name)
|
||||
if val != "" {
|
||||
return val, val != def
|
||||
}
|
||||
return def, false
|
||||
}
|
||||
|
||||
var SumdbDir = gopathDir("pkg/sumdb")
|
||||
|
||||
// GetArchEnv returns the name and setting of the
|
||||
// GOARCH-specific architecture environment variable.
|
||||
// If the current architecture has no GOARCH-specific variable,
|
||||
// GetArchEnv returns empty key and value.
|
||||
func GetArchEnv() (key, val string) {
|
||||
func GetArchEnv() (key, val string, changed bool) {
|
||||
switch Goarch {
|
||||
case "arm":
|
||||
return "GOARM", GOARM
|
||||
return "GOARM", GOARM, goARMChanged
|
||||
case "arm64":
|
||||
return "GOARM64", GOARM64
|
||||
return "GOARM64", GOARM64, goARM64Changed
|
||||
case "386":
|
||||
return "GO386", GO386
|
||||
return "GO386", GO386, go386Changed
|
||||
case "amd64":
|
||||
return "GOAMD64", GOAMD64
|
||||
return "GOAMD64", GOAMD64, goAMD64Changed
|
||||
case "mips", "mipsle":
|
||||
return "GOMIPS", GOMIPS
|
||||
return "GOMIPS", GOMIPS, goMIPSChanged
|
||||
case "mips64", "mips64le":
|
||||
return "GOMIPS64", GOMIPS64
|
||||
return "GOMIPS64", GOMIPS64, goMIPS64Changed
|
||||
case "ppc64", "ppc64le":
|
||||
return "GOPPC64", GOPPC64
|
||||
return "GOPPC64", GOPPC64, goPPC64Changed
|
||||
case "riscv64":
|
||||
return "GORISCV64", GORISCV64
|
||||
return "GORISCV64", GORISCV64, goRISCV64Changed
|
||||
case "wasm":
|
||||
return "GOWASM", GOWASM
|
||||
return "GOWASM", GOWASM, goWASMChanged
|
||||
}
|
||||
return "", ""
|
||||
return "", "", false
|
||||
}
|
||||
|
||||
// envOr returns Getenv(key) if set, or else def.
|
||||
|
|
@ -565,6 +586,7 @@ func gopathDir(rel string) string {
|
|||
return filepath.Join(list[0], rel)
|
||||
}
|
||||
|
||||
// Keep consistent with go/build.defaultGOPATH.
|
||||
func gopath(ctxt build.Context) string {
|
||||
if len(ctxt.GOPATH) > 0 {
|
||||
return ctxt.GOPATH
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) {
|
|||
sh := work.NewShell("", fmt.Print)
|
||||
|
||||
if cleanCache {
|
||||
dir := cache.DefaultDir()
|
||||
dir, _ := cache.DefaultDir()
|
||||
if dir != "off" {
|
||||
// Remove the cache subdirectories but not the top cache directory.
|
||||
// The top cache directory may have been created with special permissions
|
||||
|
|
@ -180,7 +180,7 @@ func runClean(ctx context.Context, cmd *base.Command, args []string) {
|
|||
// Instead of walking through the entire cache looking for test results,
|
||||
// we write a file to the cache indicating that all test results from before
|
||||
// right now are to be ignored.
|
||||
dir := cache.DefaultDir()
|
||||
dir, _ := cache.DefaultDir()
|
||||
if dir != "off" {
|
||||
f, err := lockedfile.Edit(filepath.Join(dir, "testexpire.txt"))
|
||||
if err == nil {
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import (
|
|||
)
|
||||
|
||||
var CmdEnv = &base.Command{
|
||||
UsageLine: "go env [-json] [-u] [-w] [var ...]",
|
||||
UsageLine: "go env [-json] [-changed] [-u] [-w] [var ...]",
|
||||
Short: "print Go environment information",
|
||||
Long: `
|
||||
Env prints Go environment information.
|
||||
|
|
@ -53,6 +53,10 @@ The -w flag requires one or more arguments of the
|
|||
form NAME=VALUE and changes the default settings
|
||||
of the named environment variables to the given values.
|
||||
|
||||
The -changed flag prints only those settings whose effective
|
||||
value differs from the default value that would be obtained in
|
||||
an empty environment with no prior uses of the -w flag.
|
||||
|
||||
For more about environment variables, see 'go help environment'.
|
||||
`,
|
||||
}
|
||||
|
|
@ -64,19 +68,20 @@ func init() {
|
|||
}
|
||||
|
||||
var (
|
||||
envJson = CmdEnv.Flag.Bool("json", false, "")
|
||||
envU = CmdEnv.Flag.Bool("u", false, "")
|
||||
envW = CmdEnv.Flag.Bool("w", false, "")
|
||||
envJson = CmdEnv.Flag.Bool("json", false, "")
|
||||
envU = CmdEnv.Flag.Bool("u", false, "")
|
||||
envW = CmdEnv.Flag.Bool("w", false, "")
|
||||
envChanged = CmdEnv.Flag.Bool("changed", false, "")
|
||||
)
|
||||
|
||||
func MkEnv() []cfg.EnvVar {
|
||||
envFile, _ := cfg.EnvFile()
|
||||
envFile, envFileChanged, _ := cfg.EnvFile()
|
||||
env := []cfg.EnvVar{
|
||||
{Name: "GO111MODULE", Value: cfg.Getenv("GO111MODULE")},
|
||||
{Name: "GOARCH", Value: cfg.Goarch},
|
||||
{Name: "GOARCH", Value: cfg.Goarch, Changed: cfg.Goarch != runtime.GOARCH},
|
||||
{Name: "GOBIN", Value: cfg.GOBIN},
|
||||
{Name: "GOCACHE", Value: cache.DefaultDir()},
|
||||
{Name: "GOENV", Value: envFile},
|
||||
{Name: "GOCACHE"},
|
||||
{Name: "GOENV", Value: envFile, Changed: envFileChanged},
|
||||
{Name: "GOEXE", Value: cfg.ExeSuffix},
|
||||
|
||||
// List the raw value of GOEXPERIMENT, not the cleaned one.
|
||||
|
|
@ -90,63 +95,82 @@ func MkEnv() []cfg.EnvVar {
|
|||
{Name: "GOHOSTARCH", Value: runtime.GOARCH},
|
||||
{Name: "GOHOSTOS", Value: runtime.GOOS},
|
||||
{Name: "GOINSECURE", Value: cfg.GOINSECURE},
|
||||
{Name: "GOMODCACHE", Value: cfg.GOMODCACHE},
|
||||
{Name: "GONOPROXY", Value: cfg.GONOPROXY},
|
||||
{Name: "GONOSUMDB", Value: cfg.GONOSUMDB},
|
||||
{Name: "GOOS", Value: cfg.Goos},
|
||||
{Name: "GOPATH", Value: cfg.BuildContext.GOPATH},
|
||||
{Name: "GOMODCACHE", Value: cfg.GOMODCACHE, Changed: cfg.GOMODCACHEChanged},
|
||||
{Name: "GONOPROXY", Value: cfg.GONOPROXY, Changed: cfg.GONOPROXYChanged},
|
||||
{Name: "GONOSUMDB", Value: cfg.GONOSUMDB, Changed: cfg.GONOSUMDBChanged},
|
||||
{Name: "GOOS", Value: cfg.Goos, Changed: cfg.Goos != runtime.GOOS},
|
||||
{Name: "GOPATH", Value: cfg.BuildContext.GOPATH, Changed: cfg.GOPATHChanged},
|
||||
{Name: "GOPRIVATE", Value: cfg.GOPRIVATE},
|
||||
{Name: "GOPROXY", Value: cfg.GOPROXY},
|
||||
{Name: "GOPROXY", Value: cfg.GOPROXY, Changed: cfg.GOPROXYChanged},
|
||||
{Name: "GOROOT", Value: cfg.GOROOT},
|
||||
{Name: "GOSUMDB", Value: cfg.GOSUMDB},
|
||||
{Name: "GOSUMDB", Value: cfg.GOSUMDB, Changed: cfg.GOSUMDBChanged},
|
||||
{Name: "GOTMPDIR", Value: cfg.Getenv("GOTMPDIR")},
|
||||
{Name: "GOTOOLCHAIN", Value: cfg.Getenv("GOTOOLCHAIN")},
|
||||
{Name: "GOTOOLDIR", Value: build.ToolDir},
|
||||
{Name: "GOVCS", Value: cfg.GOVCS},
|
||||
{Name: "GOVERSION", Value: runtime.Version()},
|
||||
{Name: "GODEBUG", Value: os.Getenv("GODEBUG")},
|
||||
{Name: "GODEBUG"},
|
||||
}
|
||||
|
||||
for i := range env {
|
||||
switch env[i].Name {
|
||||
case "GO111MODULE":
|
||||
if env[i].Value != "on" && env[i].Value != "" {
|
||||
env[i].Changed = true
|
||||
}
|
||||
case "GOBIN", "GOEXPERIMENT", "GOFLAGS", "GOINSECURE", "GOPRIVATE", "GOTMPDIR", "GOVCS":
|
||||
if env[i].Value != "" {
|
||||
env[i].Changed = true
|
||||
}
|
||||
case "GOCACHE":
|
||||
env[i].Value, env[i].Changed = cache.DefaultDir()
|
||||
case "GOTOOLCHAIN":
|
||||
if env[i].Value != "auto" {
|
||||
env[i].Changed = true
|
||||
}
|
||||
case "GODEBUG":
|
||||
env[i].Value = os.Getenv("GODEBUG")
|
||||
env[i].Changed = env[i].Value != ""
|
||||
}
|
||||
}
|
||||
|
||||
if work.GccgoBin != "" {
|
||||
env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoBin})
|
||||
env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoBin, Changed: true})
|
||||
} else {
|
||||
env = append(env, cfg.EnvVar{Name: "GCCGO", Value: work.GccgoName})
|
||||
}
|
||||
|
||||
key, val := cfg.GetArchEnv()
|
||||
if key != "" {
|
||||
env = append(env, cfg.EnvVar{Name: key, Value: val})
|
||||
goarch, val, changed := cfg.GetArchEnv()
|
||||
if goarch != "" {
|
||||
env = append(env, cfg.EnvVar{Name: goarch, Value: val, Changed: changed})
|
||||
}
|
||||
|
||||
cc := cfg.Getenv("CC")
|
||||
ccChanged := true
|
||||
if cc == "" {
|
||||
ccChanged = false
|
||||
cc = cfg.DefaultCC(cfg.Goos, cfg.Goarch)
|
||||
}
|
||||
cxx := cfg.Getenv("CXX")
|
||||
cxxChanged := true
|
||||
if cxx == "" {
|
||||
cxxChanged = false
|
||||
cxx = cfg.DefaultCXX(cfg.Goos, cfg.Goarch)
|
||||
}
|
||||
env = append(env, cfg.EnvVar{Name: "AR", Value: envOr("AR", "ar")})
|
||||
env = append(env, cfg.EnvVar{Name: "CC", Value: cc})
|
||||
env = append(env, cfg.EnvVar{Name: "CXX", Value: cxx})
|
||||
ar, arChanged := cfg.EnvOrAndChanged("AR", "ar")
|
||||
env = append(env, cfg.EnvVar{Name: "AR", Value: ar, Changed: arChanged})
|
||||
env = append(env, cfg.EnvVar{Name: "CC", Value: cc, Changed: ccChanged})
|
||||
env = append(env, cfg.EnvVar{Name: "CXX", Value: cxx, Changed: cxxChanged})
|
||||
|
||||
if cfg.BuildContext.CgoEnabled {
|
||||
env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "1"})
|
||||
env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "1", Changed: cfg.CGOChanged})
|
||||
} else {
|
||||
env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "0"})
|
||||
env = append(env, cfg.EnvVar{Name: "CGO_ENABLED", Value: "0", Changed: cfg.CGOChanged})
|
||||
}
|
||||
|
||||
return env
|
||||
}
|
||||
|
||||
func envOr(name, def string) string {
|
||||
val := cfg.Getenv(name)
|
||||
if val != "" {
|
||||
return val
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
func findEnv(env []cfg.EnvVar, name string) string {
|
||||
for _, e := range env {
|
||||
if e.Name == name {
|
||||
|
|
@ -206,7 +230,7 @@ func ExtraEnvVarsCostly() []cfg.EnvVar {
|
|||
return q
|
||||
}
|
||||
|
||||
return []cfg.EnvVar{
|
||||
ret := []cfg.EnvVar{
|
||||
// Note: Update the switch in runEnv below when adding to this list.
|
||||
{Name: "CGO_CFLAGS", Value: join(cflags)},
|
||||
{Name: "CGO_CPPFLAGS", Value: join(cppflags)},
|
||||
|
|
@ -216,6 +240,21 @@ func ExtraEnvVarsCostly() []cfg.EnvVar {
|
|||
{Name: "PKG_CONFIG", Value: b.PkgconfigCmd()},
|
||||
{Name: "GOGCCFLAGS", Value: join(cmd[3:])},
|
||||
}
|
||||
|
||||
for i := range ret {
|
||||
ev := &ret[i]
|
||||
switch ev.Name {
|
||||
case "GOGCCFLAGS": // GOGCCFLAGS cannot be modified
|
||||
case "CGO_CPPFLAGS":
|
||||
ev.Changed = ev.Value != ""
|
||||
case "PKG_CONFIG":
|
||||
ev.Changed = ev.Value != cfg.DefaultPkgConfig
|
||||
case "CGO_CXXFLAGS", "CGO_CFLAGS", "CGO_FFLAGS", "GGO_LDFLAGS":
|
||||
ev.Changed = ev.Value != work.DefaultCFlags
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// argKey returns the KEY part of the arg KEY=VAL, or else arg itself.
|
||||
|
|
@ -297,27 +336,43 @@ func runEnv(ctx context.Context, cmd *base.Command, args []string) {
|
|||
}
|
||||
|
||||
if len(args) > 0 {
|
||||
if *envJson {
|
||||
// Show only the named vars.
|
||||
if !*envChanged {
|
||||
if *envJson {
|
||||
var es []cfg.EnvVar
|
||||
for _, name := range args {
|
||||
e := cfg.EnvVar{Name: name, Value: findEnv(env, name)}
|
||||
es = append(es, e)
|
||||
}
|
||||
env = es
|
||||
} else {
|
||||
// Print just the values, without names.
|
||||
for _, name := range args {
|
||||
fmt.Printf("%s\n", findEnv(env, name))
|
||||
}
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Show only the changed, named vars.
|
||||
var es []cfg.EnvVar
|
||||
for _, name := range args {
|
||||
e := cfg.EnvVar{Name: name, Value: findEnv(env, name)}
|
||||
es = append(es, e)
|
||||
}
|
||||
printEnvAsJSON(es)
|
||||
} else {
|
||||
for _, name := range args {
|
||||
fmt.Printf("%s\n", findEnv(env, name))
|
||||
for _, e := range env {
|
||||
if e.Name == name {
|
||||
es = append(es, e)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
env = es
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// print
|
||||
if *envJson {
|
||||
printEnvAsJSON(env)
|
||||
return
|
||||
printEnvAsJSON(env, *envChanged)
|
||||
} else {
|
||||
PrintEnv(os.Stdout, env, *envChanged)
|
||||
}
|
||||
|
||||
PrintEnv(os.Stdout, env)
|
||||
}
|
||||
|
||||
func runEnvW(args []string) {
|
||||
|
|
@ -423,12 +478,15 @@ func checkBuildConfig(add map[string]string, del map[string]bool) error {
|
|||
}
|
||||
|
||||
// PrintEnv prints the environment variables to w.
|
||||
func PrintEnv(w io.Writer, env []cfg.EnvVar) {
|
||||
func PrintEnv(w io.Writer, env []cfg.EnvVar, onlyChanged bool) {
|
||||
for _, e := range env {
|
||||
if e.Name != "TERM" {
|
||||
if runtime.GOOS != "plan9" && bytes.Contains([]byte(e.Value), []byte{0}) {
|
||||
base.Fatalf("go: internal error: encountered null byte in environment variable %s on non-plan9 platform", e.Name)
|
||||
}
|
||||
if onlyChanged && !e.Changed {
|
||||
continue
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
default:
|
||||
fmt.Fprintf(w, "%s=%s\n", e.Name, shellQuote(e.Value))
|
||||
|
|
@ -503,12 +561,15 @@ func batchEscape(s string) string {
|
|||
return b.String()
|
||||
}
|
||||
|
||||
func printEnvAsJSON(env []cfg.EnvVar) {
|
||||
func printEnvAsJSON(env []cfg.EnvVar, onlyChanged bool) {
|
||||
m := make(map[string]string)
|
||||
for _, e := range env {
|
||||
if e.Name == "TERM" {
|
||||
continue
|
||||
}
|
||||
if onlyChanged && !e.Changed {
|
||||
continue
|
||||
}
|
||||
m[e.Name] = e.Value
|
||||
}
|
||||
enc := json.NewEncoder(os.Stdout)
|
||||
|
|
@ -591,7 +652,7 @@ func checkEnvWrite(key, val string) error {
|
|||
}
|
||||
|
||||
func readEnvFileLines(mustExist bool) []string {
|
||||
file, err := cfg.EnvFile()
|
||||
file, _, err := cfg.EnvFile()
|
||||
if file == "" {
|
||||
if mustExist {
|
||||
base.Fatalf("go: cannot find go env config: %v", err)
|
||||
|
|
@ -655,7 +716,7 @@ func updateEnvFile(add map[string]string, del map[string]bool) {
|
|||
}
|
||||
}
|
||||
|
||||
file, err := cfg.EnvFile()
|
||||
file, _, err := cfg.EnvFile()
|
||||
if file == "" {
|
||||
base.Fatalf("go: cannot find go env config: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ func FuzzPrintEnvEscape(f *testing.F) {
|
|||
if runtime.GOOS == "windows" {
|
||||
b.WriteString("@echo off\n")
|
||||
}
|
||||
PrintEnv(&b, []cfg.EnvVar{{Name: "var", Value: s}})
|
||||
PrintEnv(&b, []cfg.EnvVar{{Name: "var", Value: s}}, false)
|
||||
var want string
|
||||
if runtime.GOOS == "windows" {
|
||||
fmt.Fprintf(&b, "echo \"%%var%%\"\n")
|
||||
|
|
|
|||
|
|
@ -2392,7 +2392,7 @@ func (p *Package) setBuildInfo(ctx context.Context, autoVCS bool) {
|
|||
appendSetting("GOEXPERIMENT", cfg.RawGOEXPERIMENT)
|
||||
}
|
||||
appendSetting("GOOS", cfg.BuildContext.GOOS)
|
||||
if key, val := cfg.GetArchEnv(); key != "" && val != "" {
|
||||
if key, val, _ := cfg.GetArchEnv(); key != "" && val != "" {
|
||||
appendSetting(key, val)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -147,7 +147,8 @@ func GetPackage(modroot, pkgdir string) (*IndexPackage, error) {
|
|||
// using the index, for instance because the index is disabled, or the package
|
||||
// is not in a module.
|
||||
func GetModule(modroot string) (*Module, error) {
|
||||
if !enabled || cache.DefaultDir() == "off" {
|
||||
dir, _ := cache.DefaultDir()
|
||||
if !enabled || dir == "off" {
|
||||
return nil, errDisabled
|
||||
}
|
||||
if modroot == "" {
|
||||
|
|
|
|||
|
|
@ -837,7 +837,7 @@ func runTest(ctx context.Context, cmd *base.Command, args []string) {
|
|||
// Read testcache expiration time, if present.
|
||||
// (We implement go clean -testcache by writing an expiration date
|
||||
// instead of searching out and deleting test result cache entries.)
|
||||
if dir := cache.DefaultDir(); dir != "off" {
|
||||
if dir, _ := cache.DefaultDir(); dir != "off" {
|
||||
if data, _ := lockedfile.Read(filepath.Join(dir, "testexpire.txt")); len(data) > 0 && data[len(data)-1] == '\n' {
|
||||
if t, err := strconv.ParseInt(string(data[:len(data)-1]), 10, 64); err == nil {
|
||||
testCacheExpire = time.Unix(0, t)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ import (
|
|||
"cmd/internal/sys"
|
||||
)
|
||||
|
||||
const defaultCFlags = "-O2 -g"
|
||||
const DefaultCFlags = "-O2 -g"
|
||||
|
||||
// actionList returns the list of actions in the dag rooted at root
|
||||
// as visited in a depth-first post-order traversal.
|
||||
|
|
@ -337,7 +337,7 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
|
|||
}
|
||||
|
||||
// GOARM, GOMIPS, etc.
|
||||
key, val := cfg.GetArchEnv()
|
||||
key, val, _ := cfg.GetArchEnv()
|
||||
fmt.Fprintf(h, "%s=%s\n", key, val)
|
||||
|
||||
if cfg.CleanGOEXPERIMENT != "" {
|
||||
|
|
@ -1419,7 +1419,7 @@ func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) {
|
|||
}
|
||||
|
||||
// GOARM, GOMIPS, etc.
|
||||
key, val := cfg.GetArchEnv()
|
||||
key, val, _ := cfg.GetArchEnv()
|
||||
fmt.Fprintf(h, "%s=%s\n", key, val)
|
||||
|
||||
if cfg.CleanGOEXPERIMENT != "" {
|
||||
|
|
@ -2460,13 +2460,13 @@ func (b *Builder) gccSupportsFlag(compiler []string, flag string) bool {
|
|||
|
||||
cmdArgs := str.StringList(compiler, flag)
|
||||
if strings.HasPrefix(flag, "-Wl,") /* linker flag */ {
|
||||
ldflags, err := buildFlags("LDFLAGS", defaultCFlags, nil, checkLinkerFlags)
|
||||
ldflags, err := buildFlags("LDFLAGS", DefaultCFlags, nil, checkLinkerFlags)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
cmdArgs = append(cmdArgs, ldflags...)
|
||||
} else { /* compiler flag, add "-c" */
|
||||
cflags, err := buildFlags("CFLAGS", defaultCFlags, nil, checkCompilerFlags)
|
||||
cflags, err := buildFlags("CFLAGS", DefaultCFlags, nil, checkCompilerFlags)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
|
@ -2707,16 +2707,16 @@ func (b *Builder) CFlags(p *load.Package) (cppflags, cflags, cxxflags, fflags, l
|
|||
if cppflags, err = buildFlags("CPPFLAGS", "", p.CgoCPPFLAGS, checkCompilerFlags); err != nil {
|
||||
return
|
||||
}
|
||||
if cflags, err = buildFlags("CFLAGS", defaultCFlags, p.CgoCFLAGS, checkCompilerFlags); err != nil {
|
||||
if cflags, err = buildFlags("CFLAGS", DefaultCFlags, p.CgoCFLAGS, checkCompilerFlags); err != nil {
|
||||
return
|
||||
}
|
||||
if cxxflags, err = buildFlags("CXXFLAGS", defaultCFlags, p.CgoCXXFLAGS, checkCompilerFlags); err != nil {
|
||||
if cxxflags, err = buildFlags("CXXFLAGS", DefaultCFlags, p.CgoCXXFLAGS, checkCompilerFlags); err != nil {
|
||||
return
|
||||
}
|
||||
if fflags, err = buildFlags("FFLAGS", defaultCFlags, p.CgoFFLAGS, checkCompilerFlags); err != nil {
|
||||
if fflags, err = buildFlags("FFLAGS", DefaultCFlags, p.CgoFFLAGS, checkCompilerFlags); err != nil {
|
||||
return
|
||||
}
|
||||
if ldflags, err = buildFlags("LDFLAGS", defaultCFlags, p.CgoLDFLAGS, checkLinkerFlags); err != nil {
|
||||
if ldflags, err = buildFlags("LDFLAGS", DefaultCFlags, p.CgoLDFLAGS, checkLinkerFlags); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -114,7 +114,8 @@ func (sh *Shell) moveOrCopyFile(dst, src string, perm fs.FileMode, force bool) e
|
|||
// Otherwise fall back to standard copy.
|
||||
|
||||
// If the source is in the build cache, we need to copy it.
|
||||
if strings.HasPrefix(src, cache.DefaultDir()) {
|
||||
dir, _ := cache.DefaultDir()
|
||||
if strings.HasPrefix(src, dir) {
|
||||
return sh.CopyFile(dst, src, perm, force)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,45 @@
|
|||
# Test query for non-defaults in the env
|
||||
|
||||
env GOTOOLCHAIN=local
|
||||
env GOSUMDB=nodefault
|
||||
env GOPROXY=nodefault
|
||||
env GO111MODULE=auto
|
||||
env CGO_CFLAGS=nodefault
|
||||
env CGO_CPPFLAGS=nodefault
|
||||
|
||||
go env -changed
|
||||
# linux output like GOTOOLCHAIN='local'
|
||||
# windows output like GOTOOLCHAIN=local
|
||||
stdout 'GOTOOLCHAIN=''?local''?'
|
||||
stdout 'GOSUMDB=''?nodefault''?'
|
||||
stdout 'GOPROXY=''?nodefault''?'
|
||||
stdout 'GO111MODULE=''?auto''?'
|
||||
stdout 'CGO_CFLAGS=''?nodefault''?'
|
||||
stdout 'CGO_CPPFLAGS=''?nodefault''?'
|
||||
|
||||
go env -changed -json
|
||||
stdout '"GOTOOLCHAIN": "local"'
|
||||
stdout '"GOSUMDB": "nodefault"'
|
||||
stdout '"GOPROXY": "nodefault"'
|
||||
stdout '"GO111MODULE": "auto"'
|
||||
stdout '"CGO_CFLAGS": "nodefault"'
|
||||
stdout '"CGO_CPPFLAGS": "nodefault"'
|
||||
|
||||
[GOOS:windows] env GOOS=linux
|
||||
[!GOOS:windows] env GOOS=windows
|
||||
[GOARCH:amd64] env GOARCH=arm64
|
||||
[!GOARCH:amd64] env GOARCH=amd64
|
||||
|
||||
go env -changed GOOS
|
||||
[GOOS:windows] stdout 'set GOOS=linux'
|
||||
[!GOOS:windows] stdout 'GOOS=''windows'''
|
||||
go env -changed GOARCH
|
||||
[GOARCH:amd64] stdout 'set GOARCH=arm64|GOARCH=''arm64'''
|
||||
[!GOARCH:amd64] stdout 'set GOARCH=amd64|GOARCH=''amd64'''
|
||||
|
||||
go env -changed -json GOOS
|
||||
[GOOS:windows] stdout '"GOOS": "linux"'
|
||||
[!GOOS:windows] stdout '"GOOS": "windows"'
|
||||
go env -changed -json GOARCH
|
||||
[GOARCH:amd64] stdout '"GOARCH": "arm64"'
|
||||
[!GOARCH:amd64] stdout '"GOARCH": "amd64"'
|
||||
|
|
@ -286,6 +286,7 @@ func (ctxt *Context) SrcDirs() []string {
|
|||
// if set, or else the compiled code's GOARCH, GOOS, and GOROOT.
|
||||
var Default Context = defaultContext()
|
||||
|
||||
// Keep consistent with cmd/go/internal/cfg.defaultGOPATH.
|
||||
func defaultGOPATH() string {
|
||||
env := "HOME"
|
||||
if runtime.GOOS == "windows" {
|
||||
|
|
|
|||
Loading…
Reference in New Issue