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