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 "loong64", "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 toolchain = []string{"cmd/asm", "cmd/cgo", "cmd/compile", "cmd/link", "cmd/preprofile"}
1394
1395
1396
1397
1398
1399
1400
1401
1402 func cmdbootstrap() {
1403 timelog("start", "dist bootstrap")
1404 defer timelog("end", "dist bootstrap")
1405
1406 var debug, distpack, force, noBanner, noClean bool
1407 flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all")
1408 flag.BoolVar(&debug, "d", debug, "enable debugging of bootstrap process")
1409 flag.BoolVar(&distpack, "distpack", distpack, "write distribution files to pkg/distpack")
1410 flag.BoolVar(&force, "force", force, "build even if the port is marked as broken")
1411 flag.BoolVar(&noBanner, "no-banner", noBanner, "do not print banner")
1412 flag.BoolVar(&noClean, "no-clean", noClean, "print deprecation warning")
1413
1414 xflagparse(0)
1415
1416 if noClean {
1417 xprintf("warning: --no-clean is deprecated and has no effect; use 'go install std cmd' instead\n")
1418 }
1419
1420
1421 if broken[goos+"/"+goarch] && !force {
1422 fatalf("build stopped because the port %s/%s is marked as broken\n\n"+
1423 "Use the -force flag to build anyway.\n", goos, goarch)
1424 }
1425
1426
1427
1428
1429
1430
1431 os.Setenv("GOPATH", pathf("%s/pkg/obj/gopath", goroot))
1432
1433
1434
1435
1436
1437 os.Setenv("GOPROXY", "off")
1438
1439
1440
1441
1442 oldgocache = os.Getenv("GOCACHE")
1443 os.Setenv("GOCACHE", pathf("%s/pkg/obj/go-build", goroot))
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457 os.Setenv("GOEXPERIMENT", "none")
1458
1459 if debug {
1460
1461 toolchain = append(toolchain, "cmd/buildid")
1462 }
1463
1464 if isdir(pathf("%s/src/pkg", goroot)) {
1465 fatalf("\n\n"+
1466 "The Go package sources have moved to $GOROOT/src.\n"+
1467 "*** %s still exists. ***\n"+
1468 "It probably contains stale files that may confuse the build.\n"+
1469 "Please (check what's there and) remove it and try again.\n"+
1470 "See https://golang.org/s/go14nopkg\n",
1471 pathf("%s/src/pkg", goroot))
1472 }
1473
1474 if rebuildall {
1475 clean()
1476 }
1477
1478 setup()
1479
1480 timelog("build", "toolchain1")
1481 checkCC()
1482 bootstrapBuildTools()
1483
1484
1485 oldBinFiles, err := filepath.Glob(pathf("%s/bin/*", goroot))
1486 if err != nil {
1487 fatalf("glob: %v", err)
1488 }
1489
1490
1491 oldgoos = goos
1492 oldgoarch = goarch
1493 goos = gohostos
1494 goarch = gohostarch
1495 os.Setenv("GOHOSTARCH", gohostarch)
1496 os.Setenv("GOHOSTOS", gohostos)
1497 os.Setenv("GOARCH", goarch)
1498 os.Setenv("GOOS", goos)
1499
1500 timelog("build", "go_bootstrap")
1501 xprintf("Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.\n")
1502 install("runtime")
1503 install("time/tzdata")
1504 install("cmd/go")
1505 if vflag > 0 {
1506 xprintf("\n")
1507 }
1508
1509 gogcflags = os.Getenv("GO_GCFLAGS")
1510 setNoOpt()
1511 goldflags = os.Getenv("GO_LDFLAGS")
1512 goBootstrap := pathf("%s/go_bootstrap", tooldir)
1513 if debug {
1514 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1515 copyfile(pathf("%s/compile1", tooldir), pathf("%s/compile", tooldir), writeExec)
1516 }
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534 timelog("build", "toolchain2")
1535 if vflag > 0 {
1536 xprintf("\n")
1537 }
1538 xprintf("Building Go toolchain2 using go_bootstrap and Go toolchain1.\n")
1539 os.Setenv("CC", compilerEnvLookup("CC", defaultcc, goos, goarch))
1540
1541 os.Setenv("GOEXPERIMENT", goexperiment)
1542
1543 goInstall(toolenv(), goBootstrap, append([]string{"-pgo=off"}, toolchain...)...)
1544 if debug {
1545 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1546 copyfile(pathf("%s/compile2", tooldir), pathf("%s/compile", tooldir), writeExec)
1547 }
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565 timelog("build", "toolchain3")
1566 if vflag > 0 {
1567 xprintf("\n")
1568 }
1569 xprintf("Building Go toolchain3 using go_bootstrap and Go toolchain2.\n")
1570 goInstall(toolenv(), goBootstrap, append([]string{"-a"}, toolchain...)...)
1571 if debug {
1572 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1573 copyfile(pathf("%s/compile3", tooldir), pathf("%s/compile", tooldir), writeExec)
1574 }
1575
1576
1577
1578
1579
1580
1581 if _, err := os.Stat(pathf("%s/VERSION", goroot)); err == nil {
1582
1583
1584
1585
1586
1587
1588 } else {
1589 os.Setenv("GOCACHE", oldgocache)
1590 }
1591
1592 if goos == oldgoos && goarch == oldgoarch {
1593
1594 timelog("build", "toolchain")
1595 if vflag > 0 {
1596 xprintf("\n")
1597 }
1598 xprintf("Building packages and commands for %s/%s.\n", goos, goarch)
1599 } else {
1600
1601
1602
1603 timelog("build", "host toolchain")
1604 if vflag > 0 {
1605 xprintf("\n")
1606 }
1607 xprintf("Building commands for host, %s/%s.\n", goos, goarch)
1608 goInstall(toolenv(), goBootstrap, "cmd")
1609 checkNotStale(toolenv(), goBootstrap, "cmd")
1610 checkNotStale(toolenv(), gorootBinGo, "cmd")
1611
1612 timelog("build", "target toolchain")
1613 if vflag > 0 {
1614 xprintf("\n")
1615 }
1616 goos = oldgoos
1617 goarch = oldgoarch
1618 os.Setenv("GOOS", goos)
1619 os.Setenv("GOARCH", goarch)
1620 os.Setenv("CC", compilerEnvLookup("CC", defaultcc, goos, goarch))
1621 xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch)
1622 }
1623 goInstall(nil, goBootstrap, "std")
1624 goInstall(toolenv(), goBootstrap, "cmd")
1625 checkNotStale(toolenv(), goBootstrap, toolchain...)
1626 checkNotStale(nil, goBootstrap, "std")
1627 checkNotStale(toolenv(), goBootstrap, "cmd")
1628 checkNotStale(nil, gorootBinGo, "std")
1629 checkNotStale(toolenv(), gorootBinGo, "cmd")
1630 if debug {
1631 run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
1632 checkNotStale(toolenv(), goBootstrap, toolchain...)
1633 copyfile(pathf("%s/compile4", tooldir), pathf("%s/compile", tooldir), writeExec)
1634 }
1635
1636
1637
1638 binFiles, err := filepath.Glob(pathf("%s/bin/*", goroot))
1639 if err != nil {
1640 fatalf("glob: %v", err)
1641 }
1642
1643 ok := map[string]bool{}
1644 for _, f := range oldBinFiles {
1645 ok[f] = true
1646 }
1647 for _, f := range binFiles {
1648 if gohostos == "darwin" && filepath.Base(f) == ".DS_Store" {
1649 continue
1650 }
1651 elem := strings.TrimSuffix(filepath.Base(f), ".exe")
1652 if !ok[f] && elem != "go" && elem != "gofmt" && elem != goos+"_"+goarch {
1653 fatalf("unexpected new file in $GOROOT/bin: %s", elem)
1654 }
1655 }
1656
1657
1658 xremove(pathf("%s/go_bootstrap"+exe, tooldir))
1659
1660 if goos == "android" {
1661
1662 xremove(pathf("%s/go_android_exec-adb-sync-status", os.TempDir()))
1663 }
1664
1665 if wrapperPath := wrapperPathFor(goos, goarch); wrapperPath != "" {
1666 oldcc := os.Getenv("CC")
1667 os.Setenv("GOOS", gohostos)
1668 os.Setenv("GOARCH", gohostarch)
1669 os.Setenv("CC", compilerEnvLookup("CC", defaultcc, gohostos, gohostarch))
1670 goCmd(nil, gorootBinGo, "build", "-o", pathf("%s/go_%s_%s_exec%s", gorootBin, goos, goarch, exe), wrapperPath)
1671
1672
1673 os.Setenv("GOOS", goos)
1674 os.Setenv("GOARCH", goarch)
1675 os.Setenv("CC", oldcc)
1676 }
1677
1678 if distpack {
1679 xprintf("Packaging archives for %s/%s.\n", goos, goarch)
1680 run("", ShowOutput|CheckExit, pathf("%s/distpack", tooldir))
1681 }
1682
1683
1684 if !noBanner {
1685 banner()
1686 }
1687 }
1688
1689 func wrapperPathFor(goos, goarch string) string {
1690 switch {
1691 case goos == "android":
1692 if gohostos != "android" {
1693 return pathf("%s/misc/go_android_exec/main.go", goroot)
1694 }
1695 case goos == "ios":
1696 if gohostos != "ios" {
1697 return pathf("%s/misc/ios/go_ios_exec.go", goroot)
1698 }
1699 }
1700 return ""
1701 }
1702
1703 func goInstall(env []string, goBinary string, args ...string) {
1704 goCmd(env, goBinary, "install", args...)
1705 }
1706
1707 func appendCompilerFlags(args []string) []string {
1708 if gogcflags != "" {
1709 args = append(args, "-gcflags=all="+gogcflags)
1710 }
1711 if goldflags != "" {
1712 args = append(args, "-ldflags=all="+goldflags)
1713 }
1714 return args
1715 }
1716
1717 func goCmd(env []string, goBinary string, cmd string, args ...string) {
1718 goCmd := []string{goBinary, cmd}
1719 if noOpt {
1720 goCmd = append(goCmd, "-tags=noopt")
1721 }
1722 goCmd = appendCompilerFlags(goCmd)
1723 if vflag > 0 {
1724 goCmd = append(goCmd, "-v")
1725 }
1726
1727
1728 if gohostos == "plan9" && os.Getenv("sysname") == "vx32" {
1729 goCmd = append(goCmd, "-p=1")
1730 }
1731
1732 runEnv(workdir, ShowOutput|CheckExit, env, append(goCmd, args...)...)
1733 }
1734
1735 func checkNotStale(env []string, goBinary string, targets ...string) {
1736 goCmd := []string{goBinary, "list"}
1737 if noOpt {
1738 goCmd = append(goCmd, "-tags=noopt")
1739 }
1740 goCmd = appendCompilerFlags(goCmd)
1741 goCmd = append(goCmd, "-f={{if .Stale}}\tSTALE {{.ImportPath}}: {{.StaleReason}}{{end}}")
1742
1743 out := runEnv(workdir, CheckExit, env, append(goCmd, targets...)...)
1744 if strings.Contains(out, "\tSTALE ") {
1745 os.Setenv("GODEBUG", "gocachehash=1")
1746 for _, target := range []string{"internal/runtime/sys", "cmd/dist", "cmd/link"} {
1747 if strings.Contains(out, "STALE "+target) {
1748 run(workdir, ShowOutput|CheckExit, goBinary, "list", "-f={{.ImportPath}} {{.Stale}}", target)
1749 break
1750 }
1751 }
1752 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)
1753 }
1754 }
1755
1756
1757
1758
1759
1760
1761
1762
1763 var cgoEnabled = map[string]bool{
1764 "aix/ppc64": true,
1765 "darwin/amd64": true,
1766 "darwin/arm64": true,
1767 "dragonfly/amd64": true,
1768 "freebsd/386": true,
1769 "freebsd/amd64": true,
1770 "freebsd/arm": true,
1771 "freebsd/arm64": true,
1772 "freebsd/riscv64": true,
1773 "illumos/amd64": true,
1774 "linux/386": true,
1775 "linux/amd64": true,
1776 "linux/arm": true,
1777 "linux/arm64": true,
1778 "linux/loong64": true,
1779 "linux/ppc64": false,
1780 "linux/ppc64le": true,
1781 "linux/mips": true,
1782 "linux/mipsle": true,
1783 "linux/mips64": true,
1784 "linux/mips64le": true,
1785 "linux/riscv64": true,
1786 "linux/s390x": true,
1787 "linux/sparc64": true,
1788 "android/386": true,
1789 "android/amd64": true,
1790 "android/arm": true,
1791 "android/arm64": true,
1792 "ios/arm64": true,
1793 "ios/amd64": true,
1794 "js/wasm": false,
1795 "wasip1/wasm": false,
1796 "netbsd/386": true,
1797 "netbsd/amd64": true,
1798 "netbsd/arm": true,
1799 "netbsd/arm64": true,
1800 "openbsd/386": true,
1801 "openbsd/amd64": true,
1802 "openbsd/arm": true,
1803 "openbsd/arm64": true,
1804 "openbsd/mips64": true,
1805 "openbsd/ppc64": false,
1806 "openbsd/riscv64": true,
1807 "plan9/386": false,
1808 "plan9/amd64": false,
1809 "plan9/arm": false,
1810 "solaris/amd64": true,
1811 "windows/386": true,
1812 "windows/amd64": true,
1813 "windows/arm": false,
1814 "windows/arm64": true,
1815 }
1816
1817
1818
1819
1820
1821 var broken = map[string]bool{
1822 "linux/sparc64": true,
1823 "openbsd/mips64": true,
1824 "windows/arm": true,
1825 }
1826
1827
1828 var firstClass = map[string]bool{
1829 "darwin/amd64": true,
1830 "darwin/arm64": true,
1831 "linux/386": true,
1832 "linux/amd64": true,
1833 "linux/arm": true,
1834 "linux/arm64": true,
1835 "windows/386": true,
1836 "windows/amd64": true,
1837 }
1838
1839
1840
1841 func needCC() bool {
1842 return os.Getenv("CGO_ENABLED") == "1" || mustLinkExternal(gohostos, gohostarch, false)
1843 }
1844
1845 func checkCC() {
1846 if !needCC() {
1847 return
1848 }
1849 cc1 := defaultcc[""]
1850 if cc1 == "" {
1851 cc1 = "gcc"
1852 for _, os := range clangos {
1853 if gohostos == os {
1854 cc1 = "clang"
1855 break
1856 }
1857 }
1858 }
1859 cc, err := quotedSplit(cc1)
1860 if err != nil {
1861 fatalf("split CC: %v", err)
1862 }
1863 var ccHelp = append(cc, "--help")
1864
1865 if output, err := exec.Command(ccHelp[0], ccHelp[1:]...).CombinedOutput(); err != nil {
1866 outputHdr := ""
1867 if len(output) > 0 {
1868 outputHdr = "\nCommand output:\n\n"
1869 }
1870 fatalf("cannot invoke C compiler %q: %v\n\n"+
1871 "Go needs a system C compiler for use with cgo.\n"+
1872 "To set a C compiler, set CC=the-compiler.\n"+
1873 "To disable cgo, set CGO_ENABLED=0.\n%s%s", cc, err, outputHdr, output)
1874 }
1875 }
1876
1877 func defaulttarg() string {
1878
1879
1880
1881
1882 pwd := xgetwd()
1883 src := pathf("%s/src/", goroot)
1884 real_src := xrealwd(src)
1885 if !strings.HasPrefix(pwd, real_src) {
1886 fatalf("current directory %s is not under %s", pwd, real_src)
1887 }
1888 pwd = pwd[len(real_src):]
1889
1890 pwd = strings.TrimPrefix(pwd, "/")
1891
1892 return pwd
1893 }
1894
1895
1896 func cmdinstall() {
1897 xflagparse(-1)
1898
1899 if flag.NArg() == 0 {
1900 install(defaulttarg())
1901 }
1902
1903 for _, arg := range flag.Args() {
1904 install(arg)
1905 }
1906 }
1907
1908
1909 func cmdclean() {
1910 xflagparse(0)
1911 clean()
1912 }
1913
1914
1915 func cmdbanner() {
1916 xflagparse(0)
1917 banner()
1918 }
1919
1920 func banner() {
1921 if vflag > 0 {
1922 xprintf("\n")
1923 }
1924 xprintf("---\n")
1925 xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot)
1926 xprintf("Installed commands in %s\n", gorootBin)
1927
1928 if gohostos == "plan9" {
1929
1930 pid := strings.ReplaceAll(readfile("#c/pid"), " ", "")
1931 ns := fmt.Sprintf("/proc/%s/ns", pid)
1932 if !strings.Contains(readfile(ns), fmt.Sprintf("bind -b %s /bin", gorootBin)) {
1933 xprintf("*** You need to bind %s before /bin.\n", gorootBin)
1934 }
1935 } else {
1936
1937 pathsep := ":"
1938 if gohostos == "windows" {
1939 pathsep = ";"
1940 }
1941 path := os.Getenv("PATH")
1942 if p, ok := os.LookupEnv("DIST_UNMODIFIED_PATH"); ok {
1943
1944
1945
1946
1947 path = p
1948 }
1949 if !strings.Contains(pathsep+path+pathsep, pathsep+gorootBin+pathsep) {
1950 xprintf("*** You need to add %s to your PATH.\n", gorootBin)
1951 }
1952 }
1953 }
1954
1955
1956 func cmdversion() {
1957 xflagparse(0)
1958 xprintf("%s\n", findgoversion())
1959 }
1960
1961
1962 func cmdlist() {
1963 jsonFlag := flag.Bool("json", false, "produce JSON output")
1964 brokenFlag := flag.Bool("broken", false, "include broken ports")
1965 xflagparse(0)
1966
1967 var plats []string
1968 for p := range cgoEnabled {
1969 if broken[p] && !*brokenFlag {
1970 continue
1971 }
1972 plats = append(plats, p)
1973 }
1974 sort.Strings(plats)
1975
1976 if !*jsonFlag {
1977 for _, p := range plats {
1978 xprintf("%s\n", p)
1979 }
1980 return
1981 }
1982
1983 type jsonResult struct {
1984 GOOS string
1985 GOARCH string
1986 CgoSupported bool
1987 FirstClass bool
1988 Broken bool `json:",omitempty"`
1989 }
1990 var results []jsonResult
1991 for _, p := range plats {
1992 fields := strings.Split(p, "/")
1993 results = append(results, jsonResult{
1994 GOOS: fields[0],
1995 GOARCH: fields[1],
1996 CgoSupported: cgoEnabled[p],
1997 FirstClass: firstClass[p],
1998 Broken: broken[p],
1999 })
2000 }
2001 out, err := json.MarshalIndent(results, "", "\t")
2002 if err != nil {
2003 fatalf("json marshal error: %v", err)
2004 }
2005 if _, err := os.Stdout.Write(out); err != nil {
2006 fatalf("write failed: %v", err)
2007 }
2008 }
2009
2010 func setNoOpt() {
2011 for _, gcflag := range strings.Split(gogcflags, " ") {
2012 if gcflag == "-N" || gcflag == "-l" {
2013 noOpt = true
2014 break
2015 }
2016 }
2017 }
2018
View as plain text