1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 // Initialization for any invocation.
19 // The usual variables.
31 goextlinkenabled string
43 defaultcxxtarget string
44 defaultcctarget string
48 sflag bool // build static binaries
49 vflag int // verbosity
52 // The known architecture letters.
53 var gochars = "566899"
55 // The known architectures.
56 var okgoarch = []string{
57 // same order as gochars
66 // The known operating systems.
67 var okgoos = []string{
81 // find reports the first index of p in l[0:n], or else -1.
82 func find(p string, l []string) int {
91 // xinit handles initialization of the various global state, like goroot and goarch.
93 goroot = os.Getenv("GOROOT")
94 if slash == "/" && len(goroot) > 1 || slash == `\` && len(goroot) > 3 {
95 // if not "/" or "c:\", then strip trailing path separator
96 goroot = strings.TrimSuffix(goroot, slash)
99 fatal("$GOROOT must be set")
102 goroot_final = os.Getenv("GOROOT_FINAL")
103 if goroot_final == "" {
104 goroot_final = goroot
107 b := os.Getenv("GOBIN")
109 b = goroot + slash + "bin"
113 b = os.Getenv("GOOS")
118 if find(goos, okgoos) < 0 {
119 fatal("unknown $GOOS %s", goos)
122 b = os.Getenv("GOARM")
128 b = os.Getenv("GO386")
138 p := pathf("%s/include/u.h", goroot)
140 fatal("$GOROOT is not set correctly or not exported\n"+
142 "\t%s does not exist", goroot, p)
145 b = os.Getenv("GOHOSTARCH")
150 i := find(gohostarch, okgoarch)
152 fatal("unknown $GOHOSTARCH %s", gohostarch)
154 gohostchar = gochars[i : i+1]
156 b = os.Getenv("GOARCH")
161 i = find(goarch, okgoarch)
163 fatal("unknown $GOARCH %s", goarch)
165 gochar = gochars[i : i+1]
167 b = os.Getenv("GO_EXTLINK_ENABLED")
169 if b != "0" && b != "1" {
170 fatal("unknown $GO_EXTLINK_ENABLED %s", b)
177 // Use clang on OS X, because gcc is deprecated there.
178 // Xcode for OS X 10.9 Mavericks will ship a fake "gcc" binary that
179 // actually runs clang. We prepare different command
180 // lines for the two binaries, so it matters what we call it.
181 // See golang.org/issue/5822.
190 defaultcflags = os.Getenv("CFLAGS")
192 defaultldflags = os.Getenv("LDFLAGS")
194 b = os.Getenv("CC_FOR_TARGET")
200 b = os.Getenv("CXX_FOR_TARGET")
213 // For tools being invoked but also for os.ExpandEnv.
214 os.Setenv("GO386", go386)
215 os.Setenv("GOARCH", goarch)
216 os.Setenv("GOARM", goarm)
217 os.Setenv("GOHOSTARCH", gohostarch)
218 os.Setenv("GOHOSTOS", gohostos)
219 os.Setenv("GOOS", goos)
220 os.Setenv("GOROOT", goroot)
221 os.Setenv("GOROOT_FINAL", goroot_final)
223 // Make the environment more predictable.
224 os.Setenv("LANG", "C")
225 os.Setenv("LANGUAGE", "en_US.UTF8")
230 tooldir = pathf("%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch)
233 // rmworkdir deletes the work directory.
236 errprintf("rm -rf %s\n", workdir)
241 // Remove trailing spaces.
242 func chomp(s string) string {
243 return strings.TrimRight(s, " \t\r\n")
246 func branchtag(branch string) (tag string, precise bool) {
247 b := run(goroot, CheckExit, "git", "log", "--decorate=full", "--format=format:%d", "master.."+branch)
249 for _, line := range splitlines(b) {
250 // Each line is either blank, or looks like
251 // (tag: refs/tags/go1.4rc2, refs/remotes/origin/release-branch.go1.4, refs/heads/release-branch.go1.4)
252 // We need to find an element starting with refs/tags/.
253 i := strings.Index(line, " refs/tags/")
257 i += len(" refs/tags/")
258 // The tag name ends at a comma or paren (prefer the first).
259 j := strings.Index(line[i:], ",")
261 j = strings.Index(line[i:], ")")
264 continue // malformed line; ignore it
268 precise = true // tag denotes HEAD
275 // findgoversion determines the Go version to use in the version string.
276 func findgoversion() string {
277 // The $GOROOT/VERSION file takes priority, for distributions
278 // without the source repo.
279 path := pathf("%s/VERSION", goroot)
281 b := chomp(readfile(path))
282 // Commands such as "dist version > VERSION" will cause
283 // the shell to create an empty VERSION file and set dist's
284 // stdout to its fd. dist in turn looks at VERSION and uses
285 // its content if available, which is empty at this point.
286 // Only use the VERSION file if it is non-empty.
292 // The $GOROOT/VERSION.cache file is a cache to avoid invoking
293 // git every time we run this command. Unlike VERSION, it gets
294 // deleted by the clean command.
295 path = pathf("%s/VERSION.cache", goroot)
297 return chomp(readfile(path))
300 // Otherwise, use Git.
301 // What is the current branch?
302 branch := chomp(run(goroot, CheckExit, "git", "rev-parse", "--abbrev-ref", "HEAD"))
304 // What are the tags along the current branch?
308 // If we're on a release branch, use the closest matching tag
309 // that is on the release branch (and not on the master branch).
310 if strings.HasPrefix(branch, "release-branch.") {
311 tag, precise = branchtag(branch)
315 // Tag does not point at HEAD; add hash and date to version.
316 tag += chomp(run(goroot, CheckExit, "git", "log", "-n", "1", "--format=format: +%h %cd", "HEAD"))
320 writefile(tag, path, 0)
326 * Initial tree setup.
329 // The old tools that no longer live in $GOBIN or $GOROOT/bin.
330 var oldtool = []string{
331 "5a", "5c", "5g", "5l",
332 "6a", "6c", "6g", "6l",
333 "8a", "8c", "8g", "8l",
334 "9a", "9c", "9g", "9l",
353 // Unreleased directories (relative to $GOROOT) that should
354 // not be in release branches.
355 var unreleased = []string{
362 // setup sets up the tree for the initial build.
364 // Create bin directory.
365 if p := pathf("%s/bin", goroot); !isdir(p) {
369 // Create package directory.
370 if p := pathf("%s/pkg", goroot); !isdir(p) {
374 p := pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch)
380 if goos != gohostos || goarch != gohostarch {
381 p := pathf("%s/pkg/%s_%s", goroot, goos, goarch)
388 // Create object directory.
389 // We keep it in pkg/ so that all the generated binaries
390 // are in one tree. If pkg/obj/libgc.a exists, it is a dreg from
391 // before we used subdirectories of obj. Delete all of obj
393 if p := pathf("%s/pkg/obj/libgc.a", goroot); isfile(p) {
394 xremoveall(pathf("%s/pkg/obj", goroot))
396 p = pathf("%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch)
402 // Create tool directory.
403 // We keep it in pkg/, just like the object directory above.
409 // Remove tool binaries from before the tool/gohostos_gohostarch
410 xremoveall(pathf("%s/bin/tool", goroot))
412 // Remove old pre-tool binaries.
413 for _, old := range oldtool {
414 xremove(pathf("%s/bin/%s", goroot, old))
417 // If $GOBIN is set and has a Go compiler, it must be cleaned.
418 for _, char := range gochars {
419 if isfile(pathf("%s%s%c%s", gobin, slash, char, "g")) {
420 for _, old := range oldtool {
421 xremove(pathf("%s/%s", gobin, old))
427 // For release, make sure excluded things are excluded.
428 goversion := findgoversion()
429 if strings.HasPrefix(goversion, "release.") || (strings.HasPrefix(goversion, "go") && !strings.Contains(goversion, "beta")) {
430 for _, dir := range unreleased {
431 if p := pathf("%s/%s", goroot, dir); isdir(p) {
432 fatal("%s should not exist in release build", p)
439 * C library and tool building
442 // gccargs is the gcc command line to use for compiling a single C file.
443 var proto_gccargs = []string{
445 // native Plan 9 compilers don't like non-standard prototypes
446 // so let gcc catch them.
447 "-Wstrict-prototypes",
451 "-Wno-missing-braces",
453 "-Wno-unknown-pragmas",
456 "-Wno-missing-field-initializers",
463 // gccargs2 is the second part of gccargs.
464 // it is used if the environment isn't defining CFLAGS.
465 var proto_gccargs2 = []string{
466 // on older versions of GCC, -Wuninitialized is not supported
467 // without -O, so put it here together with -O settings in case
468 // the user's $CFLAGS doesn't include -O.
474 if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm" {
475 // GCC 4.5.4 (NetBSD nb1 20120916) on ARM is known to mis-optimize gc/mparith3.c
476 // Fix available at http://patchwork.ozlabs.org/patch/64562/.
477 proto_gccargs2[1] = "-O1"
481 var gccargs, ldargs []string
483 // deptab lists changes to the default dependencies for a given prefix.
484 // deps ending in /* read the whole directory; deps beginning with -
485 // exclude files with that prefix.
486 var deptab = []struct {
487 prefix string // prefix of target
488 dep []string // dependency tweaks for targets with that prefix
491 "$GOROOT/include/u.h",
492 "$GOROOT/include/utf.h",
493 "$GOROOT/include/fmt.h",
494 "$GOROOT/include/libc.h",
499 "$GOROOT/include/u.h",
500 "$GOROOT/include/utf.h",
501 "$GOROOT/include/fmt.h",
502 "$GOROOT/include/libc.h",
503 "$GOROOT/include/bio.h",
505 {"liblink", []string{
506 "$GOROOT/include/u.h",
507 "$GOROOT/include/utf.h",
508 "$GOROOT/include/fmt.h",
509 "$GOROOT/include/libc.h",
510 "$GOROOT/include/bio.h",
511 "$GOROOT/include/ar.h",
512 "$GOROOT/include/link.h",
522 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
525 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
528 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
531 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libgc.a",
534 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libld.a",
537 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libld.a",
540 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libld.a",
543 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libld.a",
549 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/liblink.a",
550 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/libbio.a",
551 "$GOROOT/pkg/obj/${GOHOSTOS}_$GOHOSTARCH/lib9.a",
553 {"runtime", []string{
558 // depsuffix records the allowed suffixes for source files.
559 var depsuffix = []string{
566 // gentab records how to generate some trivial files.
567 var gentab = []struct {
569 gen func(string, string)
571 {"opnames.h", gcopnames},
572 {"anames5.c", mkanames},
573 {"anames6.c", mkanames},
574 {"anames8.c", mkanames},
575 {"anames9.c", mkanames},
576 {"zdefaultcc.go", mkzdefaultcc},
577 {"zversion.go", mkzversion},
579 // not generated anymore, but delete the file if we see it
583 // install installs the library, package, or binary associated with dir,
584 // which is relative to $GOROOT/src.
585 func install(dir string) {
587 if goos != gohostos || goarch != gohostarch {
588 errprintf("%s (%s/%s)\n", dir, goos, goarch)
590 errprintf("%s\n", dir)
596 for _, name := range clean {
601 // path = full path to dir.
602 path := pathf("%s/src/%s", goroot, dir)
603 name := filepath.Base(dir)
605 // set up gcc command line on first run.
607 gccargs = splitfields(defaultcc + " " + defaultcflags)
608 gccargs = append(gccargs, proto_gccargs...)
609 if defaultcflags == "" {
610 gccargs = append(gccargs, proto_gccargs2...)
612 if strings.Contains(gccargs[0], "clang") {
613 // disable ASCII art in clang errors, if possible
614 gccargs = append(gccargs, "-fno-caret-diagnostics")
615 // clang is too smart about unused command-line arguments
616 gccargs = append(gccargs, "-Qunused-arguments")
618 // disable word wrapping in error messages
619 gccargs = append(gccargs, "-fmessage-length=0")
620 if gohostos == "darwin" && gohostarch != "arm" {
621 // golang.org/issue/5261
622 gccargs = append(gccargs, "-mmacosx-version-min=10.6")
625 if ldargs == nil && defaultldflags != "" {
626 ldargs = splitfields(defaultldflags)
630 ispkg := !strings.HasPrefix(dir, "cmd/") || strings.HasPrefix(dir, "cmd/internal/") || strings.HasPrefix(dir, "cmd/asm/internal/")
633 // Legacy C exceptions.
635 case "lib9", "libbio", "liblink", "cmd/gc", "cmd/ld":
638 case "cmd/5a", "cmd/5g", "cmd/5l",
639 "cmd/6a", "cmd/6g", "cmd/6l",
640 "cmd/8a", "cmd/8g", "cmd/8l",
641 "cmd/9a", "cmd/9g", "cmd/9l":
645 // Start final link command line.
646 // Note: code below knows that link.p[targ] is the target.
656 if !strings.HasPrefix(name, "lib") {
659 link = []string{"ar", "rsc", pathf("%s/pkg/obj/%s_%s/%s%s.a", goroot, gohostos, gohostarch, prefix, name)}
660 if gohostos == "plan9" {
666 // Go library (package).
668 link = []string{"pack", pathf("%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir)}
670 xmkdirall(filepath.Dir(link[targ]))
672 case dir == "cmd/go" || dir == "cmd/cgo":
676 elem = "go_bootstrap"
678 link = []string{fmt.Sprintf("%s/%sl", tooldir, gochar), "-o", pathf("%s/%s%s", tooldir, elem, exe)}
682 // C command. Use gccargs and ldargs.
683 if gohostos == "plan9" {
684 link = []string{fmt.Sprintf("%sl", gohostchar), "-o", pathf("%s/%s", tooldir, name)}
687 link = append(link, gccargs...)
688 link = append(link, ldargs...)
690 link = append(link, "-static")
692 link = append(link, "-o", pathf("%s/%s%s", tooldir, name, exe))
696 link = append(link, "-m64")
698 link = append(link, "-m32")
702 ttarg := mtime(link[targ])
704 // Gather files that are sources for this target.
705 // Everything in that directory, and any target-specific
707 files := xreaddir(path)
709 // Remove files beginning with . or _,
710 // which are likely to be editor temporary files.
711 // This is the same heuristic build.ScanDir uses.
712 // There do exist real C files beginning with _,
713 // so limit that check to just Go files.
714 files = filter(files, func(p string) bool {
715 return !strings.HasPrefix(p, ".") && (!strings.HasPrefix(p, "_") || !strings.HasSuffix(p, ".go"))
720 for _, dt := range deptab {
721 if dir == dt.prefix || strings.HasSuffix(dt.prefix, "/") && strings.HasPrefix(dir, dt.prefix) {
722 for _, p := range dt.dep {
725 case strings.HasSuffix(p, ".a"):
726 libs = append(libs, p)
728 case strings.HasSuffix(p, "/*"):
729 dir := strings.TrimSuffix(p, "/*")
730 for _, name := range xreaddir(pathf("%s/%s", path, dir)) {
731 files = append(files, pathf("%s/%s", dir, name))
734 case strings.HasPrefix(p, "-"):
735 files = filter(files, func(s string) bool {
736 return !strings.HasPrefix(s, p[1:])
740 files = append(files, p)
747 // Convert to absolute paths.
748 for i, p := range files {
750 files[i] = pathf("%s/%s", path, p)
754 // Is the target up-to-date?
755 var gofiles, missing []string
757 files = filter(files, func(p string) bool {
758 for _, suf := range depsuffix {
759 if strings.HasSuffix(p, suf) {
766 if !t.IsZero() && !strings.HasSuffix(p, ".a") && !shouldbuild(p, dir) {
769 if strings.HasSuffix(p, ".go") {
770 gofiles = append(gofiles, p)
776 missing = append(missing, p)
781 // If there are no files to compile, we're done.
787 for _, p := range libs {
788 if mtime(p).After(ttarg) {
799 // For package runtime, copy some files into the work space.
800 if dir == "runtime" {
801 // For use by assembly and C files.
802 copyfile(pathf("%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
803 pathf("%s/src/cmd/ld/textflag.h", goroot), 0)
804 copyfile(pathf("%s/pkg/%s_%s/funcdata.h", goroot, goos, goarch),
805 pathf("%s/src/runtime/funcdata.h", goroot), 0)
808 // Generate any missing files; regenerate existing ones.
809 for _, p := range files {
810 elem := filepath.Base(p)
811 for _, gt := range gentab {
815 if strings.HasPrefix(elem, gt.nameprefix) {
817 errprintf("generate %s\n", p)
820 // Do not add generated file to clean list.
821 // In runtime, we want to be able to
822 // build the package with the go tool,
823 // and it assumes these generated files already
824 // exist (it does not know how to build them).
825 // The 'clean' command can remove
826 // the generated files.
830 // Did not rebuild p.
831 if find(p, missing) >= 0 {
832 fatal("missing file %s", p)
837 if (goos != gohostos || goarch != gohostarch) && isgo {
838 // We've generated the right files; the go command can do the build.
840 errprintf("skip build for cross-compile %s\n", dir)
847 // The next loop will compile individual non-Go files.
848 // Hand the Go files to the compiler en masse.
849 // For package runtime, this writes go_asm.h, which
850 // the assembly files will need.
852 if strings.HasPrefix(dir, "cmd/") {
855 b := pathf("%s/_go_.a", workdir)
856 clean = append(clean, b)
858 link = append(link, b)
862 compile := []string{pathf("%s/%sg", tooldir, gochar), "-pack", "-o", b, "-p", pkg}
863 if dir == "runtime" {
864 compile = append(compile, "-+", "-asmhdr", pathf("%s/go_asm.h", workdir))
866 compile = append(compile, gofiles...)
867 run(path, CheckExit|ShowOutput, compile...)
870 // Compile the files.
871 for _, p := range files {
872 if !strings.HasSuffix(p, ".c") && !strings.HasSuffix(p, ".s") {
875 name := filepath.Base(p)
879 // C library or tool.
880 if gohostos == "plan9" {
882 gohostchar + "c", "-FTVwp",
885 "-D__SIZE_TYPE__=ulong", // for GNU bison
886 pathf("-I%s/include/plan9", goroot),
887 pathf("-I%s/include/plan9/%s", goroot, gohostarch),
890 compile = gccargs[0:len(gccargs):len(gccargs)]
891 compile = append(compile, "-c")
894 compile = append(compile, "-m64")
896 compile = append(compile, "-m32")
898 compile = append(compile, "-I", pathf("%s/include", goroot))
902 compile = append(compile, "-DPLAN9PORT")
905 compile = append(compile, "-I", path)
907 // lib9/goos.c gets the default constants hard-coded.
908 if name == "goos.c" {
909 compile = append(compile,
910 "-D", fmt.Sprintf("GOOS=%q", goos),
911 "-D", fmt.Sprintf("GOARCH=%q", goarch),
912 "-D", fmt.Sprintf("GOHOSTOS=%q", gohostos),
913 "-D", fmt.Sprintf("GOHOSTARCH=%q", gohostarch),
914 "-D", fmt.Sprintf("GOROOT=%q", goroot_final),
915 "-D", fmt.Sprintf("GOVERSION=%q", findgoversion()),
916 "-D", fmt.Sprintf("GOARM=%q", goarm),
917 "-D", fmt.Sprintf("GO386=%q", go386),
918 "-D", fmt.Sprintf("GO_EXTLINK_ENABLED=%q", goextlinkenabled),
922 // liblink/go.c records the GOEXPERIMENT setting used during the build.
924 compile = append(compile,
925 "-D", fmt.Sprintf("GOEXPERIMENT=%q", os.Getenv("GOEXPERIMENT")))
928 // Assembly file for a Go package.
930 pathf("%s/%sa", tooldir, gochar),
932 "-I", pathf("%s/pkg/%s_%s", goroot, goos, goarch),
933 "-D", "GOOS_" + goos,
934 "-D", "GOARCH_" + goarch,
935 "-D", "GOOS_GOARCH_" + goos + "_" + goarch,
940 b := pathf("%s/%s", workdir, filepath.Base(p))
941 if !isgo && gohostos == "darwin" {
942 // To debug C programs on OS X, it is not enough to say -ggdb
943 // on the command line. You have to leave the object files
944 // lying around too. Leave them in pkg/obj/, which does not
945 // get removed when this tool exits.
946 obj := pathf("%s/pkg/obj/%s", goroot, dir)
948 b = pathf("%s/%s", obj, filepath.Base(p))
952 // Change the last character of the output file (which was c or s).
953 if gohostos == "plan9" {
954 b = b[:len(b)-1] + gohostchar
956 b = b[:len(b)-1] + "o"
958 compile = append(compile, "-o", b, p)
959 bgrun(path, compile...)
961 link = append(link, b)
963 clean = append(clean, b)
968 if isgo && ispackcmd {
970 dopack(link[targ], archive, link[targ+1:])
975 // C binaries need the libraries explicitly, and -lm.
976 link = append(link, libs...)
977 if gohostos != "plan9" {
978 link = append(link, "-lm")
982 // Remove target before writing it.
984 run("", CheckExit|ShowOutput, link...)
987 // matchfield reports whether the field matches this build.
988 func matchfield(f string) bool {
989 for _, tag := range strings.Split(f, ",") {
990 if tag == goos || tag == goarch || tag == "cmd_go_bootstrap" || tag == "go1.1" || (goos == "android" && tag == "linux") {
998 // shouldbuild reports whether we should build this file.
999 // It applies the same rules that are used with context tags
1000 // in package go/build, except that the GOOS and GOARCH
1001 // can appear anywhere in the file name, not just after _.
1002 // In particular, they can be the entire file name (like windows.c).
1003 // We also allow the special tag cmd_go_bootstrap.
1004 // See ../go/bootstrap.go and package go/build.
1005 func shouldbuild(file, dir string) bool {
1006 // Check file name for GOOS or GOARCH.
1007 name := filepath.Base(file)
1008 excluded := func(list []string, ok string) bool {
1009 for _, x := range list {
1013 i := strings.Index(name, x)
1018 if i == len(name) || name[i] == '.' || name[i] == '_' {
1024 if excluded(okgoos, goos) || excluded(okgoarch, goarch) {
1029 if strings.Contains(name, "_test") {
1033 // cmd/go/doc.go has a giant /* */ comment before
1034 // it gets to the important detail that it is not part of
1035 // package main. We don't parse those comments,
1036 // so special case that file.
1037 if strings.HasSuffix(file, "cmd/go/doc.go") || strings.HasSuffix(file, "cmd\\go\\doc.go") {
1040 if strings.HasSuffix(file, "cmd/cgo/doc.go") || strings.HasSuffix(file, "cmd\\cgo\\doc.go") {
1044 // Check file contents for // +build lines.
1045 for _, p := range splitlines(readfile(file)) {
1046 p = strings.TrimSpace(p)
1050 if strings.Contains(p, "package documentation") {
1053 if strings.Contains(p, "package main") && dir != "cmd/go" && dir != "cmd/cgo" {
1056 if !strings.HasPrefix(p, "//") {
1059 if !strings.Contains(p, "+build") {
1062 fields := splitfields(p)
1063 if len(fields) < 2 || fields[1] != "+build" {
1066 for _, p := range fields[2:] {
1067 if (p[0] == '!' && !matchfield(p[1:])) || matchfield(p) {
1078 // copy copies the file src to dst, via memory (so only good for small files).
1079 func copyfile(dst, src string, exec int) {
1081 errprintf("cp %s %s\n", src, dst)
1083 writefile(readfile(src), dst, exec)
1086 // dopack copies the package src to dst,
1087 // appending the files listed in extra.
1088 // The archive format is the traditional Unix ar format.
1089 func dopack(dst, src string, extra []string) {
1090 bdst := bytes.NewBufferString(readfile(src))
1091 for _, file := range extra {
1093 // find last path element for archive member name
1094 i := strings.LastIndex(file, "/") + 1
1095 j := strings.LastIndex(file, `\`) + 1
1099 fmt.Fprintf(bdst, "%-16.16s%-12d%-6d%-6d%-8o%-10d`\n", file[i:], 0, 0, 0, 0644, len(b))
1105 writefile(bdst.String(), dst, 0)
1108 // buildorder records the order of builds for the 'go bootstrap' command.
1109 // The Go packages and commands must be in dependency order,
1110 // maintained by hand, but the order doesn't change often.
1111 var buildorder = []string{
1112 // Legacy C programs.
1117 "cmd/gc", // must be before g
1118 "cmd/ld", // must be before l
1119 "cmd/%sl", // must be before a, g
1123 // Go libraries and programs for bootstrap.
1162 "text/template/parse",
1167 "cmd/internal/obj/arm",
1168 "cmd/internal/obj/i386",
1169 "cmd/internal/obj/ppc64",
1170 "cmd/internal/obj/x86",
1175 // cleantab records the directories to clean in 'go clean'.
1176 // It is bigger than the buildorder because we clean all the
1177 // compilers but build only the $GOARCH ones.
1178 var cleantab = []string{
1179 // Commands and C libraries.
1234 "text/template/parse",
1241 var runtimegen = []string{
1247 for _, name := range cleantab {
1248 path := pathf("%s/src/%s", goroot, name)
1249 // Remove generated files.
1250 for _, elem := range xreaddir(path) {
1251 for _, gt := range gentab {
1252 if strings.HasPrefix(elem, gt.nameprefix) {
1253 xremove(pathf("%s/%s", path, elem))
1257 // Remove generated binary named for directory.
1258 if strings.HasPrefix(name, "cmd/") {
1259 xremove(pathf("%s/%s", path, name[4:]))
1263 // remove runtimegen files.
1264 path := pathf("%s/src/runtime", goroot)
1265 for _, elem := range runtimegen {
1266 xremove(pathf("%s/%s", path, elem))
1270 // Remove object tree.
1271 xremoveall(pathf("%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch))
1273 // Remove installed packages and tools.
1274 xremoveall(pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch))
1275 xremoveall(pathf("%s/pkg/%s_%s", goroot, goos, goarch))
1278 // Remove cached version info.
1279 xremove(pathf("%s/VERSION.cache", goroot))
1284 * command implementations
1288 xprintf("usage: go tool dist [command]\n" +
1291 "banner print installation banner\n" +
1292 "bootstrap rebuild everything\n" +
1293 "clean deletes all built files\n" +
1294 "env [-p] print environment (-p: include $PATH)\n" +
1295 "install [dir] install individual directory\n" +
1296 "version print Go version\n" +
1298 "All commands take -v flags to emit extra information.\n",
1303 // The env command prints the default environment.
1305 path := flag.Bool("p", false, "emit updated PATH")
1306 plan9 := flag.Bool("9", false, "emit plan 9 syntax")
1307 windows := flag.Bool("w", false, "emit windows syntax")
1310 format := "%s=\"%s\"\n"
1313 format = "%s='%s'\n"
1315 format = "set %s=%s\r\n"
1318 xprintf(format, "CC", defaultcc)
1319 xprintf(format, "CC_FOR_TARGET", defaultcctarget)
1320 xprintf(format, "GOROOT", goroot)
1321 xprintf(format, "GOBIN", gobin)
1322 xprintf(format, "GOARCH", goarch)
1323 xprintf(format, "GOOS", goos)
1324 xprintf(format, "GOHOSTARCH", gohostarch)
1325 xprintf(format, "GOHOSTOS", gohostos)
1326 xprintf(format, "GOTOOLDIR", tooldir)
1327 xprintf(format, "GOCHAR", gochar)
1328 if goarch == "arm" {
1329 xprintf(format, "GOARM", goarm)
1331 if goarch == "386" {
1332 xprintf(format, "GO386", go386)
1337 if gohostos == "windows" {
1340 xprintf(format, "PATH", fmt.Sprintf("%s%s%s", gobin, sep, os.Getenv("PATH")))
1344 // The bootstrap command runs a build from scratch,
1345 // stopping at having installed the go_bootstrap command.
1346 func cmdbootstrap() {
1347 flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all")
1348 flag.BoolVar(&sflag, "s", sflag, "build static binaries")
1351 if isdir(pathf("%s/src/pkg", goroot)) {
1353 "The Go package sources have moved to $GOROOT/src.\n"+
1354 "*** %s still exists. ***\n"+
1355 "It probably contains stale files that may confuse the build.\n"+
1356 "Please (check what's there and) remove it and try again.\n"+
1357 "See http://golang.org/s/go14nopkg\n",
1358 pathf("%s/src/pkg", goroot))
1367 bootstrapBuildTools()
1369 // For the main bootstrap, building for host os/arch.
1376 os.Setenv("GOHOSTARCH", gohostarch)
1377 os.Setenv("GOHOSTOS", gohostos)
1378 os.Setenv("GOARCH", goarch)
1379 os.Setenv("GOOS", goos)
1381 // TODO(rsc): Enable when appropriate.
1382 // This step is only needed if we believe that the Go compiler built from Go 1.4
1383 // will produce different object files than the Go compiler built from itself.
1384 // In the absence of bugs, that should not happen.
1385 // And if there are bugs, they're more likely in the current development tree
1386 // than in a standard release like Go 1.4, so don't do this rebuild by default.
1388 xprintf("##### Building Go toolchain using itself.\n")
1389 for _, pattern := range buildorder {
1390 if pattern == "cmd/go" {
1394 if strings.Contains(pattern, "%s") {
1395 dir = fmt.Sprintf(pattern, gohostchar)
1398 if oldgochar != gohostchar && strings.Contains(pattern, "%s") {
1399 install(fmt.Sprintf(pattern, oldgochar))
1405 xprintf("##### Building compilers and go_bootstrap for host, %s/%s.\n", gohostos, gohostarch)
1406 for _, pattern := range buildorder {
1408 if strings.Contains(pattern, "%s") {
1409 dir = fmt.Sprintf(pattern, gohostchar)
1412 if oldgochar != gohostchar && strings.Contains(pattern, "%s") {
1413 install(fmt.Sprintf(pattern, oldgochar))
1420 os.Setenv("GOARCH", goarch)
1421 os.Setenv("GOOS", goos)
1423 // Build runtime for actual goos/goarch too.
1424 if goos != gohostos || goarch != gohostarch {
1429 func defaulttarg() string {
1430 // xgetwd might return a path with symlinks fully resolved, and if
1431 // there happens to be symlinks in goroot, then the hasprefix test
1432 // will never succeed. Instead, we use xrealwd to get a canonical
1433 // goroot/src before the comparison to avoid this problem.
1435 src := pathf("%s/src/", goroot)
1436 real_src := xrealwd(src)
1437 if !strings.HasPrefix(pwd, real_src) {
1438 fatal("current directory %s is not under %s", pwd, real_src)
1440 pwd = pwd[len(real_src):]
1441 // guard againt xrealwd return the directory without the trailing /
1442 pwd = strings.TrimPrefix(pwd, "/")
1447 // Install installs the list of packages named on the command line.
1449 flag.BoolVar(&sflag, "s", sflag, "build static binaries")
1452 if flag.NArg() == 0 {
1453 install(defaulttarg())
1456 for _, arg := range flag.Args() {
1461 // Clean deletes temporary objects.
1467 // Banner prints the 'now you've installed Go' banner.
1473 xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot)
1474 xprintf("Installed commands in %s\n", gobin)
1476 if !xsamefile(goroot_final, goroot) {
1477 // If the files are to be moved, don't check that gobin
1478 // is on PATH; assume they know what they are doing.
1479 } else if gohostos == "plan9" {
1480 // Check that gobin is bound before /bin.
1481 pid := strings.Replace(readfile("#c/pid"), " ", "", -1)
1482 ns := fmt.Sprintf("/proc/%s/ns", pid)
1483 if !strings.Contains(readfile(ns), fmt.Sprintf("bind -b %s /bin", gobin)) {
1484 xprintf("*** You need to bind %s before /bin.\n", gobin)
1487 // Check that gobin appears in $PATH.
1489 if gohostos == "windows" {
1492 if !strings.Contains(pathsep+os.Getenv("PATH")+pathsep, pathsep+gobin+pathsep) {
1493 xprintf("*** You need to add %s to your PATH.\n", gobin)
1497 if !xsamefile(goroot_final, goroot) {
1499 "The binaries expect %s to be copied or moved to %s\n",
1500 goroot, goroot_final)
1504 // Version prints the Go version.
1507 xprintf("%s\n", findgoversion())