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