]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/dist/build.c
[dev.garbage] all: merge default (f38460037b72) into dev.garbage
[gostls13.git] / src / cmd / dist / build.c
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.
4
5 #include "a.h"
6 #include "arg.h"
7
8 /*
9  * Initialization for any invocation.
10  */
11
12 // The usual variables.
13 char *goarch;
14 char *gobin;
15 char *gohostarch;
16 char *gohostchar;
17 char *gohostos;
18 char *goos;
19 char *goarm;
20 char *go386;
21 char *goroot = GOROOT_FINAL;
22 char *goroot_final = GOROOT_FINAL;
23 char *goextlinkenabled = "";
24 char *workdir;
25 char *tooldir;
26 char *gochar;
27 char *goversion;
28 char *slash;    // / for unix, \ for windows
29 char *defaultcc;
30 char *defaultcflags;
31 char *defaultldflags;
32 char *defaultcxxtarget;
33 char *defaultcctarget;
34 bool    rebuildall;
35 bool defaultclang;
36
37 static bool shouldbuild(char*, char*);
38 static void dopack(char*, char*, char**, int);
39 static char *findgoversion(void);
40
41 // The known architecture letters.
42 static char *gochars = "566899";
43
44 // The known architectures.
45 static char *okgoarch[] = {
46         // same order as gochars
47         "arm",
48         "amd64",
49         "amd64p32",
50         "386",
51         "power64",
52         "power64le",
53 };
54
55 // The known operating systems.
56 static char *okgoos[] = {
57         "darwin",
58         "dragonfly",
59         "linux",
60         "android",
61         "solaris",
62         "freebsd",
63         "nacl",
64         "netbsd",
65         "openbsd",
66         "plan9",
67         "windows",
68 };
69
70 static void rmworkdir(void);
71
72 // find reports the first index of p in l[0:n], or else -1.
73 int
74 find(char *p, char **l, int n)
75 {
76         int i;
77
78         for(i=0; i<n; i++)
79                 if(streq(p, l[i]))
80                         return i;
81         return -1;
82 }
83
84 // init handles initialization of the various global state, like goroot and goarch.
85 void
86 init(void)
87 {
88         char *p;
89         int i;
90         Buf b;
91
92         binit(&b);
93
94         xgetenv(&b, "GOROOT");
95         if(b.len > 0) {
96                 // if not "/", then strip trailing path separator
97                 if(b.len >= 2 && b.p[b.len - 1] == slash[0])
98                         b.len--;
99                 goroot = btake(&b);
100         }
101
102         xgetenv(&b, "GOBIN");
103         if(b.len == 0)
104                 bprintf(&b, "%s%sbin", goroot, slash);
105         gobin = btake(&b);
106
107         xgetenv(&b, "GOOS");
108         if(b.len == 0)
109                 bwritestr(&b, gohostos);
110         goos = btake(&b);
111         if(find(goos, okgoos, nelem(okgoos)) < 0)
112                 fatal("unknown $GOOS %s", goos);
113
114         xgetenv(&b, "GOARM");
115         if(b.len == 0)
116                 bwritestr(&b, xgetgoarm());
117         goarm = btake(&b);
118
119         xgetenv(&b, "GO386");
120         if(b.len == 0) {
121                 if(cansse2())
122                         bwritestr(&b, "sse2");
123                 else
124                         bwritestr(&b, "387");
125         }
126         go386 = btake(&b);
127
128         p = bpathf(&b, "%s/include/u.h", goroot);
129         if(!isfile(p)) {
130                 fatal("$GOROOT is not set correctly or not exported\n"
131                         "\tGOROOT=%s\n"
132                         "\t%s does not exist", goroot, p);
133         }
134
135         xgetenv(&b, "GOHOSTARCH");
136         if(b.len > 0)
137                 gohostarch = btake(&b);
138
139         i = find(gohostarch, okgoarch, nelem(okgoarch));
140         if(i < 0)
141                 fatal("unknown $GOHOSTARCH %s", gohostarch);
142         bprintf(&b, "%c", gochars[i]);
143         gohostchar = btake(&b);
144
145         xgetenv(&b, "GOARCH");
146         if(b.len == 0)
147                 bwritestr(&b, gohostarch);
148         goarch = btake(&b);
149         i = find(goarch, okgoarch, nelem(okgoarch));
150         if(i < 0)
151                 fatal("unknown $GOARCH %s", goarch);
152         bprintf(&b, "%c", gochars[i]);
153         gochar = btake(&b);
154
155         xgetenv(&b, "GO_EXTLINK_ENABLED");
156         if(b.len > 0) {
157                 goextlinkenabled = btake(&b);
158                 if(!streq(goextlinkenabled, "0") && !streq(goextlinkenabled, "1"))
159                         fatal("unknown $GO_EXTLINK_ENABLED %s", goextlinkenabled);
160         }
161         
162         xgetenv(&b, "CC");
163         if(b.len == 0) {
164                 // Use clang on OS X, because gcc is deprecated there.
165                 // Xcode for OS X 10.9 Mavericks will ship a fake "gcc" binary that
166                 // actually runs clang. We prepare different command
167                 // lines for the two binaries, so it matters what we call it.
168                 // See golang.org/issue/5822.
169                 if(defaultclang)
170                         bprintf(&b, "clang");
171                 else
172                         bprintf(&b, "gcc");
173         }
174         defaultcc = btake(&b);
175
176         xgetenv(&b, "CFLAGS");
177         defaultcflags = btake(&b);
178
179         xgetenv(&b, "LDFLAGS");
180         defaultldflags = btake(&b);
181
182         xgetenv(&b, "CC_FOR_TARGET");
183         if(b.len == 0) {
184                 bprintf(&b, defaultcc);
185         }
186         defaultcctarget = btake(&b);
187
188         xgetenv(&b, "CXX_FOR_TARGET");
189         if(b.len == 0) {
190                 xgetenv(&b, "CXX");
191                 if(b.len == 0) {
192                         if(defaultclang)
193                                 bprintf(&b, "clang++");
194                         else
195                                 bprintf(&b, "g++");
196                 }
197         }
198         defaultcxxtarget = btake(&b);
199
200         xsetenv("GOROOT", goroot);
201         xsetenv("GOARCH", goarch);
202         xsetenv("GOOS", goos);
203         xsetenv("GOARM", goarm);
204         xsetenv("GO386", go386);
205
206         // Make the environment more predictable.
207         xsetenv("LANG", "C");
208         xsetenv("LANGUAGE", "en_US.UTF8");
209
210         goversion = findgoversion();
211
212         workdir = xworkdir();
213         xatexit(rmworkdir);
214
215         bpathf(&b, "%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch);
216         tooldir = btake(&b);
217
218         bfree(&b);
219 }
220
221 // rmworkdir deletes the work directory.
222 static void
223 rmworkdir(void)
224 {
225         if(vflag > 1)
226                 errprintf("rm -rf %s\n", workdir);
227         xremoveall(workdir);
228 }
229
230 // Remove trailing spaces.
231 static void
232 chomp(Buf *b)
233 {
234         int c;
235
236         while(b->len > 0 && ((c=b->p[b->len-1]) == ' ' || c == '\t' || c == '\r' || c == '\n'))
237                 b->len--;
238 }
239
240
241 // findgoversion determines the Go version to use in the version string.
242 static char*
243 findgoversion(void)
244 {
245         char *tag, *rev, *p;
246         int i, nrev;
247         Buf b, path, bmore, branch;
248         Vec tags;
249
250         binit(&b);
251         binit(&path);
252         binit(&bmore);
253         binit(&branch);
254         vinit(&tags);
255
256         // The $GOROOT/VERSION file takes priority, for distributions
257         // without the Mercurial repo.
258         bpathf(&path, "%s/VERSION", goroot);
259         if(isfile(bstr(&path))) {
260                 readfile(&b, bstr(&path));
261                 chomp(&b);
262                 // Commands such as "dist version > VERSION" will cause
263                 // the shell to create an empty VERSION file and set dist's
264                 // stdout to its fd. dist in turn looks at VERSION and uses
265                 // its content if available, which is empty at this point.
266                 if(b.len > 0)
267                         goto done;
268         }
269
270         // The $GOROOT/VERSION.cache file is a cache to avoid invoking
271         // hg every time we run this command.  Unlike VERSION, it gets
272         // deleted by the clean command.
273         bpathf(&path, "%s/VERSION.cache", goroot);
274         if(isfile(bstr(&path))) {
275                 readfile(&b, bstr(&path));
276                 chomp(&b);
277                 goto done;
278         }
279
280         // Otherwise, use Mercurial.
281         // What is the current branch?
282         run(&branch, goroot, CheckExit, "hg", "identify", "-b", nil);
283         chomp(&branch);
284
285         // What are the tags along the current branch?
286         tag = "devel";
287         rev = ".";
288         run(&b, goroot, CheckExit, "hg", "log", "-b", bstr(&branch), "-r", ".:0", "--template", "{tags} + ", nil);
289         splitfields(&tags, bstr(&b));
290         nrev = 0;
291         for(i=0; i<tags.len; i++) {
292                 p = tags.p[i];
293                 if(streq(p, "+"))
294                         nrev++;
295                 // Only show the beta tag for the exact revision.
296                 if(hasprefix(p, "go") && (!contains(p, "beta") || nrev == 0)) {
297                         tag = xstrdup(p);
298                         // If this tag matches the current checkout
299                         // exactly (no "+" yet), don't show extra
300                         // revision information.
301                         if(nrev == 0)
302                                 rev = "";
303                         break;
304                 }
305         }
306
307         if(tag[0] == '\0') {
308                 // Did not find a tag; use branch name.
309                 bprintf(&b, "branch.%s", bstr(&branch));
310                 tag = btake(&b);
311         }
312
313         if(rev[0]) {
314                 // Tag is before the revision we're building.
315                 // Add extra information.
316                 run(&bmore, goroot, CheckExit, "hg", "log", "--template", " +{node|short} {date|date}", "-r", rev, nil);
317                 chomp(&bmore);
318         }
319
320         bprintf(&b, "%s", tag);
321         if(bmore.len > 0)
322                 bwriteb(&b, &bmore);
323
324         // Cache version.
325         writefile(&b, bstr(&path), 0);
326
327 done:
328         p = btake(&b);
329
330
331         bfree(&b);
332         bfree(&path);
333         bfree(&bmore);
334         bfree(&branch);
335         vfree(&tags);
336
337         return p;
338 }
339
340 /*
341  * Initial tree setup.
342  */
343
344 // The old tools that no longer live in $GOBIN or $GOROOT/bin.
345 static char *oldtool[] = {
346         "5a", "5c", "5g", "5l",
347         "6a", "6c", "6g", "6l",
348         "8a", "8c", "8g", "8l",
349         "9a", "9c", "9g", "9l",
350         "6cov",
351         "6nm",
352         "6prof",
353         "cgo",
354         "ebnflint",
355         "goapi",
356         "gofix",
357         "goinstall",
358         "gomake",
359         "gopack",
360         "gopprof",
361         "gotest",
362         "gotype",
363         "govet",
364         "goyacc",
365         "quietgcc",
366 };
367
368 // Unreleased directories (relative to $GOROOT) that should
369 // not be in release branches.
370 static char *unreleased[] = {
371         "src/cmd/link",
372         "src/debug/goobj",
373         "src/old",
374 };
375
376 // setup sets up the tree for the initial build.
377 static void
378 setup(void)
379 {
380         int i;
381         Buf b;
382         char *p;
383
384         binit(&b);
385
386         // Create bin directory.
387         p = bpathf(&b, "%s/bin", goroot);
388         if(!isdir(p))
389                 xmkdir(p);
390
391         // Create package directory.
392         p = bpathf(&b, "%s/pkg", goroot);
393         if(!isdir(p))
394                 xmkdir(p);
395         p = bpathf(&b, "%s/pkg/%s_%s", goroot, gohostos, gohostarch);
396         if(rebuildall)
397                 xremoveall(p);
398         xmkdirall(p);
399         if(!streq(goos, gohostos) || !streq(goarch, gohostarch)) {
400                 p = bpathf(&b, "%s/pkg/%s_%s", goroot, goos, goarch);
401                 if(rebuildall)
402                         xremoveall(p);
403                 xmkdirall(p);
404         }
405
406         // Create object directory.
407         // We keep it in pkg/ so that all the generated binaries
408         // are in one tree.  If pkg/obj/libgc.a exists, it is a dreg from
409         // before we used subdirectories of obj.  Delete all of obj
410         // to clean up.
411         bpathf(&b, "%s/pkg/obj/libgc.a", goroot);
412         if(isfile(bstr(&b)))
413                 xremoveall(bpathf(&b, "%s/pkg/obj", goroot));
414         p = bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch);
415         if(rebuildall)
416                 xremoveall(p);
417         xmkdirall(p);
418
419         // Create tool directory.
420         // We keep it in pkg/, just like the object directory above.
421         if(rebuildall)
422                 xremoveall(tooldir);
423         xmkdirall(tooldir);
424
425         // Remove tool binaries from before the tool/gohostos_gohostarch
426         xremoveall(bpathf(&b, "%s/bin/tool", goroot));
427
428         // Remove old pre-tool binaries.
429         for(i=0; i<nelem(oldtool); i++)
430                 xremove(bpathf(&b, "%s/bin/%s", goroot, oldtool[i]));
431
432         // If $GOBIN is set and has a Go compiler, it must be cleaned.
433         for(i=0; gochars[i]; i++) {
434                 if(isfile(bprintf(&b, "%s%s%c%s", gobin, slash, gochars[i], "g"))) {
435                         for(i=0; i<nelem(oldtool); i++)
436                                 xremove(bprintf(&b, "%s%s%s", gobin, slash, oldtool[i]));
437                         break;
438                 }
439         }
440
441         // For release, make sure excluded things are excluded.
442         if(hasprefix(goversion, "release.") || (hasprefix(goversion, "go") && !contains(goversion, "beta"))) {
443                 for(i=0; i<nelem(unreleased); i++)
444                         if(isdir(bpathf(&b, "%s/%s", goroot, unreleased[i])))
445                                 fatal("%s should not exist in release build", bstr(&b));
446         }
447
448         bfree(&b);
449 }
450
451 /*
452  * C library and tool building
453  */
454
455 // gccargs is the gcc command line to use for compiling a single C file.
456 static char *proto_gccargs[] = {
457         "-Wall",
458         // native Plan 9 compilers don't like non-standard prototypes
459         // so let gcc catch them.
460         "-Wstrict-prototypes",
461         "-Wextra",
462         "-Wunused",
463         "-Wno-sign-compare",
464         "-Wno-missing-braces",
465         "-Wno-parentheses",
466         "-Wno-unknown-pragmas",
467         "-Wno-switch",
468         "-Wno-comment",
469         "-Wno-missing-field-initializers",
470         "-Werror",
471         "-fno-common",
472         "-ggdb",
473         "-pipe",
474 };
475
476 // gccargs2 is the second part of gccargs.
477 // it is used if the environment isn't defining CFLAGS.
478 static char *proto_gccargs2[] = {
479         // on older versions of GCC, -Wuninitialized is not supported
480         // without -O, so put it here together with -O settings in case
481         // the user's $CFLAGS doesn't include -O.
482         "-Wuninitialized",
483 #if defined(__NetBSD__) && defined(__arm__)
484         // GCC 4.5.4 (NetBSD nb1 20120916) on ARM is known to mis-optimize gc/mparith3.c
485         // Fix available at http://patchwork.ozlabs.org/patch/64562/.
486         "-O1",
487 #else
488         "-O2",
489 #endif
490 };
491
492 static Vec gccargs, ldargs;
493
494 // deptab lists changes to the default dependencies for a given prefix.
495 // deps ending in /* read the whole directory; deps beginning with -
496 // exclude files with that prefix.
497 static struct {
498         char *prefix;  // prefix of target
499         char *dep[20];  // dependency tweaks for targets with that prefix
500 } deptab[] = {
501         {"lib9", {
502                 "$GOROOT/include/u.h",
503                 "$GOROOT/include/utf.h",
504                 "$GOROOT/include/fmt.h",
505                 "$GOROOT/include/libc.h",
506                 "fmt/*",
507                 "utf/*",
508         }},
509         {"libbio", {
510                 "$GOROOT/include/u.h",
511                 "$GOROOT/include/utf.h",
512                 "$GOROOT/include/fmt.h",
513                 "$GOROOT/include/libc.h",
514                 "$GOROOT/include/bio.h",
515         }},
516         {"liblink", {
517                 "$GOROOT/include/u.h",
518                 "$GOROOT/include/utf.h",
519                 "$GOROOT/include/fmt.h",
520                 "$GOROOT/include/libc.h",
521                 "$GOROOT/include/bio.h",
522                 "$GOROOT/include/ar.h",
523                 "$GOROOT/include/link.h",
524                 "anames5.c",
525                 "anames6.c",
526                 "anames8.c",
527                 "anames9.c",
528         }},
529         {"cmd/cc", {
530                 "-pgen.c",
531                 "-pswt.c",
532         }},
533         {"cmd/gc", {
534                 "-cplx.c",
535                 "-pgen.c",
536                 "-plive.c",
537                 "-popt.c",
538                 "-y1.tab.c",  // makefile dreg
539                 "opnames.h",
540         }},
541         {"cmd/5c", {
542                 "../cc/pgen.c",
543                 "../cc/pswt.c",
544                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
545         }},
546         {"cmd/6c", {
547                 "../cc/pgen.c",
548                 "../cc/pswt.c",
549                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
550         }},
551         {"cmd/8c", {
552                 "../cc/pgen.c",
553                 "../cc/pswt.c",
554                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
555         }},
556         {"cmd/9c", {
557                 "../cc/pgen.c",
558                 "../cc/pswt.c",
559                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libcc.a",
560         }},
561         {"cmd/5g", {
562                 "../gc/cplx.c",
563                 "../gc/pgen.c",
564                 "../gc/plive.c",
565                 "../gc/popt.c",
566                 "../gc/popt.h",
567                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a",
568         }},
569         {"cmd/6g", {
570                 "../gc/cplx.c",
571                 "../gc/pgen.c",
572                 "../gc/plive.c",
573                 "../gc/popt.c",
574                 "../gc/popt.h",
575                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a",
576         }},
577         {"cmd/8g", {
578                 "../gc/cplx.c",
579                 "../gc/pgen.c",
580                 "../gc/plive.c",
581                 "../gc/popt.c",
582                 "../gc/popt.h",
583                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a",
584         }},
585         {"cmd/9g", {
586                 "../gc/cplx.c",
587                 "../gc/pgen.c",
588                 "../gc/plive.c",
589                 "../gc/popt.c",
590                 "../gc/popt.h",
591                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libgc.a",
592         }},
593         {"cmd/5l", {
594                 "../ld/*",
595         }},
596         {"cmd/6l", {
597                 "../ld/*",
598         }},
599         {"cmd/8l", {
600                 "../ld/*",
601         }},
602         {"cmd/9l", {
603                 "../ld/*",
604         }},
605         {"cmd/go", {
606                 "zdefaultcc.go",
607         }},
608         {"cmd/", {
609                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/liblink.a",
610                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/libbio.a",
611                 "$GOROOT/pkg/obj/$GOHOSTOS_$GOHOSTARCH/lib9.a",
612         }},
613         {"runtime", {
614                 "zaexperiment.h", // must sort above zasm
615                 "zasm_$GOOS_$GOARCH.h",
616                 "zsys_$GOOS_$GOARCH.s",
617                 "zgoarch_$GOARCH.go",
618                 "zgoos_$GOOS.go",
619                 "zruntime_defs_$GOOS_$GOARCH.go",
620                 "zversion.go",
621         }},
622 };
623
624 // depsuffix records the allowed suffixes for source files.
625 char *depsuffix[] = {
626         ".c",
627         ".h",
628         ".s",
629         ".go",
630 };
631
632 // gentab records how to generate some trivial files.
633 static struct {
634         char *nameprefix;
635         void (*gen)(char*, char*);
636 } gentab[] = {
637         {"opnames.h", gcopnames},
638         {"anames5.c", mkanames},
639         {"anames6.c", mkanames},
640         {"anames8.c", mkanames},
641         {"anames9.c", mkanames},
642         {"zasm_", mkzasm},
643         {"zdefaultcc.go", mkzdefaultcc},
644         {"zsys_", mkzsys},
645         {"zgoarch_", mkzgoarch},
646         {"zgoos_", mkzgoos},
647         {"zruntime_defs_", mkzruntimedefs},
648         {"zversion.go", mkzversion},
649         {"zaexperiment.h", mkzexperiment},
650
651         // not generated anymore, but delete the file if we see it
652         {"enam.c", nil},
653 };
654
655 // install installs the library, package, or binary associated with dir,
656 // which is relative to $GOROOT/src.
657 static void
658 install(char *dir)
659 {
660         char *name, *p, *elem, *prefix, *exe;
661         bool islib, ispkg, isgo, stale, ispackcmd;
662         Buf b, b1, path, final_path, final_name;
663         Vec compile, files, link, go, missing, clean, lib, extra;
664         Time ttarg, t;
665         int i, j, k, n, doclean, targ;
666
667         if(vflag) {
668                 if(!streq(goos, gohostos) || !streq(goarch, gohostarch))
669                         errprintf("%s (%s/%s)\n", dir, goos, goarch);
670                 else
671                         errprintf("%s\n", dir);
672         }
673
674         binit(&b);
675         binit(&b1);
676         binit(&path);
677         binit(&final_path);
678         binit(&final_name);
679         vinit(&compile);
680         vinit(&files);
681         vinit(&link);
682         vinit(&go);
683         vinit(&missing);
684         vinit(&clean);
685         vinit(&lib);
686         vinit(&extra);
687
688
689         // path = full path to dir.
690         bpathf(&path, "%s/src/%s", goroot, dir);
691         bpathf(&final_path, "%s/src/%s", goroot_final, dir);
692         name = lastelem(dir);
693
694         // set up gcc command line on first run.
695         if(gccargs.len == 0) {
696                 bprintf(&b, "%s %s", defaultcc, defaultcflags);
697                 splitfields(&gccargs, bstr(&b));
698                 for(i=0; i<nelem(proto_gccargs); i++)
699                         vadd(&gccargs, proto_gccargs[i]);
700                 if(defaultcflags[0] == '\0') {
701                         for(i=0; i<nelem(proto_gccargs2); i++)
702                                 vadd(&gccargs, proto_gccargs2[i]);
703                 }
704                 if(contains(gccargs.p[0], "clang")) {
705                         // disable ASCII art in clang errors, if possible
706                         vadd(&gccargs, "-fno-caret-diagnostics");
707                         // clang is too smart about unused command-line arguments
708                         vadd(&gccargs, "-Qunused-arguments");
709                 }
710                 // disable word wrapping in error messages
711                 vadd(&gccargs, "-fmessage-length=0");
712                 if(streq(gohostos, "darwin")) {
713                         // golang.org/issue/5261
714                         vadd(&gccargs, "-mmacosx-version-min=10.6");
715                 }
716         }
717         if(ldargs.len == 0 && defaultldflags[0] != '\0') {
718                 bprintf(&b, "%s", defaultldflags);
719                 splitfields(&ldargs, bstr(&b));
720         }
721
722         islib = hasprefix(dir, "lib") || streq(dir, "cmd/cc") || streq(dir, "cmd/gc");
723         ispkg = !islib && !hasprefix(dir, "cmd/");
724         isgo = ispkg || streq(dir, "cmd/go") || streq(dir, "cmd/cgo");
725
726         exe = "";
727         if(streq(gohostos, "windows"))
728                 exe = ".exe";
729
730         // Start final link command line.
731         // Note: code below knows that link.p[targ] is the target.
732         ispackcmd = 0;
733         if(islib) {
734                 // C library.
735                 vadd(&link, "ar");
736                 if(streq(gohostos, "plan9"))
737                         vadd(&link, "rc");
738                 else
739                         vadd(&link, "rsc");
740                 prefix = "";
741                 if(!hasprefix(name, "lib"))
742                         prefix = "lib";
743                 targ = link.len;
744                 vadd(&link, bpathf(&b, "%s/pkg/obj/%s_%s/%s%s.a", goroot, gohostos, gohostarch, prefix, name));
745         } else if(ispkg) {
746                 // Go library (package).
747                 ispackcmd = 1;
748                 vadd(&link, "pack"); // program name - unused here, but all the other cases record one
749                 p = bprintf(&b, "%s/pkg/%s_%s/%s", goroot, goos, goarch, dir);
750                 *xstrrchr(p, '/') = '\0';
751                 xmkdirall(p);
752                 targ = link.len;
753                 vadd(&link, bpathf(&b, "%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir));
754         } else if(streq(dir, "cmd/go") || streq(dir, "cmd/cgo")) {
755                 // Go command.
756                 vadd(&link, bpathf(&b, "%s/%sl", tooldir, gochar));
757                 vadd(&link, "-o");
758                 elem = name;
759                 if(streq(elem, "go"))
760                         elem = "go_bootstrap";
761                 targ = link.len;
762                 vadd(&link, bpathf(&b, "%s/%s%s", tooldir, elem, exe));
763         } else {
764                 // C command. Use gccargs and ldargs.
765                 if(streq(gohostos, "plan9")) {
766                         vadd(&link, bprintf(&b, "%sl", gohostchar));
767                         vadd(&link, "-o");
768                         targ = link.len;
769                         vadd(&link, bpathf(&b, "%s/%s", tooldir, name));
770                 } else {
771                         vcopy(&link, gccargs.p, gccargs.len);
772                         vcopy(&link, ldargs.p, ldargs.len);
773                         if(sflag)
774                                 vadd(&link, "-static");
775                         vadd(&link, "-o");
776                         targ = link.len;
777                         vadd(&link, bpathf(&b, "%s/%s%s", tooldir, name, exe));
778                         if(streq(gohostarch, "amd64"))
779                                 vadd(&link, "-m64");
780                         else if(streq(gohostarch, "386"))
781                                 vadd(&link, "-m32");
782                 }
783         }
784         ttarg = mtime(link.p[targ]);
785
786         // Gather files that are sources for this target.
787         // Everything in that directory, and any target-specific
788         // additions.
789         xreaddir(&files, bstr(&path));
790
791         // Remove files beginning with . or _,
792         // which are likely to be editor temporary files.
793         // This is the same heuristic build.ScanDir uses.
794         // There do exist real C files beginning with _,
795         // so limit that check to just Go files.
796         n = 0;
797         for(i=0; i<files.len; i++) {
798                 p = files.p[i];
799                 if(hasprefix(p, ".") || (hasprefix(p, "_") && hassuffix(p, ".go")))
800                         xfree(p);
801                 else
802                         files.p[n++] = p;
803         }
804         files.len = n;
805
806         for(i=0; i<nelem(deptab); i++) {
807                 if(streq(dir, deptab[i].prefix) ||
808                    (hassuffix(deptab[i].prefix, "/") && hasprefix(dir, deptab[i].prefix))) {
809                         for(j=0; (p=deptab[i].dep[j])!=nil; j++) {
810                                 breset(&b1);
811                                 bwritestr(&b1, p);
812                                 bsubst(&b1, "$GOROOT", goroot);
813                                 bsubst(&b1, "$GOOS", goos);
814                                 bsubst(&b1, "$GOARCH", goarch);
815                                 bsubst(&b1, "$GOHOSTOS", gohostos);
816                                 bsubst(&b1, "$GOHOSTARCH", gohostarch);
817                                 p = bstr(&b1);
818                                 if(hassuffix(p, ".a")) {
819                                         vadd(&lib, bpathf(&b, "%s", p));
820                                         continue;
821                                 }
822                                 if(hassuffix(p, "/*")) {
823                                         bpathf(&b, "%s/%s", bstr(&path), p);
824                                         b.len -= 2;
825                                         xreaddir(&extra, bstr(&b));
826                                         bprintf(&b, "%s", p);
827                                         b.len -= 2;
828                                         for(k=0; k<extra.len; k++)
829                                                 vadd(&files, bpathf(&b1, "%s/%s", bstr(&b), extra.p[k]));
830                                         continue;
831                                 }
832                                 if(hasprefix(p, "-")) {
833                                         p++;
834                                         n = 0;
835                                         for(k=0; k<files.len; k++) {
836                                                 if(hasprefix(files.p[k], p))
837                                                         xfree(files.p[k]);
838                                                 else
839                                                         files.p[n++] = files.p[k];
840                                         }
841                                         files.len = n;
842                                         continue;
843                                 }
844                                 vadd(&files, p);
845                         }
846                 }
847         }
848         vuniq(&files);
849
850         // Convert to absolute paths.
851         for(i=0; i<files.len; i++) {
852                 if(!isabs(files.p[i])) {
853                         bpathf(&b, "%s/%s", bstr(&path), files.p[i]);
854                         xfree(files.p[i]);
855                         files.p[i] = btake(&b);
856                 }
857         }
858
859         // Is the target up-to-date?
860         stale = rebuildall;
861         n = 0;
862         for(i=0; i<files.len; i++) {
863                 p = files.p[i];
864                 for(j=0; j<nelem(depsuffix); j++)
865                         if(hassuffix(p, depsuffix[j]))
866                                 goto ok;
867                 xfree(files.p[i]);
868                 continue;
869         ok:
870                 t = mtime(p);
871                 if(t != 0 && !hassuffix(p, ".a") && !shouldbuild(p, dir)) {
872                         xfree(files.p[i]);
873                         continue;
874                 }
875                 if(hassuffix(p, ".go"))
876                         vadd(&go, p);
877                 if(t > ttarg)
878                         stale = 1;
879                 if(t == 0) {
880                         vadd(&missing, p);
881                         files.p[n++] = files.p[i];
882                         continue;
883                 }
884                 files.p[n++] = files.p[i];
885         }
886         files.len = n;
887
888         // If there are no files to compile, we're done.
889         if(files.len == 0)
890                 goto out;
891         
892         for(i=0; i<lib.len && !stale; i++)
893                 if(mtime(lib.p[i]) > ttarg)
894                         stale = 1;
895
896         if(!stale)
897                 goto out;
898
899         // For package runtime, copy some files into the work space.
900         if(streq(dir, "runtime")) {
901                 copyfile(bpathf(&b, "%s/arch_GOARCH.h", workdir),
902                         bpathf(&b1, "%s/arch_%s.h", bstr(&path), goarch), 0);
903                 copyfile(bpathf(&b, "%s/defs_GOOS_GOARCH.h", workdir),
904                         bpathf(&b1, "%s/defs_%s_%s.h", bstr(&path), goos, goarch), 0);
905                 p = bpathf(&b1, "%s/signal_%s_%s.h", bstr(&path), goos, goarch);
906                 if(isfile(p))
907                         copyfile(bpathf(&b, "%s/signal_GOOS_GOARCH.h", workdir), p, 0);
908                 copyfile(bpathf(&b, "%s/os_GOOS.h", workdir),
909                         bpathf(&b1, "%s/os_%s.h", bstr(&path), goos), 0);
910                 copyfile(bpathf(&b, "%s/signals_GOOS.h", workdir),
911                         bpathf(&b1, "%s/signals_%s.h", bstr(&path), goos), 0);
912                 copyfile(bpathf(&b, "%s/pkg/%s_%s/textflag.h", goroot, goos, goarch),
913                         bpathf(&b1, "%s/src/cmd/ld/textflag.h", goroot), 0);
914                 copyfile(bpathf(&b, "%s/pkg/%s_%s/funcdata.h", goroot, goos, goarch),
915                         bpathf(&b1, "%s/src/runtime/funcdata.h", goroot), 0);
916         }
917
918         // Generate any missing files; regenerate existing ones.
919         for(i=0; i<files.len; i++) {
920                 p = files.p[i];
921                 elem = lastelem(p);
922                 for(j=0; j<nelem(gentab); j++) {
923                         if(gentab[j].gen == nil)
924                                 continue;
925                         if(hasprefix(elem, gentab[j].nameprefix)) {
926                                 if(vflag > 1)
927                                         errprintf("generate %s\n", p);
928                                 gentab[j].gen(bstr(&path), p);
929                                 // Do not add generated file to clean list.
930                                 // In runtime, we want to be able to
931                                 // build the package with the go tool,
932                                 // and it assumes these generated files already
933                                 // exist (it does not know how to build them).
934                                 // The 'clean' command can remove
935                                 // the generated files.
936                                 goto built;
937                         }
938                 }
939                 // Did not rebuild p.
940                 if(find(p, missing.p, missing.len) >= 0)
941                         fatal("missing file %s", p);
942         built:;
943         }
944
945         // One more copy for package runtime.
946         // The last batch was required for the generators.
947         // This one is generated.
948         if(streq(dir, "runtime")) {
949                 copyfile(bpathf(&b, "%s/zasm_GOOS_GOARCH.h", workdir),
950                         bpathf(&b1, "%s/zasm_%s_%s.h", bstr(&path), goos, goarch), 0);
951         }
952
953         if((!streq(goos, gohostos) || !streq(goarch, gohostarch)) && isgo) {
954                 // We've generated the right files; the go command can do the build.
955                 if(vflag > 1)
956                         errprintf("skip build for cross-compile %s\n", dir);
957                 goto nobuild;
958         }
959
960         // Compile the files.
961         for(i=0; i<files.len; i++) {
962                 if(!hassuffix(files.p[i], ".c") && !hassuffix(files.p[i], ".s"))
963                         continue;
964                 name = lastelem(files.p[i]);
965
966                 vreset(&compile);
967                 if(!isgo) {
968                         // C library or tool.
969                         if(streq(gohostos, "plan9")) {
970                                 vadd(&compile, bprintf(&b, "%sc", gohostchar));
971                                 vadd(&compile, "-FTVwp");
972                                 vadd(&compile, "-DPLAN9");
973                                 vadd(&compile, "-D__STDC__=1");
974                                 vadd(&compile, "-D__SIZE_TYPE__=ulong"); // for GNU Bison
975                                 vadd(&compile, bpathf(&b, "-I%s/include/plan9", goroot));
976                                 vadd(&compile, bpathf(&b, "-I%s/include/plan9/%s", goroot, gohostarch));
977                         } else {
978                                 vcopy(&compile, gccargs.p, gccargs.len);
979                                 vadd(&compile, "-c");
980                                 if(streq(gohostarch, "amd64"))
981                                         vadd(&compile, "-m64");
982                                 else if(streq(gohostarch, "386"))
983                                         vadd(&compile, "-m32");
984         
985                                 vadd(&compile, "-I");
986                                 vadd(&compile, bpathf(&b, "%s/include", goroot));
987                         }
988
989                         if(streq(dir, "lib9"))
990                                 vadd(&compile, "-DPLAN9PORT");
991
992
993                         vadd(&compile, "-I");
994                         vadd(&compile, bstr(&path));
995
996                         // lib9/goos.c gets the default constants hard-coded.
997                         if(streq(name, "goos.c")) {
998                                 vadd(&compile, "-D");
999                                 vadd(&compile, bprintf(&b, "GOOS=\"%s\"", goos));
1000                                 vadd(&compile, "-D");
1001                                 vadd(&compile, bprintf(&b, "GOARCH=\"%s\"", goarch));
1002                                 bprintf(&b1, "%s", goroot_final);
1003                                 bsubst(&b1, "\\", "\\\\");  // turn into C string
1004                                 vadd(&compile, "-D");
1005                                 vadd(&compile, bprintf(&b, "GOROOT=\"%s\"", bstr(&b1)));
1006                                 vadd(&compile, "-D");
1007                                 vadd(&compile, bprintf(&b, "GOVERSION=\"%s\"", goversion));
1008                                 vadd(&compile, "-D");
1009                                 vadd(&compile, bprintf(&b, "GOARM=\"%s\"", goarm));
1010                                 vadd(&compile, "-D");
1011                                 vadd(&compile, bprintf(&b, "GO386=\"%s\"", go386));
1012                                 vadd(&compile, "-D");
1013                                 vadd(&compile, bprintf(&b, "GO_EXTLINK_ENABLED=\"%s\"", goextlinkenabled));
1014                         }
1015
1016                         // gc/lex.c records the GOEXPERIMENT setting used during the build.
1017                         if(streq(name, "lex.c")) {
1018                                 xgetenv(&b, "GOEXPERIMENT");
1019                                 vadd(&compile, "-D");
1020                                 vadd(&compile, bprintf(&b1, "GOEXPERIMENT=\"%s\"", bstr(&b)));
1021                         }
1022                 } else {
1023                         // Supporting files for a Go package.
1024                         if(hassuffix(files.p[i], ".s"))
1025                                 vadd(&compile, bpathf(&b, "%s/%sa", tooldir, gochar));
1026                         else {
1027                                 vadd(&compile, bpathf(&b, "%s/%sc", tooldir, gochar));
1028                                 vadd(&compile, "-F");
1029                                 vadd(&compile, "-V");
1030                                 vadd(&compile, "-w");
1031                         }
1032                         vadd(&compile, "-I");
1033                         vadd(&compile, workdir);
1034                         vadd(&compile, "-I");
1035                         vadd(&compile, bprintf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
1036                         vadd(&compile, "-D");
1037                         vadd(&compile, bprintf(&b, "GOOS_%s", goos));
1038                         vadd(&compile, "-D");
1039                         vadd(&compile, bprintf(&b, "GOARCH_%s", goarch));
1040                         vadd(&compile, "-D");
1041                         vadd(&compile, bprintf(&b, "GOOS_GOARCH_%s_%s", goos, goarch));
1042                 }
1043
1044                 bpathf(&b, "%s/%s", workdir, lastelem(files.p[i]));
1045                 doclean = 1;
1046                 if(!isgo && streq(gohostos, "darwin")) {
1047                         // To debug C programs on OS X, it is not enough to say -ggdb
1048                         // on the command line.  You have to leave the object files
1049                         // lying around too.  Leave them in pkg/obj/, which does not
1050                         // get removed when this tool exits.
1051                         bpathf(&b1, "%s/pkg/obj/%s", goroot, dir);
1052                         xmkdirall(bstr(&b1));
1053                         bpathf(&b, "%s/%s", bstr(&b1), lastelem(files.p[i]));
1054                         doclean = 0;
1055                 }
1056
1057                 // Change the last character of the output file (which was c or s).
1058                 if(streq(gohostos, "plan9"))
1059                         b.p[b.len-1] = gohostchar[0];
1060                 else
1061                         b.p[b.len-1] = 'o';
1062                 vadd(&compile, "-o");
1063                 vadd(&compile, bstr(&b));
1064                 vadd(&compile, files.p[i]);
1065                 bgrunv(bstr(&path), CheckExit, &compile);
1066
1067                 vadd(&link, bstr(&b));
1068                 if(doclean)
1069                         vadd(&clean, bstr(&b));
1070         }
1071         bgwait();
1072
1073         if(isgo) {
1074                 // The last loop was compiling individual files.
1075                 // Hand the Go files to the compiler en masse.
1076                 vreset(&compile);
1077                 vadd(&compile, bpathf(&b, "%s/%sg", tooldir, gochar));
1078
1079                 bpathf(&b, "%s/_go_.a", workdir);
1080                 vadd(&compile, "-pack");
1081                 vadd(&compile, "-o");
1082                 vadd(&compile, bstr(&b));
1083                 vadd(&clean, bstr(&b));
1084                 if(!ispackcmd)
1085                         vadd(&link, bstr(&b));
1086
1087                 vadd(&compile, "-p");
1088                 if(hasprefix(dir, "pkg/"))
1089                         vadd(&compile, dir+4);
1090                 else
1091                         vadd(&compile, "main");
1092
1093                 if(streq(dir, "runtime"))
1094                         vadd(&compile, "-+");
1095
1096                 vcopy(&compile, go.p, go.len);
1097
1098                 runv(nil, bstr(&path), CheckExit, &compile);
1099
1100                 if(ispackcmd) {
1101                         xremove(link.p[targ]);
1102                         dopack(link.p[targ], bstr(&b), &link.p[targ+1], link.len - (targ+1));
1103                         goto nobuild;
1104                 }
1105         }
1106
1107         if(!islib && !isgo) {
1108                 // C binaries need the libraries explicitly, and -lm.
1109                 vcopy(&link, lib.p, lib.len);
1110                 if(!streq(gohostos, "plan9"))
1111                         vadd(&link, "-lm");
1112         }
1113
1114         // Remove target before writing it.
1115         xremove(link.p[targ]);
1116
1117         runv(nil, nil, CheckExit, &link);
1118
1119 nobuild:
1120         // In package runtime, we install runtime.h and cgocall.h too,
1121         // for use by cgo compilation.
1122         if(streq(dir, "runtime")) {
1123                 copyfile(bpathf(&b, "%s/pkg/%s_%s/cgocall.h", goroot, goos, goarch),
1124                         bpathf(&b1, "%s/src/runtime/cgocall.h", goroot), 0);
1125                 copyfile(bpathf(&b, "%s/pkg/%s_%s/runtime.h", goroot, goos, goarch),
1126                         bpathf(&b1, "%s/src/runtime/runtime.h", goroot), 0);
1127         }
1128
1129
1130 out:
1131         for(i=0; i<clean.len; i++)
1132                 xremove(clean.p[i]);
1133
1134         bfree(&b);
1135         bfree(&b1);
1136         bfree(&path);
1137         vfree(&compile);
1138         vfree(&files);
1139         vfree(&link);
1140         vfree(&go);
1141         vfree(&missing);
1142         vfree(&clean);
1143         vfree(&lib);
1144         vfree(&extra);
1145 }
1146
1147 // matchfield reports whether the field matches this build.
1148 static bool
1149 matchfield(char *f)
1150 {
1151         char *p;
1152         bool res;
1153
1154         p = xstrrchr(f, ',');
1155         if(p == nil)
1156                 return streq(f, goos) || streq(f, goarch) || streq(f, "cmd_go_bootstrap") || streq(f, "go1.1") || (streq(goos, "android") && streq(f, "linux"));
1157         *p = 0;
1158         res = matchfield(f) && matchfield(p+1);
1159         *p = ',';
1160         return res;
1161 }
1162
1163 // shouldbuild reports whether we should build this file.
1164 // It applies the same rules that are used with context tags
1165 // in package go/build, except that the GOOS and GOARCH
1166 // can appear anywhere in the file name, not just after _.
1167 // In particular, they can be the entire file name (like windows.c).
1168 // We also allow the special tag cmd_go_bootstrap.
1169 // See ../go/bootstrap.go and package go/build.
1170 static bool
1171 shouldbuild(char *file, char *dir)
1172 {
1173         char *name, *p;
1174         int i, j, ret;
1175         Buf b;
1176         Vec lines, fields;
1177         
1178         // Check file name for GOOS or GOARCH.
1179         name = lastelem(file);
1180         for(i=0; i<nelem(okgoos); i++) {
1181                 if(streq(okgoos[i], goos))
1182                         continue;
1183                 p = xstrstr(name, okgoos[i]);
1184                 if(p == nil)
1185                         continue;
1186                 p += xstrlen(okgoos[i]);
1187                 if(*p == '.' || *p == '_' || *p == '\0')
1188                         return 0;
1189         }
1190         for(i=0; i<nelem(okgoarch); i++) {
1191                 if(streq(okgoarch[i], goarch))
1192                         continue;
1193                 p = xstrstr(name, okgoarch[i]);
1194                 if(p == nil)
1195                         continue;
1196                 p += xstrlen(okgoarch[i]);
1197                 if(*p == '.' || *p == '_' || *p == '\0')
1198                         return 0;
1199         }
1200
1201         // Omit test files.
1202         if(contains(name, "_test"))
1203                 return 0;
1204
1205         // cmd/go/doc.go has a giant /* */ comment before
1206         // it gets to the important detail that it is not part of
1207         // package main.  We don't parse those comments,
1208         // so special case that file.
1209         if(hassuffix(file, "cmd/go/doc.go") || hassuffix(file, "cmd\\go\\doc.go"))
1210                 return 0;
1211         if(hassuffix(file, "cmd/cgo/doc.go") || hassuffix(file, "cmd\\cgo\\doc.go"))
1212                 return 0;
1213
1214         // Check file contents for // +build lines.
1215         binit(&b);
1216         vinit(&lines);
1217         vinit(&fields);
1218
1219         ret = 1;
1220         readfile(&b, file);
1221         splitlines(&lines, bstr(&b));
1222         for(i=0; i<lines.len; i++) {
1223                 p = lines.p[i];
1224                 while(*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
1225                         p++;
1226                 if(*p == '\0')
1227                         continue;
1228                 if(contains(p, "package documentation")) {
1229                         ret = 0;
1230                         goto out;
1231                 }
1232                 if(contains(p, "package main") && !streq(dir, "cmd/go") && !streq(dir, "cmd/cgo")) {
1233                         ret = 0;
1234                         goto out;
1235                 }
1236                 if(!hasprefix(p, "//"))
1237                         break;
1238                 if(!contains(p, "+build"))
1239                         continue;
1240                 splitfields(&fields, lines.p[i]);
1241                 if(fields.len < 2 || !streq(fields.p[1], "+build"))
1242                         continue;
1243                 for(j=2; j<fields.len; j++) {
1244                         p = fields.p[j];
1245                         if((*p == '!' && !matchfield(p+1)) || matchfield(p))
1246                                 goto fieldmatch;
1247                 }
1248                 ret = 0;
1249                 goto out;
1250         fieldmatch:;
1251         }
1252
1253 out:
1254         bfree(&b);
1255         vfree(&lines);
1256         vfree(&fields);
1257
1258         return ret;
1259 }
1260
1261 // copy copies the file src to dst, via memory (so only good for small files).
1262 void
1263 copyfile(char *dst, char *src, int exec)
1264 {
1265         Buf b;
1266
1267         if(vflag > 1)
1268                 errprintf("cp %s %s\n", src, dst);
1269
1270         binit(&b);
1271         readfile(&b, src);
1272         writefile(&b, dst, exec);
1273         bfree(&b);
1274 }
1275
1276 // dopack copies the package src to dst,
1277 // appending the files listed in extra.
1278 // The archive format is the traditional Unix ar format.
1279 static void
1280 dopack(char *dst, char *src, char **extra, int nextra)
1281 {
1282         int i;
1283         char c, *p, *q;
1284         Buf b, bdst;
1285         
1286         binit(&b);
1287         binit(&bdst);
1288
1289         readfile(&bdst, src);
1290         for(i=0; i<nextra; i++) {
1291                 readfile(&b, extra[i]);
1292                 // find last path element for archive member name
1293                 p = xstrrchr(extra[i], '/');
1294                 if(p)
1295                         p++;
1296                 q = xstrrchr(extra[i], '\\');
1297                 if(q) {
1298                         q++;
1299                         if(p == nil || q > p)
1300                                 p = q;
1301                 }
1302                 if(p == nil)
1303                         p = extra[i];
1304                 bwritef(&bdst, "%-16.16s%-12d%-6d%-6d%-8o%-10d`\n", p, 0, 0, 0, 0644, b.len);
1305                 bwriteb(&bdst, &b);
1306                 if(b.len&1) {
1307                         c = 0;
1308                         bwrite(&bdst, &c, 1);
1309                 }
1310         }
1311
1312         writefile(&bdst, dst, 0);
1313
1314         bfree(&b);
1315         bfree(&bdst);
1316 }
1317
1318 // buildorder records the order of builds for the 'go bootstrap' command.
1319 static char *buildorder[] = {
1320         "lib9",
1321         "libbio",
1322         "liblink",
1323
1324         "cmd/cc",  // must be before c
1325         "cmd/gc",  // must be before g
1326         "cmd/%sl",  // must be before a, c, g
1327         "cmd/%sa",
1328         "cmd/%sc",
1329         "cmd/%sg",
1330
1331         // The dependency order here was copied from a buildscript
1332         // back when there were build scripts.  Will have to
1333         // be maintained by hand, but shouldn't change very
1334         // often.
1335         "runtime",
1336         "errors",
1337         "sync/atomic",
1338         "sync",
1339         "io",
1340         "unicode",
1341         "unicode/utf8",
1342         "unicode/utf16",
1343         "bytes",
1344         "math",
1345         "strings",
1346         "strconv",
1347         "bufio",
1348         "sort",
1349         "container/heap",
1350         "encoding/base64",
1351         "syscall",
1352         "time",
1353         "os",
1354         "reflect",
1355         "fmt",
1356         "encoding",
1357         "encoding/json",
1358         "flag",
1359         "path/filepath",
1360         "path",
1361         "io/ioutil",
1362         "log",
1363         "regexp/syntax",
1364         "regexp",
1365         "go/token",
1366         "go/scanner",
1367         "go/ast",
1368         "go/parser",
1369         "os/exec",
1370         "os/signal",
1371         "net/url",
1372         "text/template/parse",
1373         "text/template",
1374         "go/doc",
1375         "go/build",
1376         "cmd/go",
1377 };
1378
1379 // cleantab records the directories to clean in 'go clean'.
1380 // It is bigger than the buildorder because we clean all the
1381 // compilers but build only the $GOARCH ones.
1382 static char *cleantab[] = {
1383         // Commands and C libraries.
1384         "cmd/5a",
1385         "cmd/5c",
1386         "cmd/5g",
1387         "cmd/5l",
1388         "cmd/6a",
1389         "cmd/6c",
1390         "cmd/6g",
1391         "cmd/6l",
1392         "cmd/8a",
1393         "cmd/8c",
1394         "cmd/8g",
1395         "cmd/8l",
1396         "cmd/9a",
1397         "cmd/9c",
1398         "cmd/9g",
1399         "cmd/9l",
1400         "cmd/cc",
1401         "cmd/gc",
1402         "cmd/go",       
1403         "lib9",
1404         "libbio",
1405         "liblink",
1406
1407         // Go packages.
1408         "bufio",
1409         "bytes",
1410         "container/heap",
1411         "encoding",
1412         "encoding/base64",
1413         "encoding/json",
1414         "errors",
1415         "flag",
1416         "fmt",
1417         "go/ast",
1418         "go/build",
1419         "go/doc",
1420         "go/parser",
1421         "go/scanner",
1422         "go/token",
1423         "io",
1424         "io/ioutil",
1425         "log",
1426         "math",
1427         "net/url",
1428         "os",
1429         "os/exec",
1430         "path",
1431         "path/filepath",
1432         "reflect",
1433         "regexp",
1434         "regexp/syntax",
1435         "runtime",
1436         "sort",
1437         "strconv",
1438         "strings",
1439         "sync",
1440         "sync/atomic",
1441         "syscall",
1442         "text/template",
1443         "text/template/parse",
1444         "time",
1445         "unicode",
1446         "unicode/utf16",
1447         "unicode/utf8",
1448 };
1449
1450 static void
1451 clean(void)
1452 {
1453         int i, j, k;
1454         Buf b, path;
1455         Vec dir;
1456
1457         binit(&b);
1458         binit(&path);
1459         vinit(&dir);
1460
1461         for(i=0; i<nelem(cleantab); i++) {
1462                 bpathf(&path, "%s/src/%s", goroot, cleantab[i]);
1463                 xreaddir(&dir, bstr(&path));
1464                 // Remove generated files.
1465                 for(j=0; j<dir.len; j++) {
1466                         for(k=0; k<nelem(gentab); k++) {
1467                                 if(hasprefix(dir.p[j], gentab[k].nameprefix))
1468                                         xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j]));
1469                         }
1470                 }
1471                 // Remove generated binary named for directory.
1472                 if(hasprefix(cleantab[i], "cmd/"))
1473                         xremove(bpathf(&b, "%s/%s", bstr(&path), cleantab[i]+4));
1474         }
1475
1476         // remove src/runtime/z* unconditionally
1477         vreset(&dir);
1478         bpathf(&path, "%s/src/runtime", goroot);
1479         xreaddir(&dir, bstr(&path));
1480         for(j=0; j<dir.len; j++) {
1481                 if(hasprefix(dir.p[j], "z"))
1482                         xremove(bpathf(&b, "%s/%s", bstr(&path), dir.p[j]));
1483         }
1484
1485         if(rebuildall) {
1486                 // Remove object tree.
1487                 xremoveall(bpathf(&b, "%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch));
1488
1489                 // Remove installed packages and tools.
1490                 xremoveall(bpathf(&b, "%s/pkg/%s_%s", goroot, gohostos, gohostarch));
1491                 xremoveall(bpathf(&b, "%s/pkg/%s_%s", goroot, goos, goarch));
1492                 xremoveall(tooldir);
1493
1494                 // Remove cached version info.
1495                 xremove(bpathf(&b, "%s/VERSION.cache", goroot));
1496         }
1497
1498         bfree(&b);
1499         bfree(&path);
1500         vfree(&dir);
1501 }
1502
1503 /*
1504  * command implementations
1505  */
1506
1507 void
1508 usage(void)
1509 {
1510         xprintf("usage: go tool dist [command]\n"
1511                 "Commands are:\n"
1512                 "\n"
1513                 "banner         print installation banner\n"
1514                 "bootstrap      rebuild everything\n"
1515                 "clean          deletes all built files\n"
1516                 "env [-p]       print environment (-p: include $PATH)\n"
1517                 "install [dir]  install individual directory\n"
1518                 "version        print Go version\n"
1519                 "\n"
1520                 "All commands take -v flags to emit extra information.\n"
1521         );
1522         xexit(2);
1523 }
1524
1525 // The env command prints the default environment.
1526 void
1527 cmdenv(int argc, char **argv)
1528 {
1529         bool pflag;
1530         char *sep;
1531         Buf b, b1;
1532         char *format;
1533
1534         binit(&b);
1535         binit(&b1);
1536
1537         format = "%s=\"%s\"\n";
1538         pflag = 0;
1539         ARGBEGIN{
1540         case '9':
1541                 format = "%s='%s'\n";
1542                 break;
1543         case 'p':
1544                 pflag = 1;
1545                 break;
1546         case 'v':
1547                 vflag++;
1548                 break;
1549         case 'w':
1550                 format = "set %s=%s\r\n";
1551                 break;
1552         default:
1553                 usage();
1554         }ARGEND
1555
1556         if(argc > 0)
1557                 usage();
1558
1559         xprintf(format, "CC", defaultcc);
1560         xprintf(format, "CC_FOR_TARGET", defaultcctarget);
1561         xprintf(format, "GOROOT", goroot);
1562         xprintf(format, "GOBIN", gobin);
1563         xprintf(format, "GOARCH", goarch);
1564         xprintf(format, "GOOS", goos);
1565         xprintf(format, "GOHOSTARCH", gohostarch);
1566         xprintf(format, "GOHOSTOS", gohostos);
1567         xprintf(format, "GOTOOLDIR", tooldir);
1568         xprintf(format, "GOCHAR", gochar);
1569         if(streq(goarch, "arm"))
1570                 xprintf(format, "GOARM", goarm);
1571         if(streq(goarch, "386"))
1572                 xprintf(format, "GO386", go386);
1573
1574         if(pflag) {
1575                 sep = ":";
1576                 if(streq(gohostos, "windows"))
1577                         sep = ";";
1578                 xgetenv(&b, "PATH");
1579                 bprintf(&b1, "%s%s%s", gobin, sep, bstr(&b));
1580                 xprintf(format, "PATH", bstr(&b1));
1581         }
1582
1583         bfree(&b);
1584         bfree(&b1);
1585 }
1586
1587 // The bootstrap command runs a build from scratch,
1588 // stopping at having installed the go_bootstrap command.
1589 void
1590 cmdbootstrap(int argc, char **argv)
1591 {
1592         int i;
1593         Buf b;
1594         char *oldgoos, *oldgoarch, *oldgochar;
1595
1596         binit(&b);
1597
1598         ARGBEGIN{
1599         case 'a':
1600                 rebuildall = 1;
1601                 break;
1602         case 's':
1603                 sflag++;
1604                 break;
1605         case 'v':
1606                 vflag++;
1607                 break;
1608         default:
1609                 usage();
1610         }ARGEND
1611
1612         if(argc > 0)
1613                 usage();
1614
1615         if(isdir(bpathf(&b, "%s/src/pkg", goroot))) {
1616                 fatal("\n\n"
1617                         "The Go package sources have moved to $GOROOT/src.\n"
1618                         "*** %s still exists. ***\n"
1619                         "It probably contains stale files that may confuse the build.\n"
1620                         "Please (check what's there and) remove it and try again.\n"
1621                         "See http://golang.org/s/go14nopkg\n", bpathf(&b, "%s/src/pkg", goroot));
1622         }
1623         
1624         if(rebuildall)
1625                 clean();
1626         goversion = findgoversion();
1627         setup();
1628
1629         xsetenv("GOROOT", goroot);
1630         xsetenv("GOROOT_FINAL", goroot_final);
1631
1632         // For the main bootstrap, building for host os/arch.
1633         oldgoos = goos;
1634         oldgoarch = goarch;
1635         oldgochar = gochar;
1636         goos = gohostos;
1637         goarch = gohostarch;
1638         gochar = gohostchar;
1639         xsetenv("GOARCH", goarch);
1640         xsetenv("GOOS", goos);
1641
1642         for(i=0; i<nelem(buildorder); i++) {
1643                 install(bprintf(&b, buildorder[i], gohostchar));
1644                 if(!streq(oldgochar, gohostchar) && xstrstr(buildorder[i], "%s"))
1645                         install(bprintf(&b, buildorder[i], oldgochar));
1646         }
1647
1648         goos = oldgoos;
1649         goarch = oldgoarch;
1650         gochar = oldgochar;
1651         xsetenv("GOARCH", goarch);
1652         xsetenv("GOOS", goos);
1653
1654         // Build runtime for actual goos/goarch too.
1655         if(!streq(goos, gohostos) || !streq(goarch, gohostarch))
1656                 install("runtime");
1657
1658         bfree(&b);
1659 }
1660
1661 static char*
1662 defaulttarg(void)
1663 {
1664         char *p;
1665         Buf pwd, src, real_src;
1666
1667         binit(&pwd);
1668         binit(&src);
1669         binit(&real_src);
1670
1671         // xgetwd might return a path with symlinks fully resolved, and if
1672         // there happens to be symlinks in goroot, then the hasprefix test
1673         // will never succeed. Instead, we use xrealwd to get a canonical
1674         // goroot/src before the comparison to avoid this problem.
1675         xgetwd(&pwd);
1676         p = btake(&pwd);
1677         bpathf(&src, "%s/src/", goroot);
1678         xrealwd(&real_src, bstr(&src));
1679         if(!hasprefix(p, bstr(&real_src)))
1680                 fatal("current directory %s is not under %s", p, bstr(&real_src));
1681         p += real_src.len;
1682         // guard againt xrealwd return the directory without the trailing /
1683         if(*p == slash[0])
1684                 p++;
1685
1686         bfree(&pwd);
1687         bfree(&src);
1688         bfree(&real_src);
1689
1690         return p;
1691 }
1692
1693 // Install installs the list of packages named on the command line.
1694 void
1695 cmdinstall(int argc, char **argv)
1696 {
1697         int i;
1698
1699         ARGBEGIN{
1700         case 's':
1701                 sflag++;
1702                 break;
1703         case 'v':
1704                 vflag++;
1705                 break;
1706         default:
1707                 usage();
1708         }ARGEND
1709
1710         if(argc == 0)
1711                 install(defaulttarg());
1712
1713         for(i=0; i<argc; i++)
1714                 install(argv[i]);
1715 }
1716
1717 // Clean deletes temporary objects.
1718 // Clean -i deletes the installed objects too.
1719 void
1720 cmdclean(int argc, char **argv)
1721 {
1722         ARGBEGIN{
1723         case 'v':
1724                 vflag++;
1725                 break;
1726         default:
1727                 usage();
1728         }ARGEND
1729
1730         if(argc > 0)
1731                 usage();
1732
1733         clean();
1734 }
1735
1736 // Banner prints the 'now you've installed Go' banner.
1737 void
1738 cmdbanner(int argc, char **argv)
1739 {
1740         char *pathsep, *pid, *ns;
1741         Buf b, b1, search, path;
1742
1743         ARGBEGIN{
1744         case 'v':
1745                 vflag++;
1746                 break;
1747         default:
1748                 usage();
1749         }ARGEND
1750
1751         if(argc > 0)
1752                 usage();
1753
1754         binit(&b);
1755         binit(&b1);
1756         binit(&search);
1757         binit(&path);
1758
1759         xprintf("\n");
1760         xprintf("---\n");
1761         xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot);
1762         xprintf("Installed commands in %s\n", gobin);
1763
1764         if(!xsamefile(goroot_final, goroot)) {
1765                 // If the files are to be moved, don't check that gobin
1766                 // is on PATH; assume they know what they are doing.
1767         } else if(streq(gohostos, "plan9")) {
1768                 // Check that gobin is bound before /bin.
1769                 readfile(&b, "#c/pid");
1770                 bsubst(&b, " ", "");
1771                 pid = btake(&b);
1772                 bprintf(&b, "/proc/%s/ns", pid);
1773                 ns = btake(&b);
1774                 readfile(&b, ns);
1775                 bprintf(&search, "bind -b %s /bin\n", gobin);
1776                 if(xstrstr(bstr(&b), bstr(&search)) == nil)
1777                         xprintf("*** You need to bind %s before /bin.\n", gobin);
1778         } else {
1779                 // Check that gobin appears in $PATH.
1780                 xgetenv(&b, "PATH");
1781                 pathsep = ":";
1782                 if(streq(gohostos, "windows"))
1783                         pathsep = ";";
1784                 bprintf(&b1, "%s%s%s", pathsep, bstr(&b), pathsep);
1785                 bprintf(&search, "%s%s%s", pathsep, gobin, pathsep);
1786                 if(xstrstr(bstr(&b1), bstr(&search)) == nil)
1787                         xprintf("*** You need to add %s to your PATH.\n", gobin);
1788         }
1789
1790         if(streq(gohostos, "darwin")) {
1791                 if(isfile(bpathf(&path, "%s/cov", tooldir)))
1792                         xprintf("\n"
1793                                 "On OS X the debuggers must be installed setgid procmod.\n"
1794                                 "Read and run ./sudo.bash to install the debuggers.\n");
1795         }
1796
1797         if(!xsamefile(goroot_final, goroot)) {
1798                 xprintf("\n"
1799                         "The binaries expect %s to be copied or moved to %s\n",
1800                         goroot, goroot_final);
1801         }
1802
1803         bfree(&b);
1804         bfree(&b1);
1805         bfree(&search);
1806         bfree(&path);
1807 }
1808
1809 // Version prints the Go version.
1810 void
1811 cmdversion(int argc, char **argv)
1812 {
1813         ARGBEGIN{
1814         case 'v':
1815                 vflag++;
1816                 break;
1817         default:
1818                 usage();
1819         }ARGEND
1820
1821         if(argc > 0)
1822                 usage();
1823
1824         xprintf("%s\n", goversion);
1825 }