// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// Package buildcfg provides access to the build configuration // described by the current environment. It is for use by build tools // such as cmd/go or cmd/compile and for setting up go/build's Default context. // // Note that it does NOT provide access to the build configuration used to // build the currently-running binary. For that, use runtime.GOOS etc // as well as internal/goexperiment.
package buildcfg import ( ) var ( GOROOT = runtime.GOROOT() // cached for efficiency GOARCH = envOr("GOARCH", defaultGOARCH) GOOS = envOr("GOOS", defaultGOOS) GO386 = envOr("GO386", defaultGO386) GOAMD64 = goamd64() GOARM = goarm() GOMIPS = gomips() GOMIPS64 = gomips64() GOPPC64 = goppc64() GOWASM = gowasm() ToolTags = toolTags() GO_LDSO = defaultGO_LDSO Version = version ) // Error is one of the errors found (if any) in the build configuration. var Error error // Check exits the program with a fatal error if Error is non-nil. func () { if Error != nil { fmt.Fprintf(os.Stderr, "%s: %v\n", filepath.Base(os.Args[0]), Error) os.Exit(2) } } func envOr(, string) string { if := os.Getenv(); != "" { return } return } func goamd64() int { switch := envOr("GOAMD64", defaultGOAMD64); { case "v1": return 1 case "v2": return 2 case "v3": return 3 case "v4": return 4 } Error = fmt.Errorf("invalid GOAMD64: must be v1, v2, v3, v4") return int(defaultGOAMD64[len("v")] - '0') } type goarmFeatures struct { Version int SoftFloat bool } func ( goarmFeatures) () string { := strconv.Itoa(.Version) if .SoftFloat { += ",softfloat" } else { += ",hardfloat" } return } func goarm() ( goarmFeatures) { const ( = ",softfloat" = ",hardfloat" ) := defaultGOARM if GOOS == "android" && GOARCH == "arm" { // Android arm devices always support GOARM=7. = "7" } := envOr("GOARM", ) := false if strings.HasSuffix(, ) { .SoftFloat = true = true = [:len()-len()] } if strings.HasSuffix(, ) { = true = [:len()-len()] } switch { case "5": .Version = 5 case "6": .Version = 6 case "7": .Version = 7 default: Error = fmt.Errorf("invalid GOARM: must start with 5, 6, or 7, and may optionally end in either %q or %q", , ) .Version = int([0] - '0') } // 5 defaults to softfloat. 6 and 7 default to hardfloat. if ! && .Version == 5 { .SoftFloat = true } return } func gomips() string { switch := envOr("GOMIPS", defaultGOMIPS); { case "hardfloat", "softfloat": return } Error = fmt.Errorf("invalid GOMIPS: must be hardfloat, softfloat") return defaultGOMIPS } func gomips64() string { switch := envOr("GOMIPS64", defaultGOMIPS64); { case "hardfloat", "softfloat": return } Error = fmt.Errorf("invalid GOMIPS64: must be hardfloat, softfloat") return defaultGOMIPS64 } func goppc64() int { switch := envOr("GOPPC64", defaultGOPPC64); { case "power8": return 8 case "power9": return 9 case "power10": return 10 } Error = fmt.Errorf("invalid GOPPC64: must be power8, power9, power10") return int(defaultGOPPC64[len("power")] - '0') } type gowasmFeatures struct { SatConv bool SignExt bool } func ( gowasmFeatures) () string { var []string if .SatConv { = append(, "satconv") } if .SignExt { = append(, "signext") } return strings.Join(, ",") } func gowasm() ( gowasmFeatures) { for , := range strings.Split(envOr("GOWASM", ""), ",") { switch { case "satconv": .SatConv = true case "signext": .SignExt = true case "": // ignore default: Error = fmt.Errorf("invalid GOWASM: no such feature %q", ) } } return } func () string { return envOr("GO_EXTLINK_ENABLED", defaultGO_EXTLINK_ENABLED) } func toolTags() []string { := experimentTags() = append(, gogoarchTags()...) return } func experimentTags() []string { var []string // For each experiment that has been enabled in the toolchain, define a // build tag with the same name but prefixed by "goexperiment." which can be // used for compiling alternative files for the experiment. This allows // changes for the experiment, like extra struct fields in the runtime, // without affecting the base non-experiment code at all. for , := range Experiment.Enabled() { = append(, "goexperiment."+) } return } // GOGOARCH returns the name and value of the GO$GOARCH setting. // For example, if GOARCH is "amd64" it might return "GOAMD64", "v2". func () (, string) { switch GOARCH { case "386": return "GO386", GO386 case "amd64": return "GOAMD64", fmt.Sprintf("v%d", GOAMD64) case "arm": return "GOARM", GOARM.String() case "mips", "mipsle": return "GOMIPS", GOMIPS case "mips64", "mips64le": return "GOMIPS64", GOMIPS64 case "ppc64", "ppc64le": return "GOPPC64", fmt.Sprintf("power%d", GOPPC64) case "wasm": return "GOWASM", GOWASM.String() } return "", "" } func gogoarchTags() []string { switch GOARCH { case "386": return []string{GOARCH + "." + GO386} case "amd64": var []string for := 1; <= GOAMD64; ++ { = append(, fmt.Sprintf("%s.v%d", GOARCH, )) } return case "arm": var []string for := 5; <= GOARM.Version; ++ { = append(, fmt.Sprintf("%s.%d", GOARCH, )) } return case "mips", "mipsle": return []string{GOARCH + "." + GOMIPS} case "mips64", "mips64le": return []string{GOARCH + "." + GOMIPS64} case "ppc64", "ppc64le": var []string for := 8; <= GOPPC64; ++ { = append(, fmt.Sprintf("%s.power%d", GOARCH, )) } return case "wasm": var []string if GOWASM.SatConv { = append(, GOARCH+".satconv") } if GOWASM.SignExt { = append(, GOARCH+".signext") } return } return nil }