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