github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/dist/build.c (about)

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