1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
23 // Initialization for any invocation.
25 // The usual variables.
41 goextlinkenabled string
42 gogcflags string // For running built compiler
51 defaultcc map[string]string
52 defaultcxx map[string]string
53 defaultpkgconfig string
60 vflag int // verbosity
63 // The known architectures.
64 var okgoarch = []string{
82 // The known operating systems.
83 var okgoos = []string{
102 // find reports the first index of p in l[0:n], or else -1.
103 func find(p string, l []string) int {
104 for i, s := range l {
112 // xinit handles initialization of the various global state, like goroot and goarch.
114 b := os.Getenv("GOROOT")
116 fatalf("$GOROOT must be set")
118 goroot = filepath.Clean(b)
119 gorootBin = pathf("%s/bin", goroot)
121 // Don't run just 'go' because the build infrastructure
122 // runs cmd/dist inside go/bin often, and on Windows
123 // it will be found in the current directory and refuse to exec.
124 // All exec calls rewrite "go" into gorootBinGo.
125 gorootBinGo = pathf("%s/bin/go", goroot)
127 b = os.Getenv("GOROOT_FINAL")
133 b = os.Getenv("GOOS")
138 if find(goos, okgoos) < 0 {
139 fatalf("unknown $GOOS %s", goos)
142 b = os.Getenv("GOARM")
148 b = os.Getenv("GO386")
154 b = os.Getenv("GOAMD64")
160 b = os.Getenv("GOMIPS")
166 b = os.Getenv("GOMIPS64")
172 b = os.Getenv("GOPPC64")
178 if p := pathf("%s/src/all.bash", goroot); !isfile(p) {
179 fatalf("$GOROOT is not set correctly or not exported\n"+
181 "\t%s does not exist", goroot, p)
184 b = os.Getenv("GOHOSTARCH")
188 if find(gohostarch, okgoarch) < 0 {
189 fatalf("unknown $GOHOSTARCH %s", gohostarch)
192 b = os.Getenv("GOARCH")
197 if find(goarch, okgoarch) < 0 {
198 fatalf("unknown $GOARCH %s", goarch)
201 b = os.Getenv("GO_EXTLINK_ENABLED")
203 if b != "0" && b != "1" {
204 fatalf("unknown $GO_EXTLINK_ENABLED %s", b)
209 goexperiment = os.Getenv("GOEXPERIMENT")
210 // TODO(mdempsky): Validate known experiments?
212 gogcflags = os.Getenv("BOOT_GO_GCFLAGS")
213 goldflags = os.Getenv("BOOT_GO_LDFLAGS")
215 defaultcc = compilerEnv("CC", "")
216 defaultcxx = compilerEnv("CXX", "")
218 b = os.Getenv("PKG_CONFIG")
224 defaultldso = os.Getenv("GO_LDSO")
226 // For tools being invoked but also for os.ExpandEnv.
227 os.Setenv("GO386", go386)
228 os.Setenv("GOAMD64", goamd64)
229 os.Setenv("GOARCH", goarch)
230 os.Setenv("GOARM", goarm)
231 os.Setenv("GOHOSTARCH", gohostarch)
232 os.Setenv("GOHOSTOS", gohostos)
233 os.Setenv("GOOS", goos)
234 os.Setenv("GOMIPS", gomips)
235 os.Setenv("GOMIPS64", gomips64)
236 os.Setenv("GOPPC64", goppc64)
237 os.Setenv("GOROOT", goroot)
238 os.Setenv("GOROOT_FINAL", goroot_final)
240 // Set GOBIN to GOROOT/bin. The meaning of GOBIN has drifted over time
241 // (see https://go.dev/issue/3269, https://go.dev/cl/183058,
242 // https://go.dev/issue/31576). Since we want binaries installed by 'dist' to
243 // always go to GOROOT/bin anyway.
244 os.Setenv("GOBIN", gorootBin)
246 // Make the environment more predictable.
247 os.Setenv("LANG", "C")
248 os.Setenv("LANGUAGE", "en_US.UTF8")
249 os.Unsetenv("GO111MODULE")
250 os.Setenv("GOENV", "off")
251 os.Unsetenv("GOFLAGS")
252 os.Setenv("GOWORK", "off")
255 if err := os.WriteFile(pathf("%s/go.mod", workdir), []byte("module bootstrap"), 0666); err != nil {
256 fatalf("cannot write stub go.mod: %s", err)
260 tooldir = pathf("%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch)
262 goversion := findgoversion()
263 isRelease = strings.HasPrefix(goversion, "release.") || strings.HasPrefix(goversion, "go")
266 // compilerEnv returns a map from "goos/goarch" to the
267 // compiler setting to use for that platform.
268 // The entry for key "" covers any goos/goarch not explicitly set in the map.
269 // For example, compilerEnv("CC", "gcc") returns the C compiler settings
270 // read from $CC, defaulting to gcc.
272 // The result is a map because additional environment variables
273 // can be set to change the compiler based on goos/goarch settings.
274 // The following applies to all envNames but CC is assumed to simplify
277 // If no environment variables are set, we use def for all goos/goarch.
278 // $CC, if set, applies to all goos/goarch but is overridden by the following.
279 // $CC_FOR_TARGET, if set, applies to all goos/goarch except gohostos/gohostarch,
280 // but is overridden by the following.
281 // If gohostos=goos and gohostarch=goarch, then $CC_FOR_TARGET applies even for gohostos/gohostarch.
282 // $CC_FOR_goos_goarch, if set, applies only to goos/goarch.
283 func compilerEnv(envName, def string) map[string]string {
284 m := map[string]string{"": def}
286 if env := os.Getenv(envName); env != "" {
289 if env := os.Getenv(envName + "_FOR_TARGET"); env != "" {
290 if gohostos != goos || gohostarch != goarch {
291 m[gohostos+"/"+gohostarch] = m[""]
296 for _, goos := range okgoos {
297 for _, goarch := range okgoarch {
298 if env := os.Getenv(envName + "_FOR_" + goos + "_" + goarch); env != "" {
299 m[goos+"/"+goarch] = env
307 // clangos lists the operating systems where we prefer clang to gcc.
308 var clangos = []string{
309 "darwin", "ios", // macOS 10.9 and later require clang
310 "freebsd", // FreeBSD 10 and later do not ship gcc
311 "openbsd", // OpenBSD ships with GCC 4.2, which is now quite old.
314 // compilerEnvLookup returns the compiler settings for goos/goarch in map m.
315 // kind is "CC" or "CXX".
316 func compilerEnvLookup(kind string, m map[string]string, goos, goarch string) string {
320 if cc := m[goos+"/"+goarch]; cc != "" {
323 if cc := m[""]; cc != "" {
326 for _, os := range clangos {
340 // rmworkdir deletes the work directory.
343 errprintf("rm -rf %s\n", workdir)
348 // Remove trailing spaces.
349 func chomp(s string) string {
350 return strings.TrimRight(s, " \t\r\n")
353 // findgoversion determines the Go version to use in the version string.
354 // It also parses any other metadata found in the version file.
355 func findgoversion() string {
356 // The $GOROOT/VERSION file takes priority, for distributions
357 // without the source repo.
358 path := pathf("%s/VERSION", goroot)
360 b := chomp(readfile(path))
362 // Starting in Go 1.21 the VERSION file starts with the
363 // version on a line by itself but then can contain other
364 // metadata about the release, one item per line.
365 if i := strings.Index(b, "\n"); i >= 0 {
368 for _, line := range strings.Split(rest, "\n") {
369 f := strings.Fields(line)
375 fatalf("VERSION: unexpected line: %s", line)
378 fatalf("VERSION: unexpected time line: %s", line)
380 _, err := time.Parse(time.RFC3339, f[1])
382 fatalf("VERSION: bad time: %s", err)
388 // Commands such as "dist version > VERSION" will cause
389 // the shell to create an empty VERSION file and set dist's
390 // stdout to its fd. dist in turn looks at VERSION and uses
391 // its content if available, which is empty at this point.
392 // Only use the VERSION file if it is non-empty.
398 // The $GOROOT/VERSION.cache file is a cache to avoid invoking
399 // git every time we run this command. Unlike VERSION, it gets
400 // deleted by the clean command.
401 path = pathf("%s/VERSION.cache", goroot)
403 return chomp(readfile(path))
406 // Show a nicer error message if this isn't a Git repo.
408 fatalf("FAILED: not a Git repo; must put a VERSION file in $GOROOT")
411 // Otherwise, use Git.
413 // Include 1.x base version, hash, and date in the version.
415 // Note that we lightly parse internal/goversion/goversion.go to
416 // obtain the base version. We can't just import the package,
417 // because cmd/dist is built with a bootstrap GOROOT which could
418 // be an entirely different version of Go. We assume
419 // that the file contains "const Version = <Integer>".
420 goversionSource := readfile(pathf("%s/src/internal/goversion/goversion.go", goroot))
421 m := regexp.MustCompile(`(?m)^const Version = (\d+)`).FindStringSubmatch(goversionSource)
423 fatalf("internal/goversion/goversion.go does not contain 'const Version = ...'")
425 version := fmt.Sprintf("devel go1.%s-", m[1])
426 version += chomp(run(goroot, CheckExit, "git", "log", "-n", "1", "--format=format:%h %cd", "HEAD"))
429 writefile(version, path, 0)
434 // isGitRepo reports whether the working directory is inside a Git repository.
435 func isGitRepo() bool {
436 // NB: simply checking the exit code of `git rev-parse --git-dir` would
437 // suffice here, but that requires deviating from the infrastructure
438 // provided by `run`.
439 gitDir := chomp(run(goroot, 0, "git", "rev-parse", "--git-dir"))
440 if !filepath.IsAbs(gitDir) {
441 gitDir = filepath.Join(goroot, gitDir)
447 * Initial tree setup.
450 // The old tools that no longer live in $GOBIN or $GOROOT/bin.
451 var oldtool = []string{
452 "5a", "5c", "5g", "5l",
453 "6a", "6c", "6g", "6l",
454 "8a", "8c", "8g", "8l",
455 "9a", "9c", "9g", "9l",
474 // Unreleased directories (relative to $GOROOT) that should
475 // not be in release branches.
476 var unreleased = []string{
483 // setup sets up the tree for the initial build.
485 // Create bin directory.
486 if p := pathf("%s/bin", goroot); !isdir(p) {
490 // Create package directory.
491 if p := pathf("%s/pkg", goroot); !isdir(p) {
495 goosGoarch := pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch)
497 xremoveall(goosGoarch)
499 xmkdirall(goosGoarch)
501 if files := xreaddir(goosGoarch); len(files) == 0 {
506 if goos != gohostos || goarch != gohostarch {
507 p := pathf("%s/pkg/%s_%s", goroot, goos, goarch)
514 // Create object directory.
515 // We used to use it for C objects.
516 // Now we use it for the build cache, to separate dist's cache
517 // from any other cache the user might have, and for the location
518 // to build the bootstrap versions of the standard library.
519 obj := pathf("%s/pkg/obj", goroot)
523 xatexit(func() { xremove(obj) })
525 // Create build cache directory.
526 objGobuild := pathf("%s/pkg/obj/go-build", goroot)
528 xremoveall(objGobuild)
530 xmkdirall(objGobuild)
531 xatexit(func() { xremoveall(objGobuild) })
533 // Create directory for bootstrap versions of standard library .a files.
534 objGoBootstrap := pathf("%s/pkg/obj/go-bootstrap", goroot)
536 xremoveall(objGoBootstrap)
538 xmkdirall(objGoBootstrap)
539 xatexit(func() { xremoveall(objGoBootstrap) })
541 // Create tool directory.
542 // We keep it in pkg/, just like the object directory above.
548 // Remove tool binaries from before the tool/gohostos_gohostarch
549 xremoveall(pathf("%s/bin/tool", goroot))
551 // Remove old pre-tool binaries.
552 for _, old := range oldtool {
553 xremove(pathf("%s/bin/%s", goroot, old))
556 // Special release-specific setup.
558 // Make sure release-excluded things are excluded.
559 for _, dir := range unreleased {
560 if p := pathf("%s/%s", goroot, dir); isdir(p) {
561 fatalf("%s should not exist in release build", p)
571 // mustLinkExternal is a copy of internal/platform.MustLinkExternal,
572 // duplicated here to avoid version skew in the MustLinkExternal function
573 // during bootstrapping.
574 func mustLinkExternal(goos, goarch string, cgoEnabled bool) bool {
578 "mips", "mipsle", "mips64", "mips64le",
580 // Internally linking cgo is incomplete on some architectures.
581 // https://golang.org/issue/14449
584 if goos == "windows" {
585 // windows/arm64 internal linking is not implemented.
589 // Big Endian PPC64 cgo internal linking is not implemented for aix or linux.
597 // It seems that on Dragonfly thread local storage is
598 // set up by the dynamic linker, so internal cgo linking
599 // doesn't work. Test case is "go test runtime/cgo".
606 if goarch != "arm64" {
610 if goarch == "arm64" {
617 // deptab lists changes to the default dependencies for a given prefix.
618 // deps ending in /* read the whole directory; deps beginning with -
619 // exclude files with that prefix.
620 // Note that this table applies only to the build of cmd/go,
621 // after the main compiler bootstrap.
622 // Files listed here should also be listed in ../distpack/pack.go's srcArch.Remove list.
623 var deptab = []struct {
624 prefix string // prefix of target
625 dep []string // dependency tweaks for targets with that prefix
627 {"cmd/go/internal/cfg", []string{
631 {"runtime/internal/sys", []string{
634 {"go/build", []string{
637 {"time/tzdata", []string{
642 // depsuffix records the allowed suffixes for source files.
643 var depsuffix = []string{
648 // gentab records how to generate some trivial files.
649 var gentab = []struct {
651 gen func(string, string)
653 {"zdefaultcc.go", mkzdefaultcc},
654 {"zosarch.go", mkzosarch},
655 {"zversion.go", mkzversion},
657 {"zzipdata.go", mktzdata},
659 // not generated anymore, but delete the file if we see it
667 // installed maps from a dir name (as given to install) to a chan
668 // closed when the dir's package is installed.
669 var installed = make(map[string]chan struct{})
670 var installedMu sync.Mutex
672 func install(dir string) {
676 func startInstall(dir string) chan struct{} {
680 ch = make(chan struct{})
682 go runInstall(dir, ch)
688 // runInstall installs the library, package, or binary associated with dir,
689 // which is relative to $GOROOT/src.
690 func runInstall(pkg string, ch chan struct{}) {
691 if pkg == "net" || pkg == "os/user" || pkg == "crypto/x509" {
692 fatalf("go_bootstrap cannot depend on cgo package %s", pkg)
702 if goos != gohostos || goarch != gohostarch {
703 errprintf("%s (%s/%s)\n", pkg, goos, goarch)
705 errprintf("%s\n", pkg)
709 workdir := pathf("%s/%s", workdir, pkg)
714 for _, name := range clean {
719 // dir = full path to pkg.
720 dir := pathf("%s/src/%s", goroot, pkg)
721 name := filepath.Base(dir)
723 // ispkg predicts whether the package should be linked as a binary, based
724 // on the name. There should be no "main" packages in vendor, since
725 // 'go mod vendor' will only copy imported packages there.
726 ispkg := !strings.HasPrefix(pkg, "cmd/") || strings.Contains(pkg, "/internal/") || strings.Contains(pkg, "/vendor/")
728 // Start final link command line.
729 // Note: code below knows that link.p[targ] is the target.
736 // Go library (package).
738 link = []string{"pack", packagefile(pkg)}
740 xmkdirall(filepath.Dir(link[targ]))
745 elem = "go_bootstrap"
747 link = []string{pathf("%s/link", tooldir)}
748 if goos == "android" {
749 link = append(link, "-buildmode=pie")
752 link = append(link, goldflags)
754 link = append(link, "-extld="+compilerEnvLookup("CC", defaultcc, goos, goarch))
755 link = append(link, "-L="+pathf("%s/pkg/obj/go-bootstrap/%s_%s", goroot, goos, goarch))
756 link = append(link, "-o", pathf("%s/%s%s", tooldir, elem, exe))
759 ttarg := mtime(link[targ])
761 // Gather files that are sources for this target.
762 // Everything in that directory, and any target-specific
764 files := xreaddir(dir)
766 // Remove files beginning with . or _,
767 // which are likely to be editor temporary files.
768 // This is the same heuristic build.ScanDir uses.
769 // There do exist real C files beginning with _,
770 // so limit that check to just Go files.
771 files = filter(files, func(p string) bool {
772 return !strings.HasPrefix(p, ".") && (!strings.HasPrefix(p, "_") || !strings.HasSuffix(p, ".go"))
775 for _, dt := range deptab {
776 if pkg == dt.prefix || strings.HasSuffix(dt.prefix, "/") && strings.HasPrefix(pkg, dt.prefix) {
777 for _, p := range dt.dep {
779 files = append(files, p)
785 // Convert to absolute paths.
786 for i, p := range files {
787 if !filepath.IsAbs(p) {
788 files[i] = pathf("%s/%s", dir, p)
792 // Is the target up-to-date?
793 var gofiles, sfiles, missing []string
795 files = filter(files, func(p string) bool {
796 for _, suf := range depsuffix {
797 if strings.HasSuffix(p, suf) {
804 if !t.IsZero() && !strings.HasSuffix(p, ".a") && !shouldbuild(p, pkg) {
807 if strings.HasSuffix(p, ".go") {
808 gofiles = append(gofiles, p)
809 } else if strings.HasSuffix(p, ".s") {
810 sfiles = append(sfiles, p)
816 missing = append(missing, p)
821 // If there are no files to compile, we're done.
830 // For package runtime, copy some files into the work space.
831 if pkg == "runtime" {
832 xmkdirall(pathf("%s/pkg/include", goroot))
833 // For use by assembly and C files.
834 copyfile(pathf("%s/pkg/include/textflag.h", goroot),
835 pathf("%s/src/runtime/textflag.h", goroot), 0)
836 copyfile(pathf("%s/pkg/include/funcdata.h", goroot),
837 pathf("%s/src/runtime/funcdata.h", goroot), 0)
838 copyfile(pathf("%s/pkg/include/asm_ppc64x.h", goroot),
839 pathf("%s/src/runtime/asm_ppc64x.h", goroot), 0)
840 copyfile(pathf("%s/pkg/include/asm_amd64.h", goroot),
841 pathf("%s/src/runtime/asm_amd64.h", goroot), 0)
844 // Generate any missing files; regenerate existing ones.
845 for _, p := range files {
846 elem := filepath.Base(p)
847 for _, gt := range gentab {
851 if strings.HasPrefix(elem, gt.nameprefix) {
853 errprintf("generate %s\n", p)
856 // Do not add generated file to clean list.
857 // In runtime, we want to be able to
858 // build the package with the go tool,
859 // and it assumes these generated files already
860 // exist (it does not know how to build them).
861 // The 'clean' command can remove
862 // the generated files.
866 // Did not rebuild p.
867 if find(p, missing) >= 0 {
868 fatalf("missing file %s", p)
873 // Resolve imported packages to actual package paths.
874 // Make sure they're installed.
875 importMap := make(map[string]string)
876 for _, p := range gofiles {
877 for _, imp := range readimports(p) {
879 fatalf("%s imports C", p)
881 importMap[imp] = resolveVendor(imp, dir)
884 sortedImports := make([]string, 0, len(importMap))
885 for imp := range importMap {
886 sortedImports = append(sortedImports, imp)
888 sort.Strings(sortedImports)
890 for _, dep := range importMap {
892 fatalf("%s imports C", pkg)
896 for _, dep := range importMap {
900 if goos != gohostos || goarch != gohostarch {
901 // We've generated the right files; the go command can do the build.
903 errprintf("skip build for cross-compile %s\n", pkg)
909 pathf("%s/asm", tooldir),
911 "-I", pathf("%s/pkg/include", goroot),
912 "-D", "GOOS_" + goos,
913 "-D", "GOARCH_" + goarch,
914 "-D", "GOOS_GOARCH_" + goos + "_" + goarch,
917 if goarch == "mips" || goarch == "mipsle" {
918 // Define GOMIPS_value from gomips.
919 asmArgs = append(asmArgs, "-D", "GOMIPS_"+gomips)
921 if goarch == "mips64" || goarch == "mips64le" {
922 // Define GOMIPS64_value from gomips64.
923 asmArgs = append(asmArgs, "-D", "GOMIPS64_"+gomips64)
925 if goarch == "ppc64" || goarch == "ppc64le" {
926 // We treat each powerpc version as a superset of functionality.
929 asmArgs = append(asmArgs, "-D", "GOPPC64_power10")
932 asmArgs = append(asmArgs, "-D", "GOPPC64_power9")
934 default: // This should always be power8.
935 asmArgs = append(asmArgs, "-D", "GOPPC64_power8")
938 goasmh := pathf("%s/go_asm.h", workdir)
939 if IsRuntimePackagePath(pkg) {
940 asmArgs = append(asmArgs, "-compiling-runtime")
943 // Collect symabis from assembly code.
946 symabis = pathf("%s/symabis", workdir)
947 var wg sync.WaitGroup
948 asmabis := append(asmArgs[:len(asmArgs):len(asmArgs)], "-gensymabis", "-o", symabis)
949 asmabis = append(asmabis, sfiles...)
950 if err := os.WriteFile(goasmh, nil, 0666); err != nil {
951 fatalf("cannot write empty go_asm.h: %s", err)
953 bgrun(&wg, dir, asmabis...)
957 // Build an importcfg file for the compiler.
958 buf := &bytes.Buffer{}
959 for _, imp := range sortedImports {
963 dep := importMap[imp]
965 fmt.Fprintf(buf, "importmap %s=%s\n", imp, dep)
967 fmt.Fprintf(buf, "packagefile %s=%s\n", dep, packagefile(dep))
969 importcfg := pathf("%s/importcfg", workdir)
970 if err := os.WriteFile(importcfg, buf.Bytes(), 0666); err != nil {
971 fatalf("cannot write importcfg file: %v", err)
975 // The next loop will compile individual non-Go files.
976 // Hand the Go files to the compiler en masse.
977 // For packages containing assembly, this writes go_asm.h, which
978 // the assembly files will need.
980 if strings.HasPrefix(pkg, "cmd/") && strings.Count(pkg, "/") == 1 {
983 b := pathf("%s/_go_.a", workdir)
984 clean = append(clean, b)
986 link = append(link, b)
992 compile := []string{pathf("%s/compile", tooldir), "-std", "-pack", "-o", b, "-p", pkgName, "-importcfg", importcfg}
994 compile = append(compile, strings.Fields(gogcflags)...)
996 if pkg == "runtime" {
997 compile = append(compile, "-+")
1000 compile = append(compile, "-asmhdr", goasmh)
1003 compile = append(compile, "-symabis", symabis)
1005 if goos == "android" {
1006 compile = append(compile, "-shared")
1009 compile = append(compile, gofiles...)
1010 var wg sync.WaitGroup
1011 // We use bgrun and immediately wait for it instead of calling run() synchronously.
1012 // This executes all jobs through the bgwork channel and allows the process
1013 // to exit cleanly in case an error occurs.
1014 bgrun(&wg, dir, compile...)
1017 // Compile the files.
1018 for _, p := range sfiles {
1019 // Assembly file for a Go package.
1020 compile := asmArgs[:len(asmArgs):len(asmArgs)]
1023 b := pathf("%s/%s", workdir, filepath.Base(p))
1025 // Change the last character of the output file (which was c or s).
1026 b = b[:len(b)-1] + "o"
1027 compile = append(compile, "-o", b, p)
1028 bgrun(&wg, dir, compile...)
1030 link = append(link, b)
1032 clean = append(clean, b)
1039 dopack(link[targ], archive, link[targ+1:])
1043 // Remove target before writing it.
1045 bgrun(&wg, "", link...)
1049 // packagefile returns the path to a compiled .a file for the given package
1050 // path. Paths may need to be resolved with resolveVendor first.
1051 func packagefile(pkg string) string {
1052 return pathf("%s/pkg/obj/go-bootstrap/%s_%s/%s.a", goroot, goos, goarch, pkg)
1055 // unixOS is the set of GOOS values matched by the "unix" build tag.
1056 // This is the same list as in go/build/syslist.go and
1057 // cmd/go/internal/imports/build.go.
1058 var unixOS = map[string]bool{
1073 // matchtag reports whether the tag matches this build.
1074 func matchtag(tag string) bool {
1076 case "gc", "cmd_go_bootstrap", "go1.1":
1079 return goos == "linux" || goos == "android"
1081 return goos == "solaris" || goos == "illumos"
1083 return goos == "darwin" || goos == "ios"
1093 // shouldbuild reports whether we should build this file.
1094 // It applies the same rules that are used with context tags
1095 // in package go/build, except it's less picky about the order
1096 // of GOOS and GOARCH.
1097 // We also allow the special tag cmd_go_bootstrap.
1098 // See ../go/bootstrap.go and package go/build.
1099 func shouldbuild(file, pkg string) bool {
1100 // Check file name for GOOS or GOARCH.
1101 name := filepath.Base(file)
1102 excluded := func(list []string, ok string) bool {
1103 for _, x := range list {
1104 if x == ok || (ok == "android" && x == "linux") || (ok == "illumos" && x == "solaris") || (ok == "ios" && x == "darwin") {
1107 i := strings.Index(name, x)
1108 if i <= 0 || name[i-1] != '_' {
1112 if i == len(name) || name[i] == '.' || name[i] == '_' {
1118 if excluded(okgoos, goos) || excluded(okgoarch, goarch) {
1123 if strings.Contains(name, "_test") {
1127 // Check file contents for //go:build lines.
1128 for _, p := range strings.Split(readfile(file), "\n") {
1129 p = strings.TrimSpace(p)
1134 i := strings.Index(code, "//")
1136 code = strings.TrimSpace(code[:i])
1138 if code == "package documentation" {
1141 if code == "package main" && pkg != "cmd/go" && pkg != "cmd/cgo" {
1144 if !strings.HasPrefix(p, "//") {
1147 if strings.HasPrefix(p, "//go:build ") {
1148 matched, err := matchexpr(p[len("//go:build "):])
1150 errprintf("%s: %v", file, err)
1159 // copyfile copies the file src to dst, via memory (so only good for small files).
1160 func copyfile(dst, src string, flag int) {
1162 errprintf("cp %s %s\n", src, dst)
1164 writefile(readfile(src), dst, flag)
1167 // dopack copies the package src to dst,
1168 // appending the files listed in extra.
1169 // The archive format is the traditional Unix ar format.
1170 func dopack(dst, src string, extra []string) {
1171 bdst := bytes.NewBufferString(readfile(src))
1172 for _, file := range extra {
1174 // find last path element for archive member name
1175 i := strings.LastIndex(file, "/") + 1
1176 j := strings.LastIndex(file, `\`) + 1
1180 fmt.Fprintf(bdst, "%-16.16s%-12d%-6d%-6d%-8o%-10d`\n", file[i:], 0, 0, 0, 0644, len(b))
1186 writefile(bdst.String(), dst, 0)
1189 var runtimegen = []string{
1194 // cleanlist is a list of packages with generated files and commands.
1195 var cleanlist = []string{
1196 "runtime/internal/sys",
1198 "cmd/go/internal/cfg",
1203 for _, name := range cleanlist {
1204 path := pathf("%s/src/%s", goroot, name)
1205 // Remove generated files.
1206 for _, elem := range xreaddir(path) {
1207 for _, gt := range gentab {
1208 if strings.HasPrefix(elem, gt.nameprefix) {
1209 xremove(pathf("%s/%s", path, elem))
1213 // Remove generated binary named for directory.
1214 if strings.HasPrefix(name, "cmd/") {
1215 xremove(pathf("%s/%s", path, name[4:]))
1219 // remove runtimegen files.
1220 path := pathf("%s/src/runtime", goroot)
1221 for _, elem := range runtimegen {
1222 xremove(pathf("%s/%s", path, elem))
1226 // Remove object tree.
1227 xremoveall(pathf("%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch))
1229 // Remove installed packages and tools.
1230 xremoveall(pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch))
1231 xremoveall(pathf("%s/pkg/%s_%s", goroot, goos, goarch))
1232 xremoveall(pathf("%s/pkg/%s_%s_race", goroot, gohostos, gohostarch))
1233 xremoveall(pathf("%s/pkg/%s_%s_race", goroot, goos, goarch))
1236 // Remove cached version info.
1237 xremove(pathf("%s/VERSION.cache", goroot))
1239 // Remove distribution packages.
1240 xremoveall(pathf("%s/pkg/distpack", goroot))
1245 * command implementations
1248 // The env command prints the default environment.
1250 path := flag.Bool("p", false, "emit updated PATH")
1251 plan9 := flag.Bool("9", gohostos == "plan9", "emit plan 9 syntax")
1252 windows := flag.Bool("w", gohostos == "windows", "emit windows syntax")
1255 format := "%s=\"%s\";\n" // Include ; to separate variables when 'dist env' output is used with eval.
1258 format = "%s='%s'\n"
1260 format = "set %s=%s\r\n"
1263 xprintf(format, "GO111MODULE", "")
1264 xprintf(format, "GOARCH", goarch)
1265 xprintf(format, "GOBIN", gorootBin)
1266 xprintf(format, "GODEBUG", os.Getenv("GODEBUG"))
1267 xprintf(format, "GOENV", "off")
1268 xprintf(format, "GOFLAGS", "")
1269 xprintf(format, "GOHOSTARCH", gohostarch)
1270 xprintf(format, "GOHOSTOS", gohostos)
1271 xprintf(format, "GOOS", goos)
1272 xprintf(format, "GOPROXY", os.Getenv("GOPROXY"))
1273 xprintf(format, "GOROOT", goroot)
1274 xprintf(format, "GOTMPDIR", os.Getenv("GOTMPDIR"))
1275 xprintf(format, "GOTOOLDIR", tooldir)
1276 if goarch == "arm" {
1277 xprintf(format, "GOARM", goarm)
1279 if goarch == "386" {
1280 xprintf(format, "GO386", go386)
1282 if goarch == "amd64" {
1283 xprintf(format, "GOAMD64", goamd64)
1285 if goarch == "mips" || goarch == "mipsle" {
1286 xprintf(format, "GOMIPS", gomips)
1288 if goarch == "mips64" || goarch == "mips64le" {
1289 xprintf(format, "GOMIPS64", gomips64)
1291 if goarch == "ppc64" || goarch == "ppc64le" {
1292 xprintf(format, "GOPPC64", goppc64)
1294 xprintf(format, "GOWORK", "off")
1298 if gohostos == "windows" {
1301 xprintf(format, "PATH", fmt.Sprintf("%s%s%s", gorootBin, sep, os.Getenv("PATH")))
1303 // Also include $DIST_UNMODIFIED_PATH with the original $PATH
1304 // for the internal needs of "dist banner", along with export
1305 // so that it reaches the dist process. See its comment below.
1306 var exportFormat string
1307 if !*windows && !*plan9 {
1308 exportFormat = "export " + format
1310 exportFormat = format
1312 xprintf(exportFormat, "DIST_UNMODIFIED_PATH", os.Getenv("PATH"))
1317 timeLogEnabled = os.Getenv("GOBUILDTIMELOGFILE") != ""
1318 timeLogMu sync.Mutex
1319 timeLogFile *os.File
1320 timeLogStart time.Time
1323 func timelog(op, name string) {
1324 if !timeLogEnabled {
1328 defer timeLogMu.Unlock()
1329 if timeLogFile == nil {
1330 f, err := os.OpenFile(os.Getenv("GOBUILDTIMELOGFILE"), os.O_RDWR|os.O_APPEND, 0666)
1334 buf := make([]byte, 100)
1336 s := string(buf[:n])
1337 if i := strings.Index(s, "\n"); i >= 0 {
1340 i := strings.Index(s, " start")
1342 log.Fatalf("time log %s does not begin with start line", os.Getenv("GOBUILDTIMELOGFILE"))
1344 t, err := time.Parse(time.UnixDate, s[:i])
1346 log.Fatalf("cannot parse time log line %q: %v", s, err)
1352 fmt.Fprintf(timeLogFile, "%s %+.1fs %s %s\n", t.Format(time.UnixDate), t.Sub(timeLogStart).Seconds(), op, name)
1355 // toolenv returns the environment to use when building commands in cmd.
1357 // This is a function instead of a variable because the exact toolenv depends
1358 // on the GOOS and GOARCH, and (at least for now) those are modified in place
1359 // to switch between the host and target configurations when cross-compiling.
1360 func toolenv() []string {
1362 if !mustLinkExternal(goos, goarch, false) {
1363 // Unless the platform requires external linking,
1364 // we disable cgo to get static binaries for cmd/go and cmd/pprof,
1365 // so that they work on systems without the same dynamic libraries
1366 // as the original build system.
1367 env = append(env, "CGO_ENABLED=0")
1369 if isRelease || os.Getenv("GO_BUILDER_NAME") != "" {
1370 // Add -trimpath for reproducible builds of releases.
1371 // Include builders so that -trimpath is well-tested ahead of releases.
1372 // Do not include local development, so that people working in the
1373 // main branch for day-to-day work on the Go toolchain itself can
1374 // still have full paths for stack traces for compiler crashes and the like.
1375 env = append(env, "GOFLAGS=-trimpath -ldflags=-w -gcflags=cmd/...=-dwarf=false")
1380 var toolchain = []string{"cmd/asm", "cmd/cgo", "cmd/compile", "cmd/link"}
1382 // The bootstrap command runs a build from scratch,
1383 // stopping at having installed the go_bootstrap command.
1385 // WARNING: This command runs after cmd/dist is built with the Go bootstrap toolchain.
1386 // It rebuilds and installs cmd/dist with the new toolchain, so other
1387 // commands (like "go tool dist test" in run.bash) can rely on bug fixes
1388 // made since the Go bootstrap version, but this function cannot.
1389 func cmdbootstrap() {
1390 timelog("start", "dist bootstrap")
1391 defer timelog("end", "dist bootstrap")
1393 var debug, distpack, force, noBanner, noClean bool
1394 flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all")
1395 flag.BoolVar(&debug, "d", debug, "enable debugging of bootstrap process")
1396 flag.BoolVar(&distpack, "distpack", distpack, "write distribution files to pkg/distpack")
1397 flag.BoolVar(&force, "force", force, "build even if the port is marked as broken")
1398 flag.BoolVar(&noBanner, "no-banner", noBanner, "do not print banner")
1399 flag.BoolVar(&noClean, "no-clean", noClean, "print deprecation warning")
1404 xprintf("warning: --no-clean is deprecated and has no effect; use 'go install std cmd' instead\n")
1407 // Don't build broken ports by default.
1408 if broken[goos+"/"+goarch] && !force {
1409 fatalf("build stopped because the port %s/%s is marked as broken\n\n"+
1410 "Use the -force flag to build anyway.\n", goos, goarch)
1413 // Set GOPATH to an internal directory. We shouldn't actually
1414 // need to store files here, since the toolchain won't
1415 // depend on modules outside of vendor directories, but if
1416 // GOPATH points somewhere else (e.g., to GOROOT), the
1417 // go tool may complain.
1418 os.Setenv("GOPATH", pathf("%s/pkg/obj/gopath", goroot))
1420 // Use a build cache separate from the default user one.
1421 // Also one that will be wiped out during startup, so that
1422 // make.bash really does start from a clean slate.
1423 oldgocache = os.Getenv("GOCACHE")
1424 os.Setenv("GOCACHE", pathf("%s/pkg/obj/go-build", goroot))
1426 // Disable GOEXPERIMENT when building toolchain1 and
1427 // go_bootstrap. We don't need any experiments for the
1428 // bootstrap toolchain, and this lets us avoid duplicating the
1429 // GOEXPERIMENT-related build logic from cmd/go here. If the
1430 // bootstrap toolchain is < Go 1.17, it will ignore this
1431 // anyway since GOEXPERIMENT is baked in; otherwise it will
1432 // pick it up from the environment we set here. Once we're
1433 // using toolchain1 with dist as the build system, we need to
1434 // override this to keep the experiments assumed by the
1435 // toolchain and by dist consistent. Once go_bootstrap takes
1436 // over the build process, we'll set this back to the original
1438 os.Setenv("GOEXPERIMENT", "none")
1441 // cmd/buildid is used in debug mode.
1442 toolchain = append(toolchain, "cmd/buildid")
1445 if isdir(pathf("%s/src/pkg", goroot)) {
1447 "The Go package sources have moved to $GOROOT/src.\n"+
1448 "*** %s still exists. ***\n"+
1449 "It probably contains stale files that may confuse the build.\n"+
1450 "Please (check what's there and) remove it and try again.\n"+
1451 "See https://golang.org/s/go14nopkg\n",
1452 pathf("%s/src/pkg", goroot))
1461 timelog("build", "toolchain1")
1463 bootstrapBuildTools()
1465 // Remember old content of $GOROOT/bin for comparison below.
1466 oldBinFiles, err := filepath.Glob(pathf("%s/bin/*", goroot))
1468 fatalf("glob: %v", err)
1471 // For the main bootstrap, building for host os/arch.
1476 os.Setenv("GOHOSTARCH", gohostarch)
1477 os.Setenv("GOHOSTOS", gohostos)
1478 os.Setenv("GOARCH", goarch)
1479 os.Setenv("GOOS", goos)
1481 timelog("build", "go_bootstrap")
1482 xprintf("Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.\n")
1483 install("runtime") // dependency not visible in sources; also sets up textflag.h
1484 install("time/tzdata") // no dependency in sources; creates generated file
1490 gogcflags = os.Getenv("GO_GCFLAGS") // we were using $BOOT_GO_GCFLAGS until now
1492 goldflags = os.Getenv("GO_LDFLAGS") // we were using $BOOT_GO_LDFLAGS until now
1493 goBootstrap := pathf("%s/go_bootstrap", tooldir)
1495 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1496 copyfile(pathf("%s/compile1", tooldir), pathf("%s/compile", tooldir), writeExec)
1499 // To recap, so far we have built the new toolchain
1500 // (cmd/asm, cmd/cgo, cmd/compile, cmd/link)
1501 // using the Go bootstrap toolchain and go command.
1502 // Then we built the new go command (as go_bootstrap)
1503 // using the new toolchain and our own build logic (above).
1505 // toolchain1 = mk(new toolchain, go1.17 toolchain, go1.17 cmd/go)
1506 // go_bootstrap = mk(new cmd/go, toolchain1, cmd/dist)
1508 // The toolchain1 we built earlier is built from the new sources,
1509 // but because it was built using cmd/go it has no build IDs.
1510 // The eventually installed toolchain needs build IDs, so we need
1511 // to do another round:
1513 // toolchain2 = mk(new toolchain, toolchain1, go_bootstrap)
1515 timelog("build", "toolchain2")
1519 xprintf("Building Go toolchain2 using go_bootstrap and Go toolchain1.\n")
1520 os.Setenv("CC", compilerEnvLookup("CC", defaultcc, goos, goarch))
1521 // Now that cmd/go is in charge of the build process, enable GOEXPERIMENT.
1522 os.Setenv("GOEXPERIMENT", goexperiment)
1523 goInstall(toolenv(), goBootstrap, toolchain...)
1525 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1526 copyfile(pathf("%s/compile2", tooldir), pathf("%s/compile", tooldir), writeExec)
1529 // Toolchain2 should be semantically equivalent to toolchain1,
1530 // but it was built using the newly built compiler instead of the Go bootstrap compiler,
1531 // so it should at the least run faster. Also, toolchain1 had no build IDs
1532 // in the binaries, while toolchain2 does. In non-release builds, the
1533 // toolchain's build IDs feed into constructing the build IDs of built targets,
1534 // so in non-release builds, everything now looks out-of-date due to
1535 // toolchain2 having build IDs - that is, due to the go command seeing
1536 // that there are new compilers. In release builds, the toolchain's reported
1537 // version is used in place of the build ID, and the go command does not
1538 // see that change from toolchain1 to toolchain2, so in release builds,
1539 // nothing looks out of date.
1540 // To keep the behavior the same in both non-release and release builds,
1541 // we force-install everything here.
1543 // toolchain3 = mk(new toolchain, toolchain2, go_bootstrap)
1545 timelog("build", "toolchain3")
1549 xprintf("Building Go toolchain3 using go_bootstrap and Go toolchain2.\n")
1550 goInstall(toolenv(), goBootstrap, append([]string{"-a"}, toolchain...)...)
1552 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1553 copyfile(pathf("%s/compile3", tooldir), pathf("%s/compile", tooldir), writeExec)
1556 // Now that toolchain3 has been built from scratch, its compiler and linker
1557 // should have accurate build IDs suitable for caching.
1558 // Now prime the build cache with the rest of the standard library for
1559 // testing, and so that the user can run 'go install std cmd' to quickly
1560 // iterate on local changes without waiting for a full rebuild.
1561 os.Setenv("GOCACHE", oldgocache)
1563 if goos == oldgoos && goarch == oldgoarch {
1564 // Common case - not setting up for cross-compilation.
1565 timelog("build", "toolchain")
1569 xprintf("Building packages and commands for %s/%s.\n", goos, goarch)
1571 // GOOS/GOARCH does not match GOHOSTOS/GOHOSTARCH.
1572 // Finish GOHOSTOS/GOHOSTARCH installation and then
1573 // run GOOS/GOARCH installation.
1574 timelog("build", "host toolchain")
1578 xprintf("Building commands for host, %s/%s.\n", goos, goarch)
1579 goInstall(toolenv(), goBootstrap, "cmd")
1580 checkNotStale(toolenv(), goBootstrap, "cmd")
1581 checkNotStale(toolenv(), gorootBinGo, "cmd")
1583 timelog("build", "target toolchain")
1589 os.Setenv("GOOS", goos)
1590 os.Setenv("GOARCH", goarch)
1591 os.Setenv("CC", compilerEnvLookup("CC", defaultcc, goos, goarch))
1592 xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch)
1594 goInstall(nil, goBootstrap, "std")
1595 goInstall(toolenv(), goBootstrap, "cmd")
1596 checkNotStale(toolenv(), goBootstrap, toolchain...)
1597 checkNotStale(nil, goBootstrap, "std")
1598 checkNotStale(toolenv(), goBootstrap, "cmd")
1599 checkNotStale(nil, gorootBinGo, "std")
1600 checkNotStale(toolenv(), gorootBinGo, "cmd")
1602 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1603 checkNotStale(toolenv(), goBootstrap, toolchain...)
1604 copyfile(pathf("%s/compile4", tooldir), pathf("%s/compile", tooldir), writeExec)
1607 // Check that there are no new files in $GOROOT/bin other than
1608 // go and gofmt and $GOOS_$GOARCH (target bin when cross-compiling).
1609 binFiles, err := filepath.Glob(pathf("%s/bin/*", goroot))
1611 fatalf("glob: %v", err)
1614 ok := map[string]bool{}
1615 for _, f := range oldBinFiles {
1618 for _, f := range binFiles {
1619 elem := strings.TrimSuffix(filepath.Base(f), ".exe")
1620 if !ok[f] && elem != "go" && elem != "gofmt" && elem != goos+"_"+goarch {
1621 fatalf("unexpected new file in $GOROOT/bin: %s", elem)
1625 // Remove go_bootstrap now that we're done.
1626 xremove(pathf("%s/go_bootstrap"+exe, tooldir))
1628 if goos == "android" {
1629 // Make sure the exec wrapper will sync a fresh $GOROOT to the device.
1630 xremove(pathf("%s/go_android_exec-adb-sync-status", os.TempDir()))
1633 if wrapperPath := wrapperPathFor(goos, goarch); wrapperPath != "" {
1634 oldcc := os.Getenv("CC")
1635 os.Setenv("GOOS", gohostos)
1636 os.Setenv("GOARCH", gohostarch)
1637 os.Setenv("CC", compilerEnvLookup("CC", defaultcc, gohostos, gohostarch))
1638 goCmd(nil, gorootBinGo, "build", "-o", pathf("%s/go_%s_%s_exec%s", gorootBin, goos, goarch, exe), wrapperPath)
1639 // Restore environment.
1640 // TODO(elias.naur): support environment variables in goCmd?
1641 os.Setenv("GOOS", goos)
1642 os.Setenv("GOARCH", goarch)
1643 os.Setenv("CC", oldcc)
1647 xprintf("Packaging archives for %s/%s.\n", goos, goarch)
1648 run("", ShowOutput|CheckExit, pathf("%s/distpack", tooldir))
1651 // Print trailing banner unless instructed otherwise.
1657 func wrapperPathFor(goos, goarch string) string {
1659 case goos == "android":
1660 if gohostos != "android" {
1661 return pathf("%s/misc/android/go_android_exec.go", goroot)
1664 if gohostos != "ios" {
1665 return pathf("%s/misc/ios/go_ios_exec.go", goroot)
1671 func goInstall(env []string, goBinary string, args ...string) {
1672 goCmd(env, goBinary, "install", args...)
1675 func appendCompilerFlags(args []string) []string {
1676 if gogcflags != "" {
1677 args = append(args, "-gcflags=all="+gogcflags)
1679 if goldflags != "" {
1680 args = append(args, "-ldflags=all="+goldflags)
1685 func goCmd(env []string, goBinary string, cmd string, args ...string) {
1686 goCmd := []string{goBinary, cmd}
1688 goCmd = append(goCmd, "-tags=noopt")
1690 goCmd = appendCompilerFlags(goCmd)
1692 goCmd = append(goCmd, "-v")
1695 // Force only one process at a time on vx32 emulation.
1696 if gohostos == "plan9" && os.Getenv("sysname") == "vx32" {
1697 goCmd = append(goCmd, "-p=1")
1700 runEnv(workdir, ShowOutput|CheckExit, env, append(goCmd, args...)...)
1703 func checkNotStale(env []string, goBinary string, targets ...string) {
1704 goCmd := []string{goBinary, "list"}
1706 goCmd = append(goCmd, "-tags=noopt")
1708 goCmd = appendCompilerFlags(goCmd)
1709 goCmd = append(goCmd, "-f={{if .Stale}}\tSTALE {{.ImportPath}}: {{.StaleReason}}{{end}}")
1711 out := runEnv(workdir, CheckExit, env, append(goCmd, targets...)...)
1712 if strings.Contains(out, "\tSTALE ") {
1713 os.Setenv("GODEBUG", "gocachehash=1")
1714 for _, target := range []string{"runtime/internal/sys", "cmd/dist", "cmd/link"} {
1715 if strings.Contains(out, "STALE "+target) {
1716 run(workdir, ShowOutput|CheckExit, goBinary, "list", "-f={{.ImportPath}} {{.Stale}}", target)
1720 fatalf("unexpected stale targets reported by %s list -gcflags=\"%s\" -ldflags=\"%s\" for %v (consider rerunning with GOMAXPROCS=1 GODEBUG=gocachehash=1):\n%s", goBinary, gogcflags, goldflags, targets, out)
1724 // Cannot use go/build directly because cmd/dist for a new release
1725 // builds against an old release's go/build, which may be out of sync.
1726 // To reduce duplication, we generate the list for go/build from this.
1728 // We list all supported platforms in this list, so that this is the
1729 // single point of truth for supported platforms. This list is used
1730 // by 'go tool dist list'.
1731 var cgoEnabled = map[string]bool{
1733 "darwin/amd64": true,
1734 "darwin/arm64": true,
1735 "dragonfly/amd64": true,
1736 "freebsd/386": true,
1737 "freebsd/amd64": true,
1738 "freebsd/arm": true,
1739 "freebsd/arm64": true,
1740 "freebsd/riscv64": true,
1741 "illumos/amd64": true,
1743 "linux/amd64": true,
1745 "linux/arm64": true,
1746 "linux/loong64": true,
1747 "linux/ppc64": false,
1748 "linux/ppc64le": true,
1750 "linux/mipsle": true,
1751 "linux/mips64": true,
1752 "linux/mips64le": true,
1753 "linux/riscv64": true,
1754 "linux/s390x": true,
1755 "linux/sparc64": true,
1756 "android/386": true,
1757 "android/amd64": true,
1758 "android/arm": true,
1759 "android/arm64": true,
1763 "wasip1/wasm": false,
1765 "netbsd/amd64": true,
1767 "netbsd/arm64": true,
1768 "openbsd/386": true,
1769 "openbsd/amd64": true,
1770 "openbsd/arm": true,
1771 "openbsd/arm64": true,
1772 "openbsd/mips64": true,
1773 "openbsd/ppc64": false,
1775 "plan9/amd64": false,
1777 "solaris/amd64": true,
1778 "windows/386": true,
1779 "windows/amd64": true,
1780 "windows/arm": false,
1781 "windows/arm64": true,
1784 // List of platforms that are marked as broken ports.
1785 // These require -force flag to build, and also
1786 // get filtered out of cgoEnabled for 'dist list'.
1787 // See go.dev/issue/56679.
1788 var broken = map[string]bool{
1789 "linux/sparc64": true, // An incomplete port. See CL 132155.
1790 "openbsd/ppc64": true, // An incomplete port: go.dev/issue/56001.
1791 "openbsd/mips64": true, // Broken: go.dev/issue/58110.
1794 // List of platforms which are first class ports. See go.dev/issue/38874.
1795 var firstClass = map[string]bool{
1796 "darwin/amd64": true,
1797 "darwin/arm64": true,
1799 "linux/amd64": true,
1801 "linux/arm64": true,
1802 "windows/386": true,
1803 "windows/amd64": true,
1806 // We only need CC if cgo is forced on, or if the platform requires external linking.
1807 // Otherwise the go command will automatically disable it.
1808 func needCC() bool {
1809 return os.Getenv("CGO_ENABLED") == "1" || mustLinkExternal(gohostos, gohostarch, false)
1816 cc1 := defaultcc[""]
1819 for _, os := range clangos {
1826 cc, err := quotedSplit(cc1)
1828 fatalf("split CC: %v", err)
1830 var ccHelp = append(cc, "--help")
1832 if output, err := exec.Command(ccHelp[0], ccHelp[1:]...).CombinedOutput(); err != nil {
1834 if len(output) > 0 {
1835 outputHdr = "\nCommand output:\n\n"
1837 fatalf("cannot invoke C compiler %q: %v\n\n"+
1838 "Go needs a system C compiler for use with cgo.\n"+
1839 "To set a C compiler, set CC=the-compiler.\n"+
1840 "To disable cgo, set CGO_ENABLED=0.\n%s%s", cc, err, outputHdr, output)
1844 func defaulttarg() string {
1845 // xgetwd might return a path with symlinks fully resolved, and if
1846 // there happens to be symlinks in goroot, then the hasprefix test
1847 // will never succeed. Instead, we use xrealwd to get a canonical
1848 // goroot/src before the comparison to avoid this problem.
1850 src := pathf("%s/src/", goroot)
1851 real_src := xrealwd(src)
1852 if !strings.HasPrefix(pwd, real_src) {
1853 fatalf("current directory %s is not under %s", pwd, real_src)
1855 pwd = pwd[len(real_src):]
1856 // guard against xrealwd returning the directory without the trailing /
1857 pwd = strings.TrimPrefix(pwd, "/")
1862 // Install installs the list of packages named on the command line.
1866 if flag.NArg() == 0 {
1867 install(defaulttarg())
1870 for _, arg := range flag.Args() {
1875 // Clean deletes temporary objects.
1881 // Banner prints the 'now you've installed Go' banner.
1892 xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot)
1893 xprintf("Installed commands in %s\n", gorootBin)
1895 if !xsamefile(goroot_final, goroot) {
1896 // If the files are to be moved, don't check that gobin
1897 // is on PATH; assume they know what they are doing.
1898 } else if gohostos == "plan9" {
1899 // Check that GOROOT/bin is bound before /bin.
1900 pid := strings.Replace(readfile("#c/pid"), " ", "", -1)
1901 ns := fmt.Sprintf("/proc/%s/ns", pid)
1902 if !strings.Contains(readfile(ns), fmt.Sprintf("bind -b %s /bin", gorootBin)) {
1903 xprintf("*** You need to bind %s before /bin.\n", gorootBin)
1906 // Check that GOROOT/bin appears in $PATH.
1908 if gohostos == "windows" {
1911 path := os.Getenv("PATH")
1912 if p, ok := os.LookupEnv("DIST_UNMODIFIED_PATH"); ok {
1913 // Scripts that modify $PATH and then run dist should also provide
1914 // dist with an unmodified copy of $PATH via $DIST_UNMODIFIED_PATH.
1915 // Use it here when determining if the user still needs to update
1916 // their $PATH. See go.dev/issue/42563.
1919 if !strings.Contains(pathsep+path+pathsep, pathsep+gorootBin+pathsep) {
1920 xprintf("*** You need to add %s to your PATH.\n", gorootBin)
1924 if !xsamefile(goroot_final, goroot) {
1926 "The binaries expect %s to be copied or moved to %s\n",
1927 goroot, goroot_final)
1931 // Version prints the Go version.
1934 xprintf("%s\n", findgoversion())
1937 // cmdlist lists all supported platforms.
1939 jsonFlag := flag.Bool("json", false, "produce JSON output")
1943 for p := range cgoEnabled {
1947 plats = append(plats, p)
1952 for _, p := range plats {
1958 type jsonResult struct {
1964 var results []jsonResult
1965 for _, p := range plats {
1966 fields := strings.Split(p, "/")
1967 results = append(results, jsonResult{
1970 CgoSupported: cgoEnabled[p],
1971 FirstClass: firstClass[p]})
1973 out, err := json.MarshalIndent(results, "", "\t")
1975 fatalf("json marshal error: %v", err)
1977 if _, err := os.Stdout.Write(out); err != nil {
1978 fatalf("write failed: %v", err)
1982 // IsRuntimePackagePath examines 'pkgpath' and returns TRUE if it
1983 // belongs to the collection of "runtime-related" packages, including
1984 // "runtime" itself, "reflect", "syscall", and the
1985 // "runtime/internal/*" packages.
1987 // Keep in sync with cmd/internal/objabi/path.go:IsRuntimePackagePath.
1988 func IsRuntimePackagePath(pkgpath string) bool {
1997 case "internal/bytealg":
2000 rval = strings.HasPrefix(pkgpath, "runtime/internal")
2006 for _, gcflag := range strings.Split(gogcflags, " ") {
2007 if gcflag == "-N" || gcflag == "-l" {