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