Source file
src/cmd/dist/build.go
1
2
3
4
5 package main
6
7 import (
8 "bytes"
9 "encoding/json"
10 "flag"
11 "fmt"
12 "io"
13 "io/fs"
14 "log"
15 "os"
16 "os/exec"
17 "path/filepath"
18 "regexp"
19 "slices"
20 "sort"
21 "strconv"
22 "strings"
23 "sync"
24 "time"
25 )
26
27
28
29
30 var (
31 goarch string
32 gorootBin string
33 gorootBinGo string
34 gohostarch string
35 gohostos string
36 goos string
37 goarm string
38 goarm64 string
39 go386 string
40 goamd64 string
41 gomips string
42 gomips64 string
43 goppc64 string
44 goriscv64 string
45 goroot string
46 goextlinkenabled string
47 gogcflags string
48 goldflags string
49 goexperiment string
50 gofips140 string
51 workdir string
52 tooldir string
53 oldgoos string
54 oldgoarch string
55 oldgocache string
56 exe string
57 defaultcc map[string]string
58 defaultcxx map[string]string
59 defaultpkgconfig string
60 defaultldso string
61
62 rebuildall bool
63 noOpt bool
64 isRelease bool
65
66 vflag int
67 )
68
69
70 var okgoarch = []string{
71 "386",
72 "amd64",
73 "arm",
74 "arm64",
75 "loong64",
76 "mips",
77 "mipsle",
78 "mips64",
79 "mips64le",
80 "ppc64",
81 "ppc64le",
82 "riscv64",
83 "s390x",
84 "sparc64",
85 "wasm",
86 }
87
88
89 var okgoos = []string{
90 "darwin",
91 "dragonfly",
92 "illumos",
93 "ios",
94 "js",
95 "wasip1",
96 "linux",
97 "android",
98 "solaris",
99 "freebsd",
100 "nacl",
101 "netbsd",
102 "openbsd",
103 "plan9",
104 "windows",
105 "aix",
106 }
107
108
109 func xinit() {
110 b := os.Getenv("GOROOT")
111 if b == "" {
112 fatalf("$GOROOT must be set")
113 }
114 goroot = filepath.Clean(b)
115 gorootBin = pathf("%s/bin", goroot)
116
117
118
119
120
121 gorootBinGo = pathf("%s/bin/go", goroot)
122
123 b = os.Getenv("GOOS")
124 if b == "" {
125 b = gohostos
126 }
127 goos = b
128 if slices.Index(okgoos, goos) < 0 {
129 fatalf("unknown $GOOS %s", goos)
130 }
131
132 b = os.Getenv("GOARM")
133 if b == "" {
134 b = xgetgoarm()
135 }
136 goarm = b
137
138 b = os.Getenv("GOARM64")
139 if b == "" {
140 b = "v8.0"
141 }
142 goarm64 = b
143
144 b = os.Getenv("GO386")
145 if b == "" {
146 b = "sse2"
147 }
148 go386 = b
149
150 b = os.Getenv("GOAMD64")
151 if b == "" {
152 b = "v1"
153 }
154 goamd64 = b
155
156 b = os.Getenv("GOMIPS")
157 if b == "" {
158 b = "hardfloat"
159 }
160 gomips = b
161
162 b = os.Getenv("GOMIPS64")
163 if b == "" {
164 b = "hardfloat"
165 }
166 gomips64 = b
167
168 b = os.Getenv("GOPPC64")
169 if b == "" {
170 b = "power8"
171 }
172 goppc64 = b
173
174 b = os.Getenv("GORISCV64")
175 if b == "" {
176 b = "rva20u64"
177 }
178 goriscv64 = b
179
180 b = os.Getenv("GOFIPS140")
181 if b == "" {
182 b = "off"
183 }
184 gofips140 = b
185
186 if p := pathf("%s/src/all.bash", goroot); !isfile(p) {
187 fatalf("$GOROOT is not set correctly or not exported\n"+
188 "\tGOROOT=%s\n"+
189 "\t%s does not exist", goroot, p)
190 }
191
192 b = os.Getenv("GOHOSTARCH")
193 if b != "" {
194 gohostarch = b
195 }
196 if slices.Index(okgoarch, gohostarch) < 0 {
197 fatalf("unknown $GOHOSTARCH %s", gohostarch)
198 }
199
200 b = os.Getenv("GOARCH")
201 if b == "" {
202 b = gohostarch
203 }
204 goarch = b
205 if slices.Index(okgoarch, goarch) < 0 {
206 fatalf("unknown $GOARCH %s", goarch)
207 }
208
209 b = os.Getenv("GO_EXTLINK_ENABLED")
210 if b != "" {
211 if b != "0" && b != "1" {
212 fatalf("unknown $GO_EXTLINK_ENABLED %s", b)
213 }
214 goextlinkenabled = b
215 }
216
217 goexperiment = os.Getenv("GOEXPERIMENT")
218
219
220 gogcflags = os.Getenv("BOOT_GO_GCFLAGS")
221 goldflags = os.Getenv("BOOT_GO_LDFLAGS")
222
223 defaultcc = compilerEnv("CC", "")
224 defaultcxx = compilerEnv("CXX", "")
225
226 b = os.Getenv("PKG_CONFIG")
227 if b == "" {
228 b = "pkg-config"
229 }
230 defaultpkgconfig = b
231
232 defaultldso = os.Getenv("GO_LDSO")
233
234
235 os.Setenv("GO386", go386)
236 os.Setenv("GOAMD64", goamd64)
237 os.Setenv("GOARCH", goarch)
238 os.Setenv("GOARM", goarm)
239 os.Setenv("GOARM64", goarm64)
240 os.Setenv("GOHOSTARCH", gohostarch)
241 os.Setenv("GOHOSTOS", gohostos)
242 os.Setenv("GOOS", goos)
243 os.Setenv("GOMIPS", gomips)
244 os.Setenv("GOMIPS64", gomips64)
245 os.Setenv("GOPPC64", goppc64)
246 os.Setenv("GORISCV64", goriscv64)
247 os.Setenv("GOROOT", goroot)
248 os.Setenv("GOFIPS140", gofips140)
249
250
251
252
253
254 os.Setenv("GOBIN", gorootBin)
255
256
257 os.Setenv("LANG", "C")
258 os.Setenv("LANGUAGE", "en_US.UTF8")
259 os.Unsetenv("GO111MODULE")
260 os.Setenv("GOENV", "off")
261 os.Unsetenv("GOFLAGS")
262 os.Setenv("GOWORK", "off")
263
264
265
266
267 modVer := goModVersion()
268 workdir = xworkdir()
269 if err := os.WriteFile(pathf("%s/go.mod", workdir), []byte("module bootstrap\n\ngo "+modVer+"\n"), 0666); err != nil {
270 fatalf("cannot write stub go.mod: %s", err)
271 }
272 xatexit(rmworkdir)
273
274 tooldir = pathf("%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch)
275
276 goversion := findgoversion()
277 isRelease = (strings.HasPrefix(goversion, "release.") || strings.HasPrefix(goversion, "go")) &&
278 !strings.Contains(goversion, "devel")
279 }
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298 func compilerEnv(envName, def string) map[string]string {
299 m := map[string]string{"": def}
300
301 if env := os.Getenv(envName); env != "" {
302 m[""] = env
303 }
304 if env := os.Getenv(envName + "_FOR_TARGET"); env != "" {
305 if gohostos != goos || gohostarch != goarch {
306 m[gohostos+"/"+gohostarch] = m[""]
307 }
308 m[""] = env
309 }
310
311 for _, goos := range okgoos {
312 for _, goarch := range okgoarch {
313 if env := os.Getenv(envName + "_FOR_" + goos + "_" + goarch); env != "" {
314 m[goos+"/"+goarch] = env
315 }
316 }
317 }
318
319 return m
320 }
321
322
323 var clangos = []string{
324 "darwin", "ios",
325 "freebsd",
326 "openbsd",
327 }
328
329
330
331 func compilerEnvLookup(kind string, m map[string]string, goos, goarch string) string {
332 if !needCC() {
333 return ""
334 }
335 if cc := m[goos+"/"+goarch]; cc != "" {
336 return cc
337 }
338 if cc := m[""]; cc != "" {
339 return cc
340 }
341 for _, os := range clangos {
342 if goos == os {
343 if kind == "CXX" {
344 return "clang++"
345 }
346 return "clang"
347 }
348 }
349 if kind == "CXX" {
350 return "g++"
351 }
352 return "gcc"
353 }
354
355
356 func rmworkdir() {
357 if vflag > 1 {
358 errprintf("rm -rf %s\n", workdir)
359 }
360 xremoveall(workdir)
361 }
362
363
364 func chomp(s string) string {
365 return strings.TrimRight(s, " \t\r\n")
366 }
367
368
369
370 func findgoversion() string {
371
372
373 path := pathf("%s/VERSION", goroot)
374 if isfile(path) {
375 b := chomp(readfile(path))
376
377
378
379
380 if i := strings.Index(b, "\n"); i >= 0 {
381 rest := b[i+1:]
382 b = chomp(b[:i])
383 for _, line := range strings.Split(rest, "\n") {
384 f := strings.Fields(line)
385 if len(f) == 0 {
386 continue
387 }
388 switch f[0] {
389 default:
390 fatalf("VERSION: unexpected line: %s", line)
391 case "time":
392 if len(f) != 2 {
393 fatalf("VERSION: unexpected time line: %s", line)
394 }
395 _, err := time.Parse(time.RFC3339, f[1])
396 if err != nil {
397 fatalf("VERSION: bad time: %s", err)
398 }
399 }
400 }
401 }
402
403
404
405
406
407
408 if b != "" {
409 return b
410 }
411 }
412
413
414
415
416 path = pathf("%s/VERSION.cache", goroot)
417 if isfile(path) {
418 return chomp(readfile(path))
419 }
420
421
422 if !isGitRepo() {
423 fatalf("FAILED: not a Git repo; must put a VERSION file in $GOROOT")
424 }
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439 goversionSource := readfile(pathf("%s/src/internal/goversion/goversion.go", goroot))
440 m := regexp.MustCompile(`(?m)^const Version = (\d+)`).FindStringSubmatch(goversionSource)
441 if m == nil {
442 fatalf("internal/goversion/goversion.go does not contain 'const Version = ...'")
443 }
444 version := fmt.Sprintf("go1.%s-devel_", m[1])
445 version += chomp(run(goroot, CheckExit, "git", "log", "-n", "1", "--format=format:%h %cd", "HEAD"))
446
447
448 writefile(version, path, 0)
449
450 return version
451 }
452
453
454
455
456 func goModVersion() string {
457 goMod := readfile(pathf("%s/src/go.mod", goroot))
458 m := regexp.MustCompile(`(?m)^go (1.\d+)$`).FindStringSubmatch(goMod)
459 if m == nil {
460 fatalf("std go.mod does not contain go 1.X")
461 }
462 return m[1]
463 }
464
465 func requiredBootstrapVersion(v string) string {
466 minorstr, ok := strings.CutPrefix(v, "1.")
467 if !ok {
468 fatalf("go version %q in go.mod does not start with %q", v, "1.")
469 }
470 minor, err := strconv.Atoi(minorstr)
471 if err != nil {
472 fatalf("invalid go version minor component %q: %v", minorstr, err)
473 }
474
475
476 requiredMinor := minor - 2 - minor%2
477 return "1." + strconv.Itoa(requiredMinor)
478 }
479
480
481 func isGitRepo() bool {
482
483
484
485 gitDir := chomp(run(goroot, 0, "git", "rev-parse", "--git-dir"))
486 if !filepath.IsAbs(gitDir) {
487 gitDir = filepath.Join(goroot, gitDir)
488 }
489 return isdir(gitDir)
490 }
491
492
495
496
497 var oldtool = []string{
498 "5a", "5c", "5g", "5l",
499 "6a", "6c", "6g", "6l",
500 "8a", "8c", "8g", "8l",
501 "9a", "9c", "9g", "9l",
502 "6cov",
503 "6nm",
504 "6prof",
505 "cgo",
506 "ebnflint",
507 "goapi",
508 "gofix",
509 "goinstall",
510 "gomake",
511 "gopack",
512 "gopprof",
513 "gotest",
514 "gotype",
515 "govet",
516 "goyacc",
517 "quietgcc",
518 }
519
520
521
522 var unreleased = []string{
523 "src/cmd/newlink",
524 "src/cmd/objwriter",
525 "src/debug/goobj",
526 "src/old",
527 }
528
529
530 func setup() {
531
532 if p := pathf("%s/bin", goroot); !isdir(p) {
533 xmkdir(p)
534 }
535
536
537 if p := pathf("%s/pkg", goroot); !isdir(p) {
538 xmkdir(p)
539 }
540
541 goosGoarch := pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch)
542 if rebuildall {
543 xremoveall(goosGoarch)
544 }
545 xmkdirall(goosGoarch)
546 xatexit(func() {
547 if files := xreaddir(goosGoarch); len(files) == 0 {
548 xremove(goosGoarch)
549 }
550 })
551
552 if goos != gohostos || goarch != gohostarch {
553 p := pathf("%s/pkg/%s_%s", goroot, goos, goarch)
554 if rebuildall {
555 xremoveall(p)
556 }
557 xmkdirall(p)
558 }
559
560
561
562
563
564
565 obj := pathf("%s/pkg/obj", goroot)
566 if !isdir(obj) {
567 xmkdir(obj)
568 }
569 xatexit(func() { xremove(obj) })
570
571
572 objGobuild := pathf("%s/pkg/obj/go-build", goroot)
573 if rebuildall {
574 xremoveall(objGobuild)
575 }
576 xmkdirall(objGobuild)
577 xatexit(func() { xremoveall(objGobuild) })
578
579
580 objGoBootstrap := pathf("%s/pkg/obj/go-bootstrap", goroot)
581 if rebuildall {
582 xremoveall(objGoBootstrap)
583 }
584 xmkdirall(objGoBootstrap)
585 xatexit(func() { xremoveall(objGoBootstrap) })
586
587
588
589 if rebuildall {
590 xremoveall(tooldir)
591 }
592 xmkdirall(tooldir)
593
594
595 xremoveall(pathf("%s/bin/tool", goroot))
596
597
598 for _, old := range oldtool {
599 xremove(pathf("%s/bin/%s", goroot, old))
600 }
601
602
603 if isRelease {
604
605 for _, dir := range unreleased {
606 if p := pathf("%s/%s", goroot, dir); isdir(p) {
607 fatalf("%s should not exist in release build", p)
608 }
609 }
610 }
611 }
612
613
616
617
618
619
620 func mustLinkExternal(goos, goarch string, cgoEnabled bool) bool {
621 if cgoEnabled {
622 switch goarch {
623 case "mips", "mipsle", "mips64", "mips64le":
624
625
626 return true
627 case "arm64":
628 if goos == "windows" {
629
630 return true
631 }
632 case "ppc64":
633
634 if goos == "aix" || goos == "linux" {
635 return true
636 }
637 }
638
639 switch goos {
640 case "android":
641 return true
642 case "dragonfly":
643
644
645
646 return true
647 }
648 }
649
650 switch goos {
651 case "android":
652 if goarch != "arm64" {
653 return true
654 }
655 case "ios":
656 if goarch == "arm64" {
657 return true
658 }
659 }
660 return false
661 }
662
663
664 var depsuffix = []string{
665 ".s",
666 ".go",
667 }
668
669
670
671 var gentab = []struct {
672 pkg string
673 file string
674 gen func(dir, file string)
675 }{
676 {"cmd/go/internal/cfg", "zdefaultcc.go", mkzdefaultcc},
677 {"internal/runtime/sys", "zversion.go", mkzversion},
678 {"time/tzdata", "zzipdata.go", mktzdata},
679 }
680
681
682
683 var installed = make(map[string]chan struct{})
684 var installedMu sync.Mutex
685
686 func install(dir string) {
687 <-startInstall(dir)
688 }
689
690 func startInstall(dir string) chan struct{} {
691 installedMu.Lock()
692 ch := installed[dir]
693 if ch == nil {
694 ch = make(chan struct{})
695 installed[dir] = ch
696 go runInstall(dir, ch)
697 }
698 installedMu.Unlock()
699 return ch
700 }
701
702
703
704 func runInstall(pkg string, ch chan struct{}) {
705 if pkg == "net" || pkg == "os/user" || pkg == "crypto/x509" {
706 fatalf("go_bootstrap cannot depend on cgo package %s", pkg)
707 }
708
709 defer close(ch)
710
711 if pkg == "unsafe" {
712 return
713 }
714
715 if vflag > 0 {
716 if goos != gohostos || goarch != gohostarch {
717 errprintf("%s (%s/%s)\n", pkg, goos, goarch)
718 } else {
719 errprintf("%s\n", pkg)
720 }
721 }
722
723 workdir := pathf("%s/%s", workdir, pkg)
724 xmkdirall(workdir)
725
726 var clean []string
727 defer func() {
728 for _, name := range clean {
729 xremove(name)
730 }
731 }()
732
733
734 dir := pathf("%s/src/%s", goroot, pkg)
735 name := filepath.Base(dir)
736
737
738
739
740 ispkg := !strings.HasPrefix(pkg, "cmd/") || strings.Contains(pkg, "/internal/") || strings.Contains(pkg, "/vendor/")
741
742
743
744 var (
745 link []string
746 targ int
747 ispackcmd bool
748 )
749 if ispkg {
750
751 ispackcmd = true
752 link = []string{"pack", packagefile(pkg)}
753 targ = len(link) - 1
754 xmkdirall(filepath.Dir(link[targ]))
755 } else {
756
757 elem := name
758 if elem == "go" {
759 elem = "go_bootstrap"
760 }
761 link = []string{pathf("%s/link", tooldir)}
762 if goos == "android" {
763 link = append(link, "-buildmode=pie")
764 }
765 if goldflags != "" {
766 link = append(link, goldflags)
767 }
768 link = append(link, "-extld="+compilerEnvLookup("CC", defaultcc, goos, goarch))
769 link = append(link, "-L="+pathf("%s/pkg/obj/go-bootstrap/%s_%s", goroot, goos, goarch))
770 link = append(link, "-o", pathf("%s/%s%s", tooldir, elem, exe))
771 targ = len(link) - 1
772 }
773 ttarg := mtime(link[targ])
774
775
776
777
778 files := xreaddir(dir)
779
780
781
782
783
784
785 files = filter(files, func(p string) bool {
786 return !strings.HasPrefix(p, ".") && (!strings.HasPrefix(p, "_") || !strings.HasSuffix(p, ".go"))
787 })
788
789
790 for _, gt := range gentab {
791 if gt.pkg == pkg {
792 files = append(files, gt.file)
793 }
794 }
795 files = uniq(files)
796
797
798 for i, p := range files {
799 if !filepath.IsAbs(p) {
800 files[i] = pathf("%s/%s", dir, p)
801 }
802 }
803
804
805 var gofiles, sfiles []string
806 stale := rebuildall
807 files = filter(files, func(p string) bool {
808 for _, suf := range depsuffix {
809 if strings.HasSuffix(p, suf) {
810 goto ok
811 }
812 }
813 return false
814 ok:
815 t := mtime(p)
816 if !t.IsZero() && !strings.HasSuffix(p, ".a") && !shouldbuild(p, pkg) {
817 return false
818 }
819 if strings.HasSuffix(p, ".go") {
820 gofiles = append(gofiles, p)
821 } else if strings.HasSuffix(p, ".s") {
822 sfiles = append(sfiles, p)
823 }
824 if t.After(ttarg) {
825 stale = true
826 }
827 return true
828 })
829
830
831 if len(files) == 0 {
832 return
833 }
834
835 if !stale {
836 return
837 }
838
839
840 if pkg == "runtime" {
841 xmkdirall(pathf("%s/pkg/include", goroot))
842
843 copyfile(pathf("%s/pkg/include/textflag.h", goroot),
844 pathf("%s/src/runtime/textflag.h", goroot), 0)
845 copyfile(pathf("%s/pkg/include/funcdata.h", goroot),
846 pathf("%s/src/runtime/funcdata.h", goroot), 0)
847 copyfile(pathf("%s/pkg/include/asm_ppc64x.h", goroot),
848 pathf("%s/src/runtime/asm_ppc64x.h", goroot), 0)
849 copyfile(pathf("%s/pkg/include/asm_amd64.h", goroot),
850 pathf("%s/src/runtime/asm_amd64.h", goroot), 0)
851 copyfile(pathf("%s/pkg/include/asm_riscv64.h", goroot),
852 pathf("%s/src/runtime/asm_riscv64.h", goroot), 0)
853 }
854
855
856 for _, gt := range gentab {
857 if gt.pkg != pkg {
858 continue
859 }
860 p := pathf("%s/%s", dir, gt.file)
861 if vflag > 1 {
862 errprintf("generate %s\n", p)
863 }
864 gt.gen(dir, p)
865
866
867
868
869
870
871
872 }
873
874
875
876 importMap := make(map[string]string)
877 for _, p := range gofiles {
878 for _, imp := range readimports(p) {
879 if imp == "C" {
880 fatalf("%s imports C", p)
881 }
882 importMap[imp] = resolveVendor(imp, dir)
883 }
884 }
885 sortedImports := make([]string, 0, len(importMap))
886 for imp := range importMap {
887 sortedImports = append(sortedImports, imp)
888 }
889 sort.Strings(sortedImports)
890
891 for _, dep := range importMap {
892 if dep == "C" {
893 fatalf("%s imports C", pkg)
894 }
895 startInstall(dep)
896 }
897 for _, dep := range importMap {
898 install(dep)
899 }
900
901 if goos != gohostos || goarch != gohostarch {
902
903 if vflag > 1 {
904 errprintf("skip build for cross-compile %s\n", pkg)
905 }
906 return
907 }
908
909 asmArgs := []string{
910 pathf("%s/asm", tooldir),
911 "-I", workdir,
912 "-I", pathf("%s/pkg/include", goroot),
913 "-D", "GOOS_" + goos,
914 "-D", "GOARCH_" + goarch,
915 "-D", "GOOS_GOARCH_" + goos + "_" + goarch,
916 "-p", pkg,
917 }
918 if goarch == "mips" || goarch == "mipsle" {
919
920 asmArgs = append(asmArgs, "-D", "GOMIPS_"+gomips)
921 }
922 if goarch == "mips64" || goarch == "mips64le" {
923
924 asmArgs = append(asmArgs, "-D", "GOMIPS64_"+gomips64)
925 }
926 if goarch == "ppc64" || goarch == "ppc64le" {
927
928 switch goppc64 {
929 case "power10":
930 asmArgs = append(asmArgs, "-D", "GOPPC64_power10")
931 fallthrough
932 case "power9":
933 asmArgs = append(asmArgs, "-D", "GOPPC64_power9")
934 fallthrough
935 default:
936 asmArgs = append(asmArgs, "-D", "GOPPC64_power8")
937 }
938 }
939 if goarch == "riscv64" {
940
941 asmArgs = append(asmArgs, "-D", "GORISCV64_"+goriscv64)
942 }
943 if goarch == "arm" {
944
945
946 switch {
947 case strings.Contains(goarm, "7"):
948 asmArgs = append(asmArgs, "-D", "GOARM_7")
949 fallthrough
950 case strings.Contains(goarm, "6"):
951 asmArgs = append(asmArgs, "-D", "GOARM_6")
952 fallthrough
953 default:
954 asmArgs = append(asmArgs, "-D", "GOARM_5")
955 }
956 }
957 goasmh := pathf("%s/go_asm.h", workdir)
958
959
960 var symabis string
961 if len(sfiles) > 0 {
962 symabis = pathf("%s/symabis", workdir)
963 var wg sync.WaitGroup
964 asmabis := append(asmArgs[:len(asmArgs):len(asmArgs)], "-gensymabis", "-o", symabis)
965 asmabis = append(asmabis, sfiles...)
966 if err := os.WriteFile(goasmh, nil, 0666); err != nil {
967 fatalf("cannot write empty go_asm.h: %s", err)
968 }
969 bgrun(&wg, dir, asmabis...)
970 bgwait(&wg)
971 }
972
973
974 buf := &bytes.Buffer{}
975 for _, imp := range sortedImports {
976 if imp == "unsafe" {
977 continue
978 }
979 dep := importMap[imp]
980 if imp != dep {
981 fmt.Fprintf(buf, "importmap %s=%s\n", imp, dep)
982 }
983 fmt.Fprintf(buf, "packagefile %s=%s\n", dep, packagefile(dep))
984 }
985 importcfg := pathf("%s/importcfg", workdir)
986 if err := os.WriteFile(importcfg, buf.Bytes(), 0666); err != nil {
987 fatalf("cannot write importcfg file: %v", err)
988 }
989
990 var archive string
991
992
993
994
995 pkgName := pkg
996 if strings.HasPrefix(pkg, "cmd/") && strings.Count(pkg, "/") == 1 {
997 pkgName = "main"
998 }
999 b := pathf("%s/_go_.a", workdir)
1000 clean = append(clean, b)
1001 if !ispackcmd {
1002 link = append(link, b)
1003 } else {
1004 archive = b
1005 }
1006
1007
1008 compile := []string{pathf("%s/compile", tooldir), "-std", "-pack", "-o", b, "-p", pkgName, "-importcfg", importcfg}
1009 if gogcflags != "" {
1010 compile = append(compile, strings.Fields(gogcflags)...)
1011 }
1012 if len(sfiles) > 0 {
1013 compile = append(compile, "-asmhdr", goasmh)
1014 }
1015 if symabis != "" {
1016 compile = append(compile, "-symabis", symabis)
1017 }
1018 if goos == "android" {
1019 compile = append(compile, "-shared")
1020 }
1021
1022 compile = append(compile, gofiles...)
1023 var wg sync.WaitGroup
1024
1025
1026
1027 bgrun(&wg, dir, compile...)
1028 bgwait(&wg)
1029
1030
1031 for _, p := range sfiles {
1032
1033 compile := asmArgs[:len(asmArgs):len(asmArgs)]
1034
1035 doclean := true
1036 b := pathf("%s/%s", workdir, filepath.Base(p))
1037
1038
1039 b = b[:len(b)-1] + "o"
1040 compile = append(compile, "-o", b, p)
1041 bgrun(&wg, dir, compile...)
1042
1043 link = append(link, b)
1044 if doclean {
1045 clean = append(clean, b)
1046 }
1047 }
1048 bgwait(&wg)
1049
1050 if ispackcmd {
1051 xremove(link[targ])
1052 dopack(link[targ], archive, link[targ+1:])
1053 return
1054 }
1055
1056
1057 xremove(link[targ])
1058 bgrun(&wg, "", link...)
1059 bgwait(&wg)
1060 }
1061
1062
1063
1064 func packagefile(pkg string) string {
1065 return pathf("%s/pkg/obj/go-bootstrap/%s_%s/%s.a", goroot, goos, goarch, pkg)
1066 }
1067
1068
1069
1070 var unixOS = map[string]bool{
1071 "aix": true,
1072 "android": true,
1073 "darwin": true,
1074 "dragonfly": true,
1075 "freebsd": true,
1076 "hurd": true,
1077 "illumos": true,
1078 "ios": true,
1079 "linux": true,
1080 "netbsd": true,
1081 "openbsd": true,
1082 "solaris": true,
1083 }
1084
1085
1086 func matchtag(tag string) bool {
1087 switch tag {
1088 case "gc", "cmd_go_bootstrap", "go1.1":
1089 return true
1090 case "linux":
1091 return goos == "linux" || goos == "android"
1092 case "solaris":
1093 return goos == "solaris" || goos == "illumos"
1094 case "darwin":
1095 return goos == "darwin" || goos == "ios"
1096 case goos, goarch:
1097 return true
1098 case "unix":
1099 return unixOS[goos]
1100 default:
1101 return false
1102 }
1103 }
1104
1105
1106
1107
1108
1109
1110
1111 func shouldbuild(file, pkg string) bool {
1112
1113 name := filepath.Base(file)
1114 excluded := func(list []string, ok string) bool {
1115 for _, x := range list {
1116 if x == ok || (ok == "android" && x == "linux") || (ok == "illumos" && x == "solaris") || (ok == "ios" && x == "darwin") {
1117 continue
1118 }
1119 i := strings.Index(name, x)
1120 if i <= 0 || name[i-1] != '_' {
1121 continue
1122 }
1123 i += len(x)
1124 if i == len(name) || name[i] == '.' || name[i] == '_' {
1125 return true
1126 }
1127 }
1128 return false
1129 }
1130 if excluded(okgoos, goos) || excluded(okgoarch, goarch) {
1131 return false
1132 }
1133
1134
1135 if strings.Contains(name, "_test") {
1136 return false
1137 }
1138
1139
1140 for _, p := range strings.Split(readfile(file), "\n") {
1141 p = strings.TrimSpace(p)
1142 if p == "" {
1143 continue
1144 }
1145 code := p
1146 i := strings.Index(code, "//")
1147 if i > 0 {
1148 code = strings.TrimSpace(code[:i])
1149 }
1150 if code == "package documentation" {
1151 return false
1152 }
1153 if code == "package main" && pkg != "cmd/go" && pkg != "cmd/cgo" {
1154 return false
1155 }
1156 if !strings.HasPrefix(p, "//") {
1157 break
1158 }
1159 if strings.HasPrefix(p, "//go:build ") {
1160 matched, err := matchexpr(p[len("//go:build "):])
1161 if err != nil {
1162 errprintf("%s: %v", file, err)
1163 }
1164 return matched
1165 }
1166 }
1167
1168 return true
1169 }
1170
1171
1172 func copyfile(dst, src string, flag int) {
1173 if vflag > 1 {
1174 errprintf("cp %s %s\n", src, dst)
1175 }
1176 writefile(readfile(src), dst, flag)
1177 }
1178
1179
1180
1181
1182 func dopack(dst, src string, extra []string) {
1183 bdst := bytes.NewBufferString(readfile(src))
1184 for _, file := range extra {
1185 b := readfile(file)
1186
1187 i := strings.LastIndex(file, "/") + 1
1188 j := strings.LastIndex(file, `\`) + 1
1189 if i < j {
1190 i = j
1191 }
1192 fmt.Fprintf(bdst, "%-16.16s%-12d%-6d%-6d%-8o%-10d`\n", file[i:], 0, 0, 0, 0644, len(b))
1193 bdst.WriteString(b)
1194 if len(b)&1 != 0 {
1195 bdst.WriteByte(0)
1196 }
1197 }
1198 writefile(bdst.String(), dst, 0)
1199 }
1200
1201 func clean() {
1202 generated := []byte(generatedHeader)
1203
1204
1205 filepath.WalkDir(pathf("%s/src", goroot), func(path string, d fs.DirEntry, err error) error {
1206 switch {
1207 case err != nil:
1208
1209 case d.IsDir() && (d.Name() == "vendor" || d.Name() == "testdata"):
1210 return filepath.SkipDir
1211 case d.IsDir() && d.Name() != "dist":
1212
1213 exe := filepath.Join(path, d.Name())
1214 if info, err := os.Stat(exe); err == nil && !info.IsDir() {
1215 xremove(exe)
1216 }
1217 xremove(exe + ".exe")
1218 case !d.IsDir() && strings.HasPrefix(d.Name(), "z"):
1219
1220 head := make([]byte, 512)
1221 if f, err := os.Open(path); err == nil {
1222 io.ReadFull(f, head)
1223 f.Close()
1224 }
1225 if bytes.HasPrefix(head, generated) {
1226 xremove(path)
1227 }
1228 }
1229 return nil
1230 })
1231
1232 if rebuildall {
1233
1234 xremoveall(pathf("%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch))
1235
1236
1237 xremoveall(pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch))
1238 xremoveall(pathf("%s/pkg/%s_%s", goroot, goos, goarch))
1239 xremoveall(pathf("%s/pkg/%s_%s_race", goroot, gohostos, gohostarch))
1240 xremoveall(pathf("%s/pkg/%s_%s_race", goroot, goos, goarch))
1241 xremoveall(tooldir)
1242
1243
1244 xremove(pathf("%s/VERSION.cache", goroot))
1245
1246
1247 xremoveall(pathf("%s/pkg/distpack", goroot))
1248 }
1249 }
1250
1251
1254
1255
1256 func cmdenv() {
1257 path := flag.Bool("p", false, "emit updated PATH")
1258 plan9 := flag.Bool("9", gohostos == "plan9", "emit plan 9 syntax")
1259 windows := flag.Bool("w", gohostos == "windows", "emit windows syntax")
1260 xflagparse(0)
1261
1262 format := "%s=\"%s\";\n"
1263 switch {
1264 case *plan9:
1265 format = "%s='%s'\n"
1266 case *windows:
1267 format = "set %s=%s\r\n"
1268 }
1269
1270 xprintf(format, "GO111MODULE", "")
1271 xprintf(format, "GOARCH", goarch)
1272 xprintf(format, "GOBIN", gorootBin)
1273 xprintf(format, "GODEBUG", os.Getenv("GODEBUG"))
1274 xprintf(format, "GOENV", "off")
1275 xprintf(format, "GOFLAGS", "")
1276 xprintf(format, "GOHOSTARCH", gohostarch)
1277 xprintf(format, "GOHOSTOS", gohostos)
1278 xprintf(format, "GOOS", goos)
1279 xprintf(format, "GOPROXY", os.Getenv("GOPROXY"))
1280 xprintf(format, "GOROOT", goroot)
1281 xprintf(format, "GOTMPDIR", os.Getenv("GOTMPDIR"))
1282 xprintf(format, "GOTOOLDIR", tooldir)
1283 if goarch == "arm" {
1284 xprintf(format, "GOARM", goarm)
1285 }
1286 if goarch == "arm64" {
1287 xprintf(format, "GOARM64", goarm64)
1288 }
1289 if goarch == "386" {
1290 xprintf(format, "GO386", go386)
1291 }
1292 if goarch == "amd64" {
1293 xprintf(format, "GOAMD64", goamd64)
1294 }
1295 if goarch == "mips" || goarch == "mipsle" {
1296 xprintf(format, "GOMIPS", gomips)
1297 }
1298 if goarch == "mips64" || goarch == "mips64le" {
1299 xprintf(format, "GOMIPS64", gomips64)
1300 }
1301 if goarch == "ppc64" || goarch == "ppc64le" {
1302 xprintf(format, "GOPPC64", goppc64)
1303 }
1304 if goarch == "riscv64" {
1305 xprintf(format, "GORISCV64", goriscv64)
1306 }
1307 xprintf(format, "GOWORK", "off")
1308
1309 if *path {
1310 sep := ":"
1311 if gohostos == "windows" {
1312 sep = ";"
1313 }
1314 xprintf(format, "PATH", fmt.Sprintf("%s%s%s", gorootBin, sep, os.Getenv("PATH")))
1315
1316
1317
1318
1319 var exportFormat string
1320 if !*windows && !*plan9 {
1321 exportFormat = "export " + format
1322 } else {
1323 exportFormat = format
1324 }
1325 xprintf(exportFormat, "DIST_UNMODIFIED_PATH", os.Getenv("PATH"))
1326 }
1327 }
1328
1329 var (
1330 timeLogEnabled = os.Getenv("GOBUILDTIMELOGFILE") != ""
1331 timeLogMu sync.Mutex
1332 timeLogFile *os.File
1333 timeLogStart time.Time
1334 )
1335
1336 func timelog(op, name string) {
1337 if !timeLogEnabled {
1338 return
1339 }
1340 timeLogMu.Lock()
1341 defer timeLogMu.Unlock()
1342 if timeLogFile == nil {
1343 f, err := os.OpenFile(os.Getenv("GOBUILDTIMELOGFILE"), os.O_RDWR|os.O_APPEND, 0666)
1344 if err != nil {
1345 log.Fatal(err)
1346 }
1347 buf := make([]byte, 100)
1348 n, _ := f.Read(buf)
1349 s := string(buf[:n])
1350 if i := strings.Index(s, "\n"); i >= 0 {
1351 s = s[:i]
1352 }
1353 i := strings.Index(s, " start")
1354 if i < 0 {
1355 log.Fatalf("time log %s does not begin with start line", os.Getenv("GOBUILDTIMELOGFILE"))
1356 }
1357 t, err := time.Parse(time.UnixDate, s[:i])
1358 if err != nil {
1359 log.Fatalf("cannot parse time log line %q: %v", s, err)
1360 }
1361 timeLogStart = t
1362 timeLogFile = f
1363 }
1364 t := time.Now()
1365 fmt.Fprintf(timeLogFile, "%s %+.1fs %s %s\n", t.Format(time.UnixDate), t.Sub(timeLogStart).Seconds(), op, name)
1366 }
1367
1368
1369
1370
1371
1372
1373 func toolenv() []string {
1374 var env []string
1375 if !mustLinkExternal(goos, goarch, false) {
1376
1377
1378
1379
1380 env = append(env, "CGO_ENABLED=0")
1381 }
1382 if isRelease || os.Getenv("GO_BUILDER_NAME") != "" {
1383
1384
1385
1386
1387
1388 env = append(env, "GOFLAGS=-trimpath -ldflags=-w -gcflags=cmd/...=-dwarf=false")
1389 }
1390 return env
1391 }
1392
1393 var (
1394 toolchain = []string{"cmd/asm", "cmd/cgo", "cmd/compile", "cmd/link", "cmd/preprofile"}
1395
1396
1397 binExesIncludedInDistpack = []string{"cmd/go", "cmd/gofmt"}
1398
1399
1400 toolsIncludedInDistpack = []string{"cmd/asm", "cmd/cgo", "cmd/compile", "cmd/cover", "cmd/link", "cmd/preprofile", "cmd/vet"}
1401
1402
1403
1404
1405
1406 toolsToInstall = slices.Concat(binExesIncludedInDistpack, toolsIncludedInDistpack)
1407 )
1408
1409
1410
1411
1412
1413
1414
1415
1416 func cmdbootstrap() {
1417 timelog("start", "dist bootstrap")
1418 defer timelog("end", "dist bootstrap")
1419
1420 var debug, distpack, force, noBanner, noClean bool
1421 flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all")
1422 flag.BoolVar(&debug, "d", debug, "enable debugging of bootstrap process")
1423 flag.BoolVar(&distpack, "distpack", distpack, "write distribution files to pkg/distpack")
1424 flag.BoolVar(&force, "force", force, "build even if the port is marked as broken")
1425 flag.BoolVar(&noBanner, "no-banner", noBanner, "do not print banner")
1426 flag.BoolVar(&noClean, "no-clean", noClean, "print deprecation warning")
1427
1428 xflagparse(0)
1429
1430 if noClean {
1431 xprintf("warning: --no-clean is deprecated and has no effect; use 'go install std cmd' instead\n")
1432 }
1433
1434
1435 if broken[goos+"/"+goarch] && !force {
1436 fatalf("build stopped because the port %s/%s is marked as broken\n\n"+
1437 "Use the -force flag to build anyway.\n", goos, goarch)
1438 }
1439
1440
1441
1442
1443
1444
1445 os.Setenv("GOPATH", pathf("%s/pkg/obj/gopath", goroot))
1446
1447
1448
1449
1450
1451 os.Setenv("GOPROXY", "off")
1452
1453
1454
1455
1456 oldgocache = os.Getenv("GOCACHE")
1457 os.Setenv("GOCACHE", pathf("%s/pkg/obj/go-build", goroot))
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471 os.Setenv("GOEXPERIMENT", "none")
1472
1473 if isdir(pathf("%s/src/pkg", goroot)) {
1474 fatalf("\n\n"+
1475 "The Go package sources have moved to $GOROOT/src.\n"+
1476 "*** %s still exists. ***\n"+
1477 "It probably contains stale files that may confuse the build.\n"+
1478 "Please (check what's there and) remove it and try again.\n"+
1479 "See https://golang.org/s/go14nopkg\n",
1480 pathf("%s/src/pkg", goroot))
1481 }
1482
1483 if rebuildall {
1484 clean()
1485 }
1486
1487 setup()
1488
1489 timelog("build", "toolchain1")
1490 checkCC()
1491 bootstrapBuildTools()
1492
1493
1494 oldBinFiles, err := filepath.Glob(pathf("%s/bin/*", goroot))
1495 if err != nil {
1496 fatalf("glob: %v", err)
1497 }
1498
1499
1500 oldgoos = goos
1501 oldgoarch = goarch
1502 goos = gohostos
1503 goarch = gohostarch
1504 os.Setenv("GOHOSTARCH", gohostarch)
1505 os.Setenv("GOHOSTOS", gohostos)
1506 os.Setenv("GOARCH", goarch)
1507 os.Setenv("GOOS", goos)
1508
1509 timelog("build", "go_bootstrap")
1510 xprintf("Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.\n")
1511 install("runtime")
1512 install("time/tzdata")
1513 install("cmd/go")
1514 if vflag > 0 {
1515 xprintf("\n")
1516 }
1517
1518 gogcflags = os.Getenv("GO_GCFLAGS")
1519 setNoOpt()
1520 goldflags = os.Getenv("GO_LDFLAGS")
1521 goBootstrap := pathf("%s/go_bootstrap", tooldir)
1522 if debug {
1523 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1524 copyfile(pathf("%s/compile1", tooldir), pathf("%s/compile", tooldir), writeExec)
1525 }
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543 timelog("build", "toolchain2")
1544 if vflag > 0 {
1545 xprintf("\n")
1546 }
1547 xprintf("Building Go toolchain2 using go_bootstrap and Go toolchain1.\n")
1548 os.Setenv("CC", compilerEnvLookup("CC", defaultcc, goos, goarch))
1549
1550 os.Setenv("GOEXPERIMENT", goexperiment)
1551
1552 goInstall(toolenv(), goBootstrap, append([]string{"-pgo=off"}, toolchain...)...)
1553 if debug {
1554 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1555 copyfile(pathf("%s/compile2", tooldir), pathf("%s/compile", tooldir), writeExec)
1556 }
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574 timelog("build", "toolchain3")
1575 if vflag > 0 {
1576 xprintf("\n")
1577 }
1578 xprintf("Building Go toolchain3 using go_bootstrap and Go toolchain2.\n")
1579 goInstall(toolenv(), goBootstrap, append([]string{"-a"}, toolchain...)...)
1580 if debug {
1581 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1582 copyfile(pathf("%s/compile3", tooldir), pathf("%s/compile", tooldir), writeExec)
1583 }
1584
1585
1586
1587
1588
1589
1590 if _, err := os.Stat(pathf("%s/VERSION", goroot)); err == nil {
1591
1592
1593
1594
1595
1596
1597 } else {
1598 os.Setenv("GOCACHE", oldgocache)
1599 }
1600
1601 if goos == oldgoos && goarch == oldgoarch {
1602
1603 timelog("build", "toolchain")
1604 if vflag > 0 {
1605 xprintf("\n")
1606 }
1607 xprintf("Building packages and commands for %s/%s.\n", goos, goarch)
1608 } else {
1609
1610
1611
1612 timelog("build", "host toolchain")
1613 if vflag > 0 {
1614 xprintf("\n")
1615 }
1616 xprintf("Building commands for host, %s/%s.\n", goos, goarch)
1617 goInstall(toolenv(), goBootstrap, toolsToInstall...)
1618 checkNotStale(toolenv(), goBootstrap, toolsToInstall...)
1619 checkNotStale(toolenv(), gorootBinGo, toolsToInstall...)
1620
1621 timelog("build", "target toolchain")
1622 if vflag > 0 {
1623 xprintf("\n")
1624 }
1625 goos = oldgoos
1626 goarch = oldgoarch
1627 os.Setenv("GOOS", goos)
1628 os.Setenv("GOARCH", goarch)
1629 os.Setenv("CC", compilerEnvLookup("CC", defaultcc, goos, goarch))
1630 xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch)
1631 }
1632 goInstall(nil, goBootstrap, "std")
1633 goInstall(toolenv(), goBootstrap, toolsToInstall...)
1634 checkNotStale(toolenv(), goBootstrap, toolchain...)
1635 checkNotStale(nil, goBootstrap, "std")
1636 checkNotStale(toolenv(), goBootstrap, toolsToInstall...)
1637 checkNotStale(nil, gorootBinGo, "std")
1638 checkNotStale(toolenv(), gorootBinGo, toolsToInstall...)
1639 if debug {
1640 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1641 checkNotStale(toolenv(), goBootstrap, toolchain...)
1642 copyfile(pathf("%s/compile4", tooldir), pathf("%s/compile", tooldir), writeExec)
1643 }
1644
1645
1646
1647 binFiles, err := filepath.Glob(pathf("%s/bin/*", goroot))
1648 if err != nil {
1649 fatalf("glob: %v", err)
1650 }
1651
1652 ok := map[string]bool{}
1653 for _, f := range oldBinFiles {
1654 ok[f] = true
1655 }
1656 for _, f := range binFiles {
1657 if gohostos == "darwin" && filepath.Base(f) == ".DS_Store" {
1658 continue
1659 }
1660 elem := strings.TrimSuffix(filepath.Base(f), ".exe")
1661 if !ok[f] && elem != "go" && elem != "gofmt" && elem != goos+"_"+goarch {
1662 fatalf("unexpected new file in $GOROOT/bin: %s", elem)
1663 }
1664 }
1665
1666
1667 xremove(pathf("%s/go_bootstrap"+exe, tooldir))
1668
1669 if goos == "android" {
1670
1671 xremove(pathf("%s/go_android_exec-adb-sync-status", os.TempDir()))
1672 }
1673
1674 if wrapperPath := wrapperPathFor(goos, goarch); wrapperPath != "" {
1675 oldcc := os.Getenv("CC")
1676 os.Setenv("GOOS", gohostos)
1677 os.Setenv("GOARCH", gohostarch)
1678 os.Setenv("CC", compilerEnvLookup("CC", defaultcc, gohostos, gohostarch))
1679 goCmd(nil, gorootBinGo, "build", "-o", pathf("%s/go_%s_%s_exec%s", gorootBin, goos, goarch, exe), wrapperPath)
1680
1681
1682 os.Setenv("GOOS", goos)
1683 os.Setenv("GOARCH", goarch)
1684 os.Setenv("CC", oldcc)
1685 }
1686
1687 if distpack {
1688 xprintf("Packaging archives for %s/%s.\n", goos, goarch)
1689 run("", ShowOutput|CheckExit, gorootBinGo, "tool", "distpack")
1690 }
1691
1692
1693 if !noBanner {
1694 banner()
1695 }
1696 }
1697
1698 func wrapperPathFor(goos, goarch string) string {
1699 switch {
1700 case goos == "android":
1701 if gohostos != "android" {
1702 return pathf("%s/misc/go_android_exec/main.go", goroot)
1703 }
1704 case goos == "ios":
1705 if gohostos != "ios" {
1706 return pathf("%s/misc/ios/go_ios_exec.go", goroot)
1707 }
1708 }
1709 return ""
1710 }
1711
1712 func goInstall(env []string, goBinary string, args ...string) {
1713 goCmd(env, goBinary, "install", args...)
1714 }
1715
1716 func appendCompilerFlags(args []string) []string {
1717 if gogcflags != "" {
1718 args = append(args, "-gcflags=all="+gogcflags)
1719 }
1720 if goldflags != "" {
1721 args = append(args, "-ldflags=all="+goldflags)
1722 }
1723 return args
1724 }
1725
1726 func goCmd(env []string, goBinary string, cmd string, args ...string) {
1727 goCmd := []string{goBinary, cmd}
1728 if noOpt {
1729 goCmd = append(goCmd, "-tags=noopt")
1730 }
1731 goCmd = appendCompilerFlags(goCmd)
1732 if vflag > 0 {
1733 goCmd = append(goCmd, "-v")
1734 }
1735
1736
1737 if gohostos == "plan9" && os.Getenv("sysname") == "vx32" {
1738 goCmd = append(goCmd, "-p=1")
1739 }
1740
1741 runEnv(workdir, ShowOutput|CheckExit, env, append(goCmd, args...)...)
1742 }
1743
1744 func checkNotStale(env []string, goBinary string, targets ...string) {
1745 goCmd := []string{goBinary, "list"}
1746 if noOpt {
1747 goCmd = append(goCmd, "-tags=noopt")
1748 }
1749 goCmd = appendCompilerFlags(goCmd)
1750 goCmd = append(goCmd, "-f={{if .Stale}}\tSTALE {{.ImportPath}}: {{.StaleReason}}{{end}}")
1751
1752 out := runEnv(workdir, CheckExit, env, append(goCmd, targets...)...)
1753 if strings.Contains(out, "\tSTALE ") {
1754 os.Setenv("GODEBUG", "gocachehash=1")
1755 for _, target := range []string{"internal/runtime/sys", "cmd/dist", "cmd/link"} {
1756 if strings.Contains(out, "STALE "+target) {
1757 run(workdir, ShowOutput|CheckExit, goBinary, "list", "-f={{.ImportPath}} {{.Stale}}", target)
1758 break
1759 }
1760 }
1761 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)
1762 }
1763 }
1764
1765
1766
1767
1768
1769
1770
1771
1772 var cgoEnabled = map[string]bool{
1773 "aix/ppc64": true,
1774 "darwin/amd64": true,
1775 "darwin/arm64": true,
1776 "dragonfly/amd64": true,
1777 "freebsd/386": true,
1778 "freebsd/amd64": true,
1779 "freebsd/arm": true,
1780 "freebsd/arm64": true,
1781 "freebsd/riscv64": true,
1782 "illumos/amd64": true,
1783 "linux/386": true,
1784 "linux/amd64": true,
1785 "linux/arm": true,
1786 "linux/arm64": true,
1787 "linux/loong64": true,
1788 "linux/ppc64": false,
1789 "linux/ppc64le": true,
1790 "linux/mips": true,
1791 "linux/mipsle": true,
1792 "linux/mips64": true,
1793 "linux/mips64le": true,
1794 "linux/riscv64": true,
1795 "linux/s390x": true,
1796 "linux/sparc64": true,
1797 "android/386": true,
1798 "android/amd64": true,
1799 "android/arm": true,
1800 "android/arm64": true,
1801 "ios/arm64": true,
1802 "ios/amd64": true,
1803 "js/wasm": false,
1804 "wasip1/wasm": false,
1805 "netbsd/386": true,
1806 "netbsd/amd64": true,
1807 "netbsd/arm": true,
1808 "netbsd/arm64": true,
1809 "openbsd/386": true,
1810 "openbsd/amd64": true,
1811 "openbsd/arm": true,
1812 "openbsd/arm64": true,
1813 "openbsd/mips64": true,
1814 "openbsd/ppc64": false,
1815 "openbsd/riscv64": true,
1816 "plan9/386": false,
1817 "plan9/amd64": false,
1818 "plan9/arm": false,
1819 "solaris/amd64": true,
1820 "windows/386": true,
1821 "windows/amd64": true,
1822 "windows/arm": false,
1823 "windows/arm64": true,
1824 }
1825
1826
1827
1828
1829
1830 var broken = map[string]bool{
1831 "linux/sparc64": true,
1832 "openbsd/mips64": true,
1833 "windows/arm": true,
1834 }
1835
1836
1837 var firstClass = map[string]bool{
1838 "darwin/amd64": true,
1839 "darwin/arm64": true,
1840 "linux/386": true,
1841 "linux/amd64": true,
1842 "linux/arm": true,
1843 "linux/arm64": true,
1844 "windows/386": true,
1845 "windows/amd64": true,
1846 }
1847
1848
1849
1850 func needCC() bool {
1851 return os.Getenv("CGO_ENABLED") == "1" || mustLinkExternal(gohostos, gohostarch, false)
1852 }
1853
1854 func checkCC() {
1855 if !needCC() {
1856 return
1857 }
1858 cc1 := defaultcc[""]
1859 if cc1 == "" {
1860 cc1 = "gcc"
1861 for _, os := range clangos {
1862 if gohostos == os {
1863 cc1 = "clang"
1864 break
1865 }
1866 }
1867 }
1868 cc, err := quotedSplit(cc1)
1869 if err != nil {
1870 fatalf("split CC: %v", err)
1871 }
1872 var ccHelp = append(cc, "--help")
1873
1874 if output, err := exec.Command(ccHelp[0], ccHelp[1:]...).CombinedOutput(); err != nil {
1875 outputHdr := ""
1876 if len(output) > 0 {
1877 outputHdr = "\nCommand output:\n\n"
1878 }
1879 fatalf("cannot invoke C compiler %q: %v\n\n"+
1880 "Go needs a system C compiler for use with cgo.\n"+
1881 "To set a C compiler, set CC=the-compiler.\n"+
1882 "To disable cgo, set CGO_ENABLED=0.\n%s%s", cc, err, outputHdr, output)
1883 }
1884 }
1885
1886 func defaulttarg() string {
1887
1888
1889
1890
1891 pwd := xgetwd()
1892 src := pathf("%s/src/", goroot)
1893 real_src := xrealwd(src)
1894 if !strings.HasPrefix(pwd, real_src) {
1895 fatalf("current directory %s is not under %s", pwd, real_src)
1896 }
1897 pwd = pwd[len(real_src):]
1898
1899 pwd = strings.TrimPrefix(pwd, "/")
1900
1901 return pwd
1902 }
1903
1904
1905 func cmdinstall() {
1906 xflagparse(-1)
1907
1908 if flag.NArg() == 0 {
1909 install(defaulttarg())
1910 }
1911
1912 for _, arg := range flag.Args() {
1913 install(arg)
1914 }
1915 }
1916
1917
1918 func cmdclean() {
1919 xflagparse(0)
1920 clean()
1921 }
1922
1923
1924 func cmdbanner() {
1925 xflagparse(0)
1926 banner()
1927 }
1928
1929 func banner() {
1930 if vflag > 0 {
1931 xprintf("\n")
1932 }
1933 xprintf("---\n")
1934 xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot)
1935 xprintf("Installed commands in %s\n", gorootBin)
1936
1937 if gohostos == "plan9" {
1938
1939 pid := strings.ReplaceAll(readfile("#c/pid"), " ", "")
1940 ns := fmt.Sprintf("/proc/%s/ns", pid)
1941 if !strings.Contains(readfile(ns), fmt.Sprintf("bind -b %s /bin", gorootBin)) {
1942 xprintf("*** You need to bind %s before /bin.\n", gorootBin)
1943 }
1944 } else {
1945
1946 pathsep := ":"
1947 if gohostos == "windows" {
1948 pathsep = ";"
1949 }
1950 path := os.Getenv("PATH")
1951 if p, ok := os.LookupEnv("DIST_UNMODIFIED_PATH"); ok {
1952
1953
1954
1955
1956 path = p
1957 }
1958 if !strings.Contains(pathsep+path+pathsep, pathsep+gorootBin+pathsep) {
1959 xprintf("*** You need to add %s to your PATH.\n", gorootBin)
1960 }
1961 }
1962 }
1963
1964
1965 func cmdversion() {
1966 xflagparse(0)
1967 xprintf("%s\n", findgoversion())
1968 }
1969
1970
1971 func cmdlist() {
1972 jsonFlag := flag.Bool("json", false, "produce JSON output")
1973 brokenFlag := flag.Bool("broken", false, "include broken ports")
1974 xflagparse(0)
1975
1976 var plats []string
1977 for p := range cgoEnabled {
1978 if broken[p] && !*brokenFlag {
1979 continue
1980 }
1981 plats = append(plats, p)
1982 }
1983 sort.Strings(plats)
1984
1985 if !*jsonFlag {
1986 for _, p := range plats {
1987 xprintf("%s\n", p)
1988 }
1989 return
1990 }
1991
1992 type jsonResult struct {
1993 GOOS string
1994 GOARCH string
1995 CgoSupported bool
1996 FirstClass bool
1997 Broken bool `json:",omitempty"`
1998 }
1999 var results []jsonResult
2000 for _, p := range plats {
2001 fields := strings.Split(p, "/")
2002 results = append(results, jsonResult{
2003 GOOS: fields[0],
2004 GOARCH: fields[1],
2005 CgoSupported: cgoEnabled[p],
2006 FirstClass: firstClass[p],
2007 Broken: broken[p],
2008 })
2009 }
2010 out, err := json.MarshalIndent(results, "", "\t")
2011 if err != nil {
2012 fatalf("json marshal error: %v", err)
2013 }
2014 if _, err := os.Stdout.Write(out); err != nil {
2015 fatalf("write failed: %v", err)
2016 }
2017 }
2018
2019 func setNoOpt() {
2020 for _, gcflag := range strings.Split(gogcflags, " ") {
2021 if gcflag == "-N" || gcflag == "-l" {
2022 noOpt = true
2023 break
2024 }
2025 }
2026 }
2027
View as plain text