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