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