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