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
50 defaultcc map[string]string
51 defaultcxx map[string]string
52 defaultpkgconfig string
59 vflag int // verbosity
62 // The known architectures.
63 var okgoarch = []string{
81 // The known operating systems.
82 var okgoos = []string{
100 // find reports the first index of p in l[0:n], or else -1.
101 func find(p string, l []string) int {
102 for i, s := range l {
110 // xinit handles initialization of the various global state, like goroot and goarch.
112 b := os.Getenv("GOROOT")
114 fatalf("$GOROOT must be set")
116 goroot = filepath.Clean(b)
117 gorootBin = pathf("%s/bin", goroot)
119 // Don't run just 'go' because the build infrastructure
120 // runs cmd/dist inside go/bin often, and on Windows
121 // it will be found in the current directory and refuse to exec.
122 // All exec calls rewrite "go" into gorootBinGo.
123 gorootBinGo = pathf("%s/bin/go", goroot)
125 b = os.Getenv("GOROOT_FINAL")
131 b = os.Getenv("GOOS")
136 if find(goos, okgoos) < 0 {
137 fatalf("unknown $GOOS %s", goos)
140 b = os.Getenv("GOARM")
146 b = os.Getenv("GO386")
152 b = os.Getenv("GOAMD64")
158 b = os.Getenv("GOMIPS")
164 b = os.Getenv("GOMIPS64")
170 b = os.Getenv("GOPPC64")
176 if p := pathf("%s/src/all.bash", goroot); !isfile(p) {
177 fatalf("$GOROOT is not set correctly or not exported\n"+
179 "\t%s does not exist", goroot, p)
182 b = os.Getenv("GOHOSTARCH")
186 if find(gohostarch, okgoarch) < 0 {
187 fatalf("unknown $GOHOSTARCH %s", gohostarch)
190 b = os.Getenv("GOARCH")
195 if find(goarch, okgoarch) < 0 {
196 fatalf("unknown $GOARCH %s", goarch)
199 b = os.Getenv("GO_EXTLINK_ENABLED")
201 if b != "0" && b != "1" {
202 fatalf("unknown $GO_EXTLINK_ENABLED %s", b)
207 goexperiment = os.Getenv("GOEXPERIMENT")
208 // TODO(mdempsky): Validate known experiments?
210 gogcflags = os.Getenv("BOOT_GO_GCFLAGS")
211 goldflags = os.Getenv("BOOT_GO_LDFLAGS")
213 cc, cxx := "gcc", "g++"
215 cc, cxx = "clang", "clang++"
217 defaultcc = compilerEnv("CC", cc)
218 defaultcxx = compilerEnv("CXX", cxx)
220 b = os.Getenv("PKG_CONFIG")
226 defaultldso = os.Getenv("GO_LDSO")
228 // For tools being invoked but also for os.ExpandEnv.
229 os.Setenv("GO386", go386)
230 os.Setenv("GOAMD64", goamd64)
231 os.Setenv("GOARCH", goarch)
232 os.Setenv("GOARM", goarm)
233 os.Setenv("GOHOSTARCH", gohostarch)
234 os.Setenv("GOHOSTOS", gohostos)
235 os.Setenv("GOOS", goos)
236 os.Setenv("GOMIPS", gomips)
237 os.Setenv("GOMIPS64", gomips64)
238 os.Setenv("GOPPC64", goppc64)
239 os.Setenv("GOROOT", goroot)
240 os.Setenv("GOROOT_FINAL", goroot_final)
242 // Use a build cache separate from the default user one.
243 // Also one that will be wiped out during startup, so that
244 // make.bash really does start from a clean slate.
245 os.Setenv("GOCACHE", pathf("%s/pkg/obj/go-build", goroot))
247 // Set GOBIN to GOROOT/bin. The meaning of GOBIN has drifted over time
248 // (see https://go.dev/issue/3269, https://go.dev/cl/183058,
249 // https://go.dev/issue/31576). Since we want binaries installed by 'dist' to
250 // always go to GOROOT/bin anyway.
251 os.Setenv("GOBIN", gorootBin)
253 // Make the environment more predictable.
254 os.Setenv("LANG", "C")
255 os.Setenv("LANGUAGE", "en_US.UTF8")
256 os.Unsetenv("GO111MODULE")
257 os.Setenv("GOENV", "off")
258 os.Unsetenv("GOFLAGS")
259 os.Setenv("GOWORK", "off")
262 if err := os.WriteFile(pathf("%s/go.mod", workdir), []byte("module bootstrap"), 0666); err != nil {
263 fatalf("cannot write stub go.mod: %s", err)
267 tooldir = pathf("%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch)
270 // compilerEnv returns a map from "goos/goarch" to the
271 // compiler setting to use for that platform.
272 // The entry for key "" covers any goos/goarch not explicitly set in the map.
273 // For example, compilerEnv("CC", "gcc") returns the C compiler settings
274 // read from $CC, defaulting to gcc.
276 // The result is a map because additional environment variables
277 // can be set to change the compiler based on goos/goarch settings.
278 // The following applies to all envNames but CC is assumed to simplify
281 // If no environment variables are set, we use def for all goos/goarch.
282 // $CC, if set, applies to all goos/goarch but is overridden by the following.
283 // $CC_FOR_TARGET, if set, applies to all goos/goarch except gohostos/gohostarch,
284 // but is overridden by the following.
285 // If gohostos=goos and gohostarch=goarch, then $CC_FOR_TARGET applies even for gohostos/gohostarch.
286 // $CC_FOR_goos_goarch, if set, applies only to goos/goarch.
287 func compilerEnv(envName, def string) map[string]string {
288 m := map[string]string{"": def}
290 if env := os.Getenv(envName); env != "" {
293 if env := os.Getenv(envName + "_FOR_TARGET"); env != "" {
294 if gohostos != goos || gohostarch != goarch {
295 m[gohostos+"/"+gohostarch] = m[""]
300 for _, goos := range okgoos {
301 for _, goarch := range okgoarch {
302 if env := os.Getenv(envName + "_FOR_" + goos + "_" + goarch); env != "" {
303 m[goos+"/"+goarch] = env
311 // compilerEnvLookup returns the compiler settings for goos/goarch in map m.
312 func compilerEnvLookup(m map[string]string, goos, goarch string) string {
313 if cc := m[goos+"/"+goarch]; cc != "" {
319 // rmworkdir deletes the work directory.
322 errprintf("rm -rf %s\n", workdir)
327 // Remove trailing spaces.
328 func chomp(s string) string {
329 return strings.TrimRight(s, " \t\r\n")
332 // findgoversion determines the Go version to use in the version string.
333 func findgoversion() string {
334 // The $GOROOT/VERSION file takes priority, for distributions
335 // without the source repo.
336 path := pathf("%s/VERSION", goroot)
338 b := chomp(readfile(path))
339 // Commands such as "dist version > VERSION" will cause
340 // the shell to create an empty VERSION file and set dist's
341 // stdout to its fd. dist in turn looks at VERSION and uses
342 // its content if available, which is empty at this point.
343 // Only use the VERSION file if it is non-empty.
345 // Some builders cross-compile the toolchain on linux-amd64
346 // and then copy the toolchain to the target builder (say, linux-arm)
347 // for use there. But on non-release (devel) branches, the compiler
348 // used on linux-amd64 will be an amd64 binary, and the compiler
349 // shipped to linux-arm will be an arm binary, so they will have different
350 // content IDs (they are binaries for different architectures) and so the
351 // packages compiled by the running-on-amd64 compiler will appear
352 // stale relative to the running-on-arm compiler. Avoid this by setting
353 // the version string to something that doesn't begin with devel.
354 // Then the version string will be used in place of the content ID,
355 // and the packages will look up-to-date.
356 // TODO(rsc): Really the builders could be writing out a better VERSION file instead,
357 // but it is easier to change cmd/dist than to try to make changes to
358 // the builder while Brad is away.
359 if strings.HasPrefix(b, "devel") {
360 if hostType := os.Getenv("META_BUILDLET_HOST_TYPE"); strings.Contains(hostType, "-cross") {
361 fmt.Fprintf(os.Stderr, "warning: changing VERSION from %q to %q\n", b, "builder "+hostType)
362 b = "builder " + hostType
369 // The $GOROOT/VERSION.cache file is a cache to avoid invoking
370 // git every time we run this command. Unlike VERSION, it gets
371 // deleted by the clean command.
372 path = pathf("%s/VERSION.cache", goroot)
374 return chomp(readfile(path))
377 // Show a nicer error message if this isn't a Git repo.
379 fatalf("FAILED: not a Git repo; must put a VERSION file in $GOROOT")
382 // Otherwise, use Git.
384 // Include 1.x base version, hash, and date in the version.
386 // Note that we lightly parse internal/goversion/goversion.go to
387 // obtain the base version. We can't just import the package,
388 // because cmd/dist is built with a bootstrap GOROOT which could
389 // be an entirely different version of Go. We assume
390 // that the file contains "const Version = <Integer>".
391 goversionSource := readfile(pathf("%s/src/internal/goversion/goversion.go", goroot))
392 m := regexp.MustCompile(`(?m)^const Version = (\d+)`).FindStringSubmatch(goversionSource)
394 fatalf("internal/goversion/goversion.go does not contain 'const Version = ...'")
396 version := fmt.Sprintf("devel go1.%s-", m[1])
397 version += chomp(run(goroot, CheckExit, "git", "log", "-n", "1", "--format=format:%h %cd", "HEAD"))
400 writefile(version, path, 0)
405 // isGitRepo reports whether the working directory is inside a Git repository.
406 func isGitRepo() bool {
407 // NB: simply checking the exit code of `git rev-parse --git-dir` would
408 // suffice here, but that requires deviating from the infrastructure
409 // provided by `run`.
410 gitDir := chomp(run(goroot, 0, "git", "rev-parse", "--git-dir"))
411 if !filepath.IsAbs(gitDir) {
412 gitDir = filepath.Join(goroot, gitDir)
418 * Initial tree setup.
421 // The old tools that no longer live in $GOBIN or $GOROOT/bin.
422 var oldtool = []string{
423 "5a", "5c", "5g", "5l",
424 "6a", "6c", "6g", "6l",
425 "8a", "8c", "8g", "8l",
426 "9a", "9c", "9g", "9l",
445 // Unreleased directories (relative to $GOROOT) that should
446 // not be in release branches.
447 var unreleased = []string{
454 // setup sets up the tree for the initial build.
456 // Create bin directory.
457 if p := pathf("%s/bin", goroot); !isdir(p) {
461 // Create package directory.
462 if p := pathf("%s/pkg", goroot); !isdir(p) {
466 goosGoarch := pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch)
468 xremoveall(goosGoarch)
470 xmkdirall(goosGoarch)
472 if files := xreaddir(goosGoarch); len(files) == 0 {
477 if goos != gohostos || goarch != gohostarch {
478 p := pathf("%s/pkg/%s_%s", goroot, goos, goarch)
485 // Create object directory.
486 // We used to use it for C objects.
487 // Now we use it for the build cache, to separate dist's cache
488 // from any other cache the user might have, and for the location
489 // to build the bootstrap versions of the standard library.
490 obj := pathf("%s/pkg/obj", goroot)
494 xatexit(func() { xremove(obj) })
496 // Create build cache directory.
497 objGobuild := pathf("%s/pkg/obj/go-build", goroot)
499 xremoveall(objGobuild)
501 xmkdirall(objGobuild)
502 xatexit(func() { xremoveall(objGobuild) })
504 // Create directory for bootstrap versions of standard library .a files.
505 objGoBootstrap := pathf("%s/pkg/obj/go-bootstrap", goroot)
507 xremoveall(objGoBootstrap)
509 xmkdirall(objGoBootstrap)
510 xatexit(func() { xremoveall(objGoBootstrap) })
512 // Create tool directory.
513 // We keep it in pkg/, just like the object directory above.
519 // Remove tool binaries from before the tool/gohostos_gohostarch
520 xremoveall(pathf("%s/bin/tool", goroot))
522 // Remove old pre-tool binaries.
523 for _, old := range oldtool {
524 xremove(pathf("%s/bin/%s", goroot, old))
527 // For release, make sure excluded things are excluded.
528 goversion := findgoversion()
529 if strings.HasPrefix(goversion, "release.") || (strings.HasPrefix(goversion, "go") && !strings.Contains(goversion, "beta")) {
530 for _, dir := range unreleased {
531 if p := pathf("%s/%s", goroot, dir); isdir(p) {
532 fatalf("%s should not exist in release build", p)
542 // deptab lists changes to the default dependencies for a given prefix.
543 // deps ending in /* read the whole directory; deps beginning with -
544 // exclude files with that prefix.
545 // Note that this table applies only to the build of cmd/go,
546 // after the main compiler bootstrap.
547 var deptab = []struct {
548 prefix string // prefix of target
549 dep []string // dependency tweaks for targets with that prefix
551 {"cmd/go/internal/cfg", []string{
555 {"runtime/internal/sys", []string{
558 {"go/build", []string{
563 // depsuffix records the allowed suffixes for source files.
564 var depsuffix = []string{
569 // gentab records how to generate some trivial files.
570 var gentab = []struct {
572 gen func(string, string)
574 {"zdefaultcc.go", mkzdefaultcc},
575 {"zosarch.go", mkzosarch},
576 {"zversion.go", mkzversion},
579 // not generated anymore, but delete the file if we see it
587 // installed maps from a dir name (as given to install) to a chan
588 // closed when the dir's package is installed.
589 var installed = make(map[string]chan struct{})
590 var installedMu sync.Mutex
592 func install(dir string) {
596 func startInstall(dir string) chan struct{} {
600 ch = make(chan struct{})
602 go runInstall(dir, ch)
608 // runInstall installs the library, package, or binary associated with dir,
609 // which is relative to $GOROOT/src.
610 func runInstall(pkg string, ch chan struct{}) {
611 if pkg == "net" || pkg == "os/user" || pkg == "crypto/x509" {
612 fatalf("go_bootstrap cannot depend on cgo package %s", pkg)
622 if goos != gohostos || goarch != gohostarch {
623 errprintf("%s (%s/%s)\n", pkg, goos, goarch)
625 errprintf("%s\n", pkg)
629 workdir := pathf("%s/%s", workdir, pkg)
634 for _, name := range clean {
639 // dir = full path to pkg.
640 dir := pathf("%s/src/%s", goroot, pkg)
641 name := filepath.Base(dir)
643 // ispkg predicts whether the package should be linked as a binary, based
644 // on the name. There should be no "main" packages in vendor, since
645 // 'go mod vendor' will only copy imported packages there.
646 ispkg := !strings.HasPrefix(pkg, "cmd/") || strings.Contains(pkg, "/internal/") || strings.Contains(pkg, "/vendor/")
648 // Start final link command line.
649 // Note: code below knows that link.p[targ] is the target.
656 // Go library (package).
658 link = []string{"pack", packagefile(pkg)}
660 xmkdirall(filepath.Dir(link[targ]))
665 elem = "go_bootstrap"
667 link = []string{pathf("%s/link", tooldir)}
668 if goos == "android" {
669 link = append(link, "-buildmode=pie")
672 link = append(link, goldflags)
674 link = append(link, "-extld="+compilerEnvLookup(defaultcc, goos, goarch))
675 link = append(link, "-L="+pathf("%s/pkg/obj/go-bootstrap/%s_%s", goroot, goos, goarch))
676 link = append(link, "-o", pathf("%s/%s%s", tooldir, elem, exe))
679 ttarg := mtime(link[targ])
681 // Gather files that are sources for this target.
682 // Everything in that directory, and any target-specific
684 files := xreaddir(dir)
686 // Remove files beginning with . or _,
687 // which are likely to be editor temporary files.
688 // This is the same heuristic build.ScanDir uses.
689 // There do exist real C files beginning with _,
690 // so limit that check to just Go files.
691 files = filter(files, func(p string) bool {
692 return !strings.HasPrefix(p, ".") && (!strings.HasPrefix(p, "_") || !strings.HasSuffix(p, ".go"))
695 for _, dt := range deptab {
696 if pkg == dt.prefix || strings.HasSuffix(dt.prefix, "/") && strings.HasPrefix(pkg, dt.prefix) {
697 for _, p := range dt.dep {
699 files = append(files, p)
705 // Convert to absolute paths.
706 for i, p := range files {
707 if !filepath.IsAbs(p) {
708 files[i] = pathf("%s/%s", dir, p)
712 // Is the target up-to-date?
713 var gofiles, sfiles, missing []string
715 files = filter(files, func(p string) bool {
716 for _, suf := range depsuffix {
717 if strings.HasSuffix(p, suf) {
724 if !t.IsZero() && !strings.HasSuffix(p, ".a") && !shouldbuild(p, pkg) {
727 if strings.HasSuffix(p, ".go") {
728 gofiles = append(gofiles, p)
729 } else if strings.HasSuffix(p, ".s") {
730 sfiles = append(sfiles, p)
736 missing = append(missing, p)
741 // If there are no files to compile, we're done.
750 // For package runtime, copy some files into the work space.
751 if pkg == "runtime" {
752 xmkdirall(pathf("%s/pkg/include", goroot))
753 // For use by assembly and C files.
754 copyfile(pathf("%s/pkg/include/textflag.h", goroot),
755 pathf("%s/src/runtime/textflag.h", goroot), 0)
756 copyfile(pathf("%s/pkg/include/funcdata.h", goroot),
757 pathf("%s/src/runtime/funcdata.h", goroot), 0)
758 copyfile(pathf("%s/pkg/include/asm_ppc64x.h", goroot),
759 pathf("%s/src/runtime/asm_ppc64x.h", goroot), 0)
760 copyfile(pathf("%s/pkg/include/asm_amd64.h", goroot),
761 pathf("%s/src/runtime/asm_amd64.h", goroot), 0)
764 // Generate any missing files; regenerate existing ones.
765 for _, p := range files {
766 elem := filepath.Base(p)
767 for _, gt := range gentab {
771 if strings.HasPrefix(elem, gt.nameprefix) {
773 errprintf("generate %s\n", p)
776 // Do not add generated file to clean list.
777 // In runtime, we want to be able to
778 // build the package with the go tool,
779 // and it assumes these generated files already
780 // exist (it does not know how to build them).
781 // The 'clean' command can remove
782 // the generated files.
786 // Did not rebuild p.
787 if find(p, missing) >= 0 {
788 fatalf("missing file %s", p)
793 // Resolve imported packages to actual package paths.
794 // Make sure they're installed.
795 importMap := make(map[string]string)
796 for _, p := range gofiles {
797 for _, imp := range readimports(p) {
799 fatalf("%s imports C", p)
801 importMap[imp] = resolveVendor(imp, dir)
804 sortedImports := make([]string, 0, len(importMap))
805 for imp := range importMap {
806 sortedImports = append(sortedImports, imp)
808 sort.Strings(sortedImports)
810 for _, dep := range importMap {
812 fatalf("%s imports C", pkg)
816 for _, dep := range importMap {
820 if goos != gohostos || goarch != gohostarch {
821 // We've generated the right files; the go command can do the build.
823 errprintf("skip build for cross-compile %s\n", pkg)
829 pathf("%s/asm", tooldir),
831 "-I", pathf("%s/pkg/include", goroot),
832 "-D", "GOOS_" + goos,
833 "-D", "GOARCH_" + goarch,
834 "-D", "GOOS_GOARCH_" + goos + "_" + goarch,
837 if goarch == "mips" || goarch == "mipsle" {
838 // Define GOMIPS_value from gomips.
839 asmArgs = append(asmArgs, "-D", "GOMIPS_"+gomips)
841 if goarch == "mips64" || goarch == "mips64le" {
842 // Define GOMIPS64_value from gomips64.
843 asmArgs = append(asmArgs, "-D", "GOMIPS64_"+gomips64)
845 if goarch == "ppc64" || goarch == "ppc64le" {
846 // We treat each powerpc version as a superset of functionality.
849 asmArgs = append(asmArgs, "-D", "GOPPC64_power10")
852 asmArgs = append(asmArgs, "-D", "GOPPC64_power9")
854 default: // This should always be power8.
855 asmArgs = append(asmArgs, "-D", "GOPPC64_power8")
858 goasmh := pathf("%s/go_asm.h", workdir)
859 if IsRuntimePackagePath(pkg) {
860 asmArgs = append(asmArgs, "-compiling-runtime")
863 // Collect symabis from assembly code.
866 symabis = pathf("%s/symabis", workdir)
867 var wg sync.WaitGroup
868 asmabis := append(asmArgs[:len(asmArgs):len(asmArgs)], "-gensymabis", "-o", symabis)
869 asmabis = append(asmabis, sfiles...)
870 if err := os.WriteFile(goasmh, nil, 0666); err != nil {
871 fatalf("cannot write empty go_asm.h: %s", err)
873 bgrun(&wg, dir, asmabis...)
877 // Build an importcfg file for the compiler.
878 buf := &bytes.Buffer{}
879 for _, imp := range sortedImports {
883 dep := importMap[imp]
885 fmt.Fprintf(buf, "importmap %s=%s\n", imp, dep)
887 fmt.Fprintf(buf, "packagefile %s=%s\n", dep, packagefile(dep))
889 importcfg := pathf("%s/importcfg", workdir)
890 if err := os.WriteFile(importcfg, buf.Bytes(), 0666); err != nil {
891 fatalf("cannot write importcfg file: %v", err)
895 // The next loop will compile individual non-Go files.
896 // Hand the Go files to the compiler en masse.
897 // For packages containing assembly, this writes go_asm.h, which
898 // the assembly files will need.
900 if strings.HasPrefix(pkg, "cmd/") && strings.Count(pkg, "/") == 1 {
903 b := pathf("%s/_go_.a", workdir)
904 clean = append(clean, b)
906 link = append(link, b)
912 compile := []string{pathf("%s/compile", tooldir), "-std", "-pack", "-o", b, "-p", pkgName, "-importcfg", importcfg}
914 compile = append(compile, strings.Fields(gogcflags)...)
916 if pkg == "runtime" {
917 compile = append(compile, "-+")
920 compile = append(compile, "-asmhdr", goasmh)
923 compile = append(compile, "-symabis", symabis)
925 if goos == "android" {
926 compile = append(compile, "-shared")
929 compile = append(compile, gofiles...)
930 var wg sync.WaitGroup
931 // We use bgrun and immediately wait for it instead of calling run() synchronously.
932 // This executes all jobs through the bgwork channel and allows the process
933 // to exit cleanly in case an error occurs.
934 bgrun(&wg, dir, compile...)
937 // Compile the files.
938 for _, p := range sfiles {
939 // Assembly file for a Go package.
940 compile := asmArgs[:len(asmArgs):len(asmArgs)]
943 b := pathf("%s/%s", workdir, filepath.Base(p))
945 // Change the last character of the output file (which was c or s).
946 b = b[:len(b)-1] + "o"
947 compile = append(compile, "-o", b, p)
948 bgrun(&wg, dir, compile...)
950 link = append(link, b)
952 clean = append(clean, b)
959 dopack(link[targ], archive, link[targ+1:])
963 // Remove target before writing it.
965 bgrun(&wg, "", link...)
969 // packagefile returns the path to a compiled .a file for the given package
970 // path. Paths may need to be resolved with resolveVendor first.
971 func packagefile(pkg string) string {
972 return pathf("%s/pkg/obj/go-bootstrap/%s_%s/%s.a", goroot, goos, goarch, pkg)
975 // unixOS is the set of GOOS values matched by the "unix" build tag.
976 // This is the same list as in go/build/syslist.go and
977 // cmd/go/internal/imports/build.go.
978 var unixOS = map[string]bool{
993 // matchtag reports whether the tag matches this build.
994 func matchtag(tag string) bool {
996 case "gc", "cmd_go_bootstrap", "go1.1":
999 return goos == "linux" || goos == "android"
1001 return goos == "solaris" || goos == "illumos"
1003 return goos == "darwin" || goos == "ios"
1013 // shouldbuild reports whether we should build this file.
1014 // It applies the same rules that are used with context tags
1015 // in package go/build, except it's less picky about the order
1016 // of GOOS and GOARCH.
1017 // We also allow the special tag cmd_go_bootstrap.
1018 // See ../go/bootstrap.go and package go/build.
1019 func shouldbuild(file, pkg string) bool {
1020 // Check file name for GOOS or GOARCH.
1021 name := filepath.Base(file)
1022 excluded := func(list []string, ok string) bool {
1023 for _, x := range list {
1024 if x == ok || (ok == "android" && x == "linux") || (ok == "illumos" && x == "solaris") || (ok == "ios" && x == "darwin") {
1027 i := strings.Index(name, x)
1028 if i <= 0 || name[i-1] != '_' {
1032 if i == len(name) || name[i] == '.' || name[i] == '_' {
1038 if excluded(okgoos, goos) || excluded(okgoarch, goarch) {
1043 if strings.Contains(name, "_test") {
1047 // Check file contents for //go:build lines.
1048 for _, p := range strings.Split(readfile(file), "\n") {
1049 p = strings.TrimSpace(p)
1054 i := strings.Index(code, "//")
1056 code = strings.TrimSpace(code[:i])
1058 if code == "package documentation" {
1061 if code == "package main" && pkg != "cmd/go" && pkg != "cmd/cgo" {
1064 if !strings.HasPrefix(p, "//") {
1067 if strings.HasPrefix(p, "//go:build ") {
1068 matched, err := matchexpr(p[len("//go:build "):])
1070 errprintf("%s: %v", file, err)
1079 // copy copies the file src to dst, via memory (so only good for small files).
1080 func copyfile(dst, src string, flag int) {
1082 errprintf("cp %s %s\n", src, dst)
1084 writefile(readfile(src), dst, flag)
1087 // dopack copies the package src to dst,
1088 // appending the files listed in extra.
1089 // The archive format is the traditional Unix ar format.
1090 func dopack(dst, src string, extra []string) {
1091 bdst := bytes.NewBufferString(readfile(src))
1092 for _, file := range extra {
1094 // find last path element for archive member name
1095 i := strings.LastIndex(file, "/") + 1
1096 j := strings.LastIndex(file, `\`) + 1
1100 fmt.Fprintf(bdst, "%-16.16s%-12d%-6d%-6d%-8o%-10d`\n", file[i:], 0, 0, 0, 0644, len(b))
1106 writefile(bdst.String(), dst, 0)
1109 var runtimegen = []string{
1114 // cleanlist is a list of packages with generated files and commands.
1115 var cleanlist = []string{
1116 "runtime/internal/sys",
1118 "cmd/go/internal/cfg",
1123 for _, name := range cleanlist {
1124 path := pathf("%s/src/%s", goroot, name)
1125 // Remove generated files.
1126 for _, elem := range xreaddir(path) {
1127 for _, gt := range gentab {
1128 if strings.HasPrefix(elem, gt.nameprefix) {
1129 xremove(pathf("%s/%s", path, elem))
1133 // Remove generated binary named for directory.
1134 if strings.HasPrefix(name, "cmd/") {
1135 xremove(pathf("%s/%s", path, name[4:]))
1139 // remove runtimegen files.
1140 path := pathf("%s/src/runtime", goroot)
1141 for _, elem := range runtimegen {
1142 xremove(pathf("%s/%s", path, elem))
1146 // Remove object tree.
1147 xremoveall(pathf("%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch))
1149 // Remove installed packages and tools.
1150 xremoveall(pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch))
1151 xremoveall(pathf("%s/pkg/%s_%s", goroot, goos, goarch))
1152 xremoveall(pathf("%s/pkg/%s_%s_race", goroot, gohostos, gohostarch))
1153 xremoveall(pathf("%s/pkg/%s_%s_race", goroot, goos, goarch))
1156 // Remove cached version info.
1157 xremove(pathf("%s/VERSION.cache", goroot))
1162 * command implementations
1165 // The env command prints the default environment.
1167 path := flag.Bool("p", false, "emit updated PATH")
1168 plan9 := flag.Bool("9", gohostos == "plan9", "emit plan 9 syntax")
1169 windows := flag.Bool("w", gohostos == "windows", "emit windows syntax")
1172 format := "%s=\"%s\"\n"
1175 format = "%s='%s'\n"
1177 format = "set %s=%s\r\n"
1180 xprintf(format, "GO111MODULE", "")
1181 xprintf(format, "GOARCH", goarch)
1182 xprintf(format, "GOBIN", gorootBin)
1183 xprintf(format, "GOCACHE", os.Getenv("GOCACHE"))
1184 xprintf(format, "GODEBUG", os.Getenv("GODEBUG"))
1185 xprintf(format, "GOENV", "off")
1186 xprintf(format, "GOFLAGS", "")
1187 xprintf(format, "GOHOSTARCH", gohostarch)
1188 xprintf(format, "GOHOSTOS", gohostos)
1189 xprintf(format, "GOOS", goos)
1190 xprintf(format, "GOPROXY", os.Getenv("GOPROXY"))
1191 xprintf(format, "GOROOT", goroot)
1192 xprintf(format, "GOTMPDIR", os.Getenv("GOTMPDIR"))
1193 xprintf(format, "GOTOOLDIR", tooldir)
1194 if goarch == "arm" {
1195 xprintf(format, "GOARM", goarm)
1197 if goarch == "386" {
1198 xprintf(format, "GO386", go386)
1200 if goarch == "amd64" {
1201 xprintf(format, "GOAMD64", goamd64)
1203 if goarch == "mips" || goarch == "mipsle" {
1204 xprintf(format, "GOMIPS", gomips)
1206 if goarch == "mips64" || goarch == "mips64le" {
1207 xprintf(format, "GOMIPS64", gomips64)
1209 if goarch == "ppc64" || goarch == "ppc64le" {
1210 xprintf(format, "GOPPC64", goppc64)
1212 xprintf(format, "GOWORK", "off")
1216 if gohostos == "windows" {
1219 xprintf(format, "PATH", fmt.Sprintf("%s%s%s", gorootBin, sep, os.Getenv("PATH")))
1224 timeLogEnabled = os.Getenv("GOBUILDTIMELOGFILE") != ""
1225 timeLogMu sync.Mutex
1226 timeLogFile *os.File
1227 timeLogStart time.Time
1230 func timelog(op, name string) {
1231 if !timeLogEnabled {
1235 defer timeLogMu.Unlock()
1236 if timeLogFile == nil {
1237 f, err := os.OpenFile(os.Getenv("GOBUILDTIMELOGFILE"), os.O_RDWR|os.O_APPEND, 0666)
1241 buf := make([]byte, 100)
1243 s := string(buf[:n])
1244 if i := strings.Index(s, "\n"); i >= 0 {
1247 i := strings.Index(s, " start")
1249 log.Fatalf("time log %s does not begin with start line", os.Getenv("GOBUILDTIMELOGFILE"))
1251 t, err := time.Parse(time.UnixDate, s[:i])
1253 log.Fatalf("cannot parse time log line %q: %v", s, err)
1259 fmt.Fprintf(timeLogFile, "%s %+.1fs %s %s\n", t.Format(time.UnixDate), t.Sub(timeLogStart).Seconds(), op, name)
1262 var toolchain = []string{"cmd/asm", "cmd/cgo", "cmd/compile", "cmd/link"}
1264 // The bootstrap command runs a build from scratch,
1265 // stopping at having installed the go_bootstrap command.
1267 // WARNING: This command runs after cmd/dist is built with the Go bootstrap toolchain.
1268 // It rebuilds and installs cmd/dist with the new toolchain, so other
1269 // commands (like "go tool dist test" in run.bash) can rely on bug fixes
1270 // made since the Go bootstrap version, but this function cannot.
1271 func cmdbootstrap() {
1272 timelog("start", "dist bootstrap")
1273 defer timelog("end", "dist bootstrap")
1275 var noBanner, noClean bool
1277 flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all")
1278 flag.BoolVar(&debug, "d", debug, "enable debugging of bootstrap process")
1279 flag.BoolVar(&noBanner, "no-banner", noBanner, "do not print banner")
1280 flag.BoolVar(&noClean, "no-clean", noClean, "print deprecation warning")
1285 xprintf("warning: --no-clean is deprecated and has no effect; use 'go install std cmd' instead\n")
1288 // Set GOPATH to an internal directory. We shouldn't actually
1289 // need to store files here, since the toolchain won't
1290 // depend on modules outside of vendor directories, but if
1291 // GOPATH points somewhere else (e.g., to GOROOT), the
1292 // go tool may complain.
1293 os.Setenv("GOPATH", pathf("%s/pkg/obj/gopath", goroot))
1295 // Disable GOEXPERIMENT when building toolchain1 and
1296 // go_bootstrap. We don't need any experiments for the
1297 // bootstrap toolchain, and this lets us avoid duplicating the
1298 // GOEXPERIMENT-related build logic from cmd/go here. If the
1299 // bootstrap toolchain is < Go 1.17, it will ignore this
1300 // anyway since GOEXPERIMENT is baked in; otherwise it will
1301 // pick it up from the environment we set here. Once we're
1302 // using toolchain1 with dist as the build system, we need to
1303 // override this to keep the experiments assumed by the
1304 // toolchain and by dist consistent. Once go_bootstrap takes
1305 // over the build process, we'll set this back to the original
1307 os.Setenv("GOEXPERIMENT", "none")
1310 // cmd/buildid is used in debug mode.
1311 toolchain = append(toolchain, "cmd/buildid")
1314 if isdir(pathf("%s/src/pkg", goroot)) {
1316 "The Go package sources have moved to $GOROOT/src.\n"+
1317 "*** %s still exists. ***\n"+
1318 "It probably contains stale files that may confuse the build.\n"+
1319 "Please (check what's there and) remove it and try again.\n"+
1320 "See https://golang.org/s/go14nopkg\n",
1321 pathf("%s/src/pkg", goroot))
1330 timelog("build", "toolchain1")
1332 bootstrapBuildTools()
1334 // Remember old content of $GOROOT/bin for comparison below.
1335 oldBinFiles, _ := filepath.Glob(pathf("%s/bin/*", goroot))
1337 // For the main bootstrap, building for host os/arch.
1342 os.Setenv("GOHOSTARCH", gohostarch)
1343 os.Setenv("GOHOSTOS", gohostos)
1344 os.Setenv("GOARCH", goarch)
1345 os.Setenv("GOOS", goos)
1347 timelog("build", "go_bootstrap")
1348 xprintf("Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.\n")
1349 install("runtime") // dependency not visible in sources; also sets up textflag.h
1355 gogcflags = os.Getenv("GO_GCFLAGS") // we were using $BOOT_GO_GCFLAGS until now
1357 goldflags = os.Getenv("GO_LDFLAGS") // we were using $BOOT_GO_LDFLAGS until now
1358 goBootstrap := pathf("%s/go_bootstrap", tooldir)
1359 cmdGo := pathf("%s/go", gorootBin)
1361 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1362 copyfile(pathf("%s/compile1", tooldir), pathf("%s/compile", tooldir), writeExec)
1365 // To recap, so far we have built the new toolchain
1366 // (cmd/asm, cmd/cgo, cmd/compile, cmd/link)
1367 // using the Go bootstrap toolchain and go command.
1368 // Then we built the new go command (as go_bootstrap)
1369 // using the new toolchain and our own build logic (above).
1371 // toolchain1 = mk(new toolchain, go1.17 toolchain, go1.17 cmd/go)
1372 // go_bootstrap = mk(new cmd/go, toolchain1, cmd/dist)
1374 // The toolchain1 we built earlier is built from the new sources,
1375 // but because it was built using cmd/go it has no build IDs.
1376 // The eventually installed toolchain needs build IDs, so we need
1377 // to do another round:
1379 // toolchain2 = mk(new toolchain, toolchain1, go_bootstrap)
1381 timelog("build", "toolchain2")
1385 xprintf("Building Go toolchain2 using go_bootstrap and Go toolchain1.\n")
1386 os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch))
1387 // Now that cmd/go is in charge of the build process, enable GOEXPERIMENT.
1388 os.Setenv("GOEXPERIMENT", goexperiment)
1389 goInstall(goBootstrap, toolchain...)
1391 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1392 copyfile(pathf("%s/compile2", tooldir), pathf("%s/compile", tooldir), writeExec)
1395 // Toolchain2 should be semantically equivalent to toolchain1,
1396 // but it was built using the newly built compiler instead of the Go bootstrap compiler,
1397 // so it should at the least run faster. Also, toolchain1 had no build IDs
1398 // in the binaries, while toolchain2 does. In non-release builds, the
1399 // toolchain's build IDs feed into constructing the build IDs of built targets,
1400 // so in non-release builds, everything now looks out-of-date due to
1401 // toolchain2 having build IDs - that is, due to the go command seeing
1402 // that there are new compilers. In release builds, the toolchain's reported
1403 // version is used in place of the build ID, and the go command does not
1404 // see that change from toolchain1 to toolchain2, so in release builds,
1405 // nothing looks out of date.
1406 // To keep the behavior the same in both non-release and release builds,
1407 // we force-install everything here.
1409 // toolchain3 = mk(new toolchain, toolchain2, go_bootstrap)
1411 timelog("build", "toolchain3")
1415 xprintf("Building Go toolchain3 using go_bootstrap and Go toolchain2.\n")
1416 goInstall(goBootstrap, append([]string{"-a"}, toolchain...)...)
1418 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1419 copyfile(pathf("%s/compile3", tooldir), pathf("%s/compile", tooldir), writeExec)
1422 if goos == oldgoos && goarch == oldgoarch {
1423 // Common case - not setting up for cross-compilation.
1424 timelog("build", "toolchain")
1428 xprintf("Building packages and commands for %s/%s.\n", goos, goarch)
1430 // GOOS/GOARCH does not match GOHOSTOS/GOHOSTARCH.
1431 // Finish GOHOSTOS/GOHOSTARCH installation and then
1432 // run GOOS/GOARCH installation.
1433 timelog("build", "host toolchain")
1437 xprintf("Building packages and commands for host, %s/%s.\n", goos, goarch)
1438 goInstall(goBootstrap, "std", "cmd")
1439 checkNotStale(goBootstrap, "std", "cmd")
1440 checkNotStale(cmdGo, "std", "cmd")
1442 timelog("build", "target toolchain")
1448 os.Setenv("GOOS", goos)
1449 os.Setenv("GOARCH", goarch)
1450 os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch))
1451 xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch)
1453 targets := []string{"std", "cmd"}
1454 goInstall(goBootstrap, targets...)
1455 checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...)
1456 checkNotStale(goBootstrap, targets...)
1457 checkNotStale(cmdGo, targets...)
1459 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1460 checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...)
1461 copyfile(pathf("%s/compile4", tooldir), pathf("%s/compile", tooldir), writeExec)
1464 // Check that there are no new files in $GOROOT/bin other than
1465 // go and gofmt and $GOOS_$GOARCH (target bin when cross-compiling).
1466 binFiles, _ := filepath.Glob(pathf("%s/bin/*", goroot))
1467 ok := map[string]bool{}
1468 for _, f := range oldBinFiles {
1471 for _, f := range binFiles {
1472 elem := strings.TrimSuffix(filepath.Base(f), ".exe")
1473 if !ok[f] && elem != "go" && elem != "gofmt" && elem != goos+"_"+goarch {
1474 fatalf("unexpected new file in $GOROOT/bin: %s", elem)
1478 // Remove go_bootstrap now that we're done.
1479 xremove(pathf("%s/go_bootstrap", tooldir))
1481 if goos == "android" {
1482 // Make sure the exec wrapper will sync a fresh $GOROOT to the device.
1483 xremove(pathf("%s/go_android_exec-adb-sync-status", os.TempDir()))
1486 if wrapperPath := wrapperPathFor(goos, goarch); wrapperPath != "" {
1487 oldcc := os.Getenv("CC")
1488 os.Setenv("GOOS", gohostos)
1489 os.Setenv("GOARCH", gohostarch)
1490 os.Setenv("CC", compilerEnvLookup(defaultcc, gohostos, gohostarch))
1491 goCmd(cmdGo, "build", "-o", pathf("%s/go_%s_%s_exec%s", gorootBin, goos, goarch, exe), wrapperPath)
1492 // Restore environment.
1493 // TODO(elias.naur): support environment variables in goCmd?
1494 os.Setenv("GOOS", goos)
1495 os.Setenv("GOARCH", goarch)
1496 os.Setenv("CC", oldcc)
1499 // Print trailing banner unless instructed otherwise.
1505 func wrapperPathFor(goos, goarch string) string {
1507 case goos == "android":
1508 if gohostos != "android" {
1509 return pathf("%s/misc/android/go_android_exec.go", goroot)
1512 if gohostos != "ios" {
1513 return pathf("%s/misc/ios/go_ios_exec.go", goroot)
1519 func goInstall(goBinary string, args ...string) {
1520 goCmd(goBinary, "install", args...)
1523 func appendCompilerFlags(args []string) []string {
1524 if gogcflags != "" {
1525 args = append(args, "-gcflags=all="+gogcflags)
1527 if goldflags != "" {
1528 args = append(args, "-ldflags=all="+goldflags)
1533 func goCmd(goBinary string, cmd string, args ...string) {
1534 goCmd := []string{goBinary, cmd}
1536 goCmd = append(goCmd, "-tags=noopt")
1538 goCmd = appendCompilerFlags(goCmd)
1540 goCmd = append(goCmd, "-v")
1543 // Force only one process at a time on vx32 emulation.
1544 if gohostos == "plan9" && os.Getenv("sysname") == "vx32" {
1545 goCmd = append(goCmd, "-p=1")
1548 run(workdir, ShowOutput|CheckExit, append(goCmd, args...)...)
1551 func checkNotStale(goBinary string, targets ...string) {
1552 goCmd := []string{goBinary, "list"}
1554 goCmd = append(goCmd, "-tags=noopt")
1556 goCmd = appendCompilerFlags(goCmd)
1557 goCmd = append(goCmd, "-f={{if .Stale}}\tSTALE {{.ImportPath}}: {{.StaleReason}}{{end}}")
1559 out := run(workdir, CheckExit, append(goCmd, targets...)...)
1560 if strings.Contains(out, "\tSTALE ") {
1561 os.Setenv("GODEBUG", "gocachehash=1")
1562 for _, target := range []string{"runtime/internal/sys", "cmd/dist", "cmd/link"} {
1563 if strings.Contains(out, "STALE "+target) {
1564 run(workdir, ShowOutput|CheckExit, goBinary, "list", "-f={{.ImportPath}} {{.Stale}}", target)
1568 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)
1572 // Cannot use go/build directly because cmd/dist for a new release
1573 // builds against an old release's go/build, which may be out of sync.
1574 // To reduce duplication, we generate the list for go/build from this.
1576 // We list all supported platforms in this list, so that this is the
1577 // single point of truth for supported platforms. This list is used
1578 // by 'go tool dist list'.
1579 var cgoEnabled = map[string]bool{
1581 "darwin/amd64": true,
1582 "darwin/arm64": true,
1583 "dragonfly/amd64": true,
1584 "freebsd/386": true,
1585 "freebsd/amd64": true,
1586 "freebsd/arm": true,
1587 "freebsd/arm64": true,
1588 "freebsd/riscv64": true,
1589 "illumos/amd64": true,
1591 "linux/amd64": true,
1593 "linux/arm64": true,
1594 "linux/loong64": true,
1595 "linux/ppc64": false,
1596 "linux/ppc64le": true,
1598 "linux/mipsle": true,
1599 "linux/mips64": true,
1600 "linux/mips64le": true,
1601 "linux/riscv64": true,
1602 "linux/s390x": true,
1603 "linux/sparc64": true,
1604 "android/386": true,
1605 "android/amd64": true,
1606 "android/arm": true,
1607 "android/arm64": true,
1612 "netbsd/amd64": true,
1614 "netbsd/arm64": true,
1615 "openbsd/386": true,
1616 "openbsd/amd64": true,
1617 "openbsd/arm": true,
1618 "openbsd/arm64": true,
1619 "openbsd/mips64": true,
1621 "plan9/amd64": false,
1623 "solaris/amd64": true,
1624 "windows/386": true,
1625 "windows/amd64": true,
1626 "windows/arm": false,
1627 "windows/arm64": true,
1630 // List of platforms which are supported but not complete yet. These get
1631 // filtered out of cgoEnabled for 'dist list'. See golang.org/issue/28944
1632 var incomplete = map[string]bool{
1633 "linux/sparc64": true,
1636 // List of platforms which are first class ports. See golang.org/issue/38874.
1637 var firstClass = map[string]bool{
1638 "darwin/amd64": true,
1639 "darwin/arm64": true,
1641 "linux/amd64": true,
1643 "linux/arm64": true,
1644 "windows/386": true,
1645 "windows/amd64": true,
1648 func needCC() bool {
1649 switch os.Getenv("CGO_ENABLED") {
1655 return cgoEnabled[gohostos+"/"+gohostarch]
1662 cc, err := quotedSplit(defaultcc[""])
1664 fatalf("split CC: %v", err)
1666 var ccHelp = append(cc, "--help")
1668 if output, err := exec.Command(ccHelp[0], ccHelp[1:]...).CombinedOutput(); err != nil {
1670 if len(output) > 0 {
1671 outputHdr = "\nCommand output:\n\n"
1673 fatalf("cannot invoke C compiler %q: %v\n\n"+
1674 "Go needs a system C compiler for use with cgo.\n"+
1675 "To set a C compiler, set CC=the-compiler.\n"+
1676 "To disable cgo, set CGO_ENABLED=0.\n%s%s", cc, err, outputHdr, output)
1680 func defaulttarg() string {
1681 // xgetwd might return a path with symlinks fully resolved, and if
1682 // there happens to be symlinks in goroot, then the hasprefix test
1683 // will never succeed. Instead, we use xrealwd to get a canonical
1684 // goroot/src before the comparison to avoid this problem.
1686 src := pathf("%s/src/", goroot)
1687 real_src := xrealwd(src)
1688 if !strings.HasPrefix(pwd, real_src) {
1689 fatalf("current directory %s is not under %s", pwd, real_src)
1691 pwd = pwd[len(real_src):]
1692 // guard against xrealwd returning the directory without the trailing /
1693 pwd = strings.TrimPrefix(pwd, "/")
1698 // Install installs the list of packages named on the command line.
1702 if flag.NArg() == 0 {
1703 install(defaulttarg())
1706 for _, arg := range flag.Args() {
1711 // Clean deletes temporary objects.
1717 // Banner prints the 'now you've installed Go' banner.
1728 xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot)
1729 xprintf("Installed commands in %s\n", gorootBin)
1731 if !xsamefile(goroot_final, goroot) {
1732 // If the files are to be moved, don't check that gobin
1733 // is on PATH; assume they know what they are doing.
1734 } else if gohostos == "plan9" {
1735 // Check that GOROOT/bin is bound before /bin.
1736 pid := strings.Replace(readfile("#c/pid"), " ", "", -1)
1737 ns := fmt.Sprintf("/proc/%s/ns", pid)
1738 if !strings.Contains(readfile(ns), fmt.Sprintf("bind -b %s /bin", gorootBin)) {
1739 xprintf("*** You need to bind %s before /bin.\n", gorootBin)
1742 // Check that GOROOT/bin appears in $PATH.
1744 if gohostos == "windows" {
1747 if !strings.Contains(pathsep+os.Getenv("PATH")+pathsep, pathsep+gorootBin+pathsep) {
1748 xprintf("*** You need to add %s to your PATH.\n", gorootBin)
1752 if !xsamefile(goroot_final, goroot) {
1754 "The binaries expect %s to be copied or moved to %s\n",
1755 goroot, goroot_final)
1759 // Version prints the Go version.
1762 xprintf("%s\n", findgoversion())
1765 // cmdlist lists all supported platforms.
1767 jsonFlag := flag.Bool("json", false, "produce JSON output")
1771 for p := range cgoEnabled {
1775 plats = append(plats, p)
1780 for _, p := range plats {
1786 type jsonResult struct {
1792 var results []jsonResult
1793 for _, p := range plats {
1794 fields := strings.Split(p, "/")
1795 results = append(results, jsonResult{
1798 CgoSupported: cgoEnabled[p],
1799 FirstClass: firstClass[p]})
1801 out, err := json.MarshalIndent(results, "", "\t")
1803 fatalf("json marshal error: %v", err)
1805 if _, err := os.Stdout.Write(out); err != nil {
1806 fatalf("write failed: %v", err)
1810 // IsRuntimePackagePath examines 'pkgpath' and returns TRUE if it
1811 // belongs to the collection of "runtime-related" packages, including
1812 // "runtime" itself, "reflect", "syscall", and the
1813 // "runtime/internal/*" packages.
1815 // Keep in sync with cmd/internal/objabi/path.go:IsRuntimePackagePath.
1816 func IsRuntimePackagePath(pkgpath string) bool {
1825 case "internal/bytealg":
1828 rval = strings.HasPrefix(pkgpath, "runtime/internal")
1834 for _, gcflag := range strings.Split(gogcflags, " ") {
1835 if gcflag == "-N" || gcflag == "-l" {