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