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