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