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