...

Source file src/cmd/dist/build.go

     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	package main
     6	
     7	import (
     8		"bytes"
     9		"encoding/json"
    10		"flag"
    11		"fmt"
    12		"io/ioutil"
    13		"log"
    14		"os"
    15		"os/exec"
    16		"path/filepath"
    17		"sort"
    18		"strings"
    19		"sync"
    20		"time"
    21	)
    22	
    23	// Initialization for any invocation.
    24	
    25	// The usual variables.
    26	var (
    27		goarch           string
    28		gobin            string
    29		gohostarch       string
    30		gohostos         string
    31		goos             string
    32		goarm            string
    33		go386            string
    34		gomips           string
    35		gomips64         string
    36		goppc64          string
    37		goroot           string
    38		goroot_final     string
    39		goextlinkenabled string
    40		gogcflags        string // For running built compiler
    41		goldflags        string
    42		workdir          string
    43		tooldir          string
    44		oldgoos          string
    45		oldgoarch        string
    46		exe              string
    47		defaultcc        map[string]string
    48		defaultcxx       map[string]string
    49		defaultcflags    string
    50		defaultldflags   string
    51		defaultpkgconfig string
    52		defaultldso      string
    53	
    54		rebuildall   bool
    55		defaultclang bool
    56	
    57		vflag int // verbosity
    58	)
    59	
    60	// The known architectures.
    61	var okgoarch = []string{
    62		"386",
    63		"amd64",
    64		"amd64p32",
    65		"arm",
    66		"arm64",
    67		"mips",
    68		"mipsle",
    69		"mips64",
    70		"mips64le",
    71		"ppc64",
    72		"ppc64le",
    73		"riscv64",
    74		"s390x",
    75		"sparc64",
    76		"wasm",
    77	}
    78	
    79	// The known operating systems.
    80	var okgoos = []string{
    81		"darwin",
    82		"dragonfly",
    83		"illumos",
    84		"js",
    85		"linux",
    86		"android",
    87		"solaris",
    88		"freebsd",
    89		"nacl",
    90		"netbsd",
    91		"openbsd",
    92		"plan9",
    93		"windows",
    94		"aix",
    95	}
    96	
    97	// find reports the first index of p in l[0:n], or else -1.
    98	func find(p string, l []string) int {
    99		for i, s := range l {
   100			if p == s {
   101				return i
   102			}
   103		}
   104		return -1
   105	}
   106	
   107	// xinit handles initialization of the various global state, like goroot and goarch.
   108	func xinit() {
   109		b := os.Getenv("GOROOT")
   110		if b == "" {
   111			fatalf("$GOROOT must be set")
   112		}
   113		goroot = filepath.Clean(b)
   114	
   115		b = os.Getenv("GOROOT_FINAL")
   116		if b == "" {
   117			b = goroot
   118		}
   119		goroot_final = b
   120	
   121		b = os.Getenv("GOBIN")
   122		if b == "" {
   123			b = pathf("%s/bin", goroot)
   124		}
   125		gobin = b
   126	
   127		b = os.Getenv("GOOS")
   128		if b == "" {
   129			b = gohostos
   130		}
   131		goos = b
   132		if find(goos, okgoos) < 0 {
   133			fatalf("unknown $GOOS %s", goos)
   134		}
   135	
   136		b = os.Getenv("GOARM")
   137		if b == "" {
   138			b = xgetgoarm()
   139		}
   140		goarm = b
   141	
   142		b = os.Getenv("GO386")
   143		if b == "" {
   144			if cansse2() {
   145				b = "sse2"
   146			} else {
   147				b = "387"
   148			}
   149		}
   150		go386 = b
   151	
   152		b = os.Getenv("GOMIPS")
   153		if b == "" {
   154			b = "hardfloat"
   155		}
   156		gomips = b
   157	
   158		b = os.Getenv("GOMIPS64")
   159		if b == "" {
   160			b = "hardfloat"
   161		}
   162		gomips64 = b
   163	
   164		b = os.Getenv("GOPPC64")
   165		if b == "" {
   166			b = "power8"
   167		}
   168		goppc64 = b
   169	
   170		if p := pathf("%s/src/all.bash", goroot); !isfile(p) {
   171			fatalf("$GOROOT is not set correctly or not exported\n"+
   172				"\tGOROOT=%s\n"+
   173				"\t%s does not exist", goroot, p)
   174		}
   175	
   176		b = os.Getenv("GOHOSTARCH")
   177		if b != "" {
   178			gohostarch = b
   179		}
   180		if find(gohostarch, okgoarch) < 0 {
   181			fatalf("unknown $GOHOSTARCH %s", gohostarch)
   182		}
   183	
   184		b = os.Getenv("GOARCH")
   185		if b == "" {
   186			b = gohostarch
   187		}
   188		goarch = b
   189		if find(goarch, okgoarch) < 0 {
   190			fatalf("unknown $GOARCH %s", goarch)
   191		}
   192	
   193		b = os.Getenv("GO_EXTLINK_ENABLED")
   194		if b != "" {
   195			if b != "0" && b != "1" {
   196				fatalf("unknown $GO_EXTLINK_ENABLED %s", b)
   197			}
   198			goextlinkenabled = b
   199		}
   200	
   201		gogcflags = os.Getenv("BOOT_GO_GCFLAGS")
   202		goldflags = os.Getenv("BOOT_GO_LDFLAGS")
   203	
   204		cc, cxx := "gcc", "g++"
   205		if defaultclang {
   206			cc, cxx = "clang", "clang++"
   207		}
   208		defaultcc = compilerEnv("CC", cc)
   209		defaultcxx = compilerEnv("CXX", cxx)
   210	
   211		defaultcflags = os.Getenv("CFLAGS")
   212		defaultldflags = os.Getenv("LDFLAGS")
   213	
   214		b = os.Getenv("PKG_CONFIG")
   215		if b == "" {
   216			b = "pkg-config"
   217		}
   218		defaultpkgconfig = b
   219	
   220		defaultldso = os.Getenv("GO_LDSO")
   221	
   222		// For tools being invoked but also for os.ExpandEnv.
   223		os.Setenv("GO386", go386)
   224		os.Setenv("GOARCH", goarch)
   225		os.Setenv("GOARM", goarm)
   226		os.Setenv("GOHOSTARCH", gohostarch)
   227		os.Setenv("GOHOSTOS", gohostos)
   228		os.Setenv("GOOS", goos)
   229		os.Setenv("GOMIPS", gomips)
   230		os.Setenv("GOMIPS64", gomips64)
   231		os.Setenv("GOPPC64", goppc64)
   232		os.Setenv("GOROOT", goroot)
   233		os.Setenv("GOROOT_FINAL", goroot_final)
   234	
   235		// Use a build cache separate from the default user one.
   236		// Also one that will be wiped out during startup, so that
   237		// make.bash really does start from a clean slate.
   238		os.Setenv("GOCACHE", pathf("%s/pkg/obj/go-build", goroot))
   239	
   240		// Make the environment more predictable.
   241		os.Setenv("LANG", "C")
   242		os.Setenv("LANGUAGE", "en_US.UTF8")
   243	
   244		workdir = xworkdir()
   245		xatexit(rmworkdir)
   246	
   247		tooldir = pathf("%s/pkg/tool/%s_%s", goroot, gohostos, gohostarch)
   248	}
   249	
   250	// compilerEnv returns a map from "goos/goarch" to the
   251	// compiler setting to use for that platform.
   252	// The entry for key "" covers any goos/goarch not explicitly set in the map.
   253	// For example, compilerEnv("CC", "gcc") returns the C compiler settings
   254	// read from $CC, defaulting to gcc.
   255	//
   256	// The result is a map because additional environment variables
   257	// can be set to change the compiler based on goos/goarch settings.
   258	// The following applies to all envNames but CC is assumed to simplify
   259	// the presentation.
   260	//
   261	// If no environment variables are set, we use def for all goos/goarch.
   262	// $CC, if set, applies to all goos/goarch but is overridden by the following.
   263	// $CC_FOR_TARGET, if set, applies to all goos/goarch except gohostos/gohostarch,
   264	// but is overridden by the following.
   265	// If gohostos=goos and gohostarch=goarch, then $CC_FOR_TARGET applies even for gohostos/gohostarch.
   266	// $CC_FOR_goos_goarch, if set, applies only to goos/goarch.
   267	func compilerEnv(envName, def string) map[string]string {
   268		m := map[string]string{"": def}
   269	
   270		if env := os.Getenv(envName); env != "" {
   271			m[""] = env
   272		}
   273		if env := os.Getenv(envName + "_FOR_TARGET"); env != "" {
   274			if gohostos != goos || gohostarch != goarch {
   275				m[gohostos+"/"+gohostarch] = m[""]
   276			}
   277			m[""] = env
   278		}
   279	
   280		for _, goos := range okgoos {
   281			for _, goarch := range okgoarch {
   282				if env := os.Getenv(envName + "_FOR_" + goos + "_" + goarch); env != "" {
   283					m[goos+"/"+goarch] = env
   284				}
   285			}
   286		}
   287	
   288		return m
   289	}
   290	
   291	// compilerEnvLookup returns the compiler settings for goos/goarch in map m.
   292	func compilerEnvLookup(m map[string]string, goos, goarch string) string {
   293		if cc := m[goos+"/"+goarch]; cc != "" {
   294			return cc
   295		}
   296		return m[""]
   297	}
   298	
   299	// rmworkdir deletes the work directory.
   300	func rmworkdir() {
   301		if vflag > 1 {
   302			errprintf("rm -rf %s\n", workdir)
   303		}
   304		xremoveall(workdir)
   305	}
   306	
   307	// Remove trailing spaces.
   308	func chomp(s string) string {
   309		return strings.TrimRight(s, " \t\r\n")
   310	}
   311	
   312	func branchtag(branch string) (tag string, precise bool) {
   313		log := run(goroot, CheckExit, "git", "log", "--decorate=full", "--format=format:%d", "master.."+branch)
   314		tag = branch
   315		for row, line := range strings.Split(log, "\n") {
   316			// Each line is either blank, or looks like
   317			//	  (tag: refs/tags/go1.4rc2, refs/remotes/origin/release-branch.go1.4, refs/heads/release-branch.go1.4)
   318			// We need to find an element starting with refs/tags/.
   319			const s = " refs/tags/"
   320			i := strings.Index(line, s)
   321			if i < 0 {
   322				continue
   323			}
   324			// Trim off known prefix.
   325			line = line[i+len(s):]
   326			// The tag name ends at a comma or paren.
   327			j := strings.IndexAny(line, ",)")
   328			if j < 0 {
   329				continue // malformed line; ignore it
   330			}
   331			tag = line[:j]
   332			if row == 0 {
   333				precise = true // tag denotes HEAD
   334			}
   335			break
   336		}
   337		return
   338	}
   339	
   340	// findgoversion determines the Go version to use in the version string.
   341	func findgoversion() string {
   342		// The $GOROOT/VERSION file takes priority, for distributions
   343		// without the source repo.
   344		path := pathf("%s/VERSION", goroot)
   345		if isfile(path) {
   346			b := chomp(readfile(path))
   347			// Commands such as "dist version > VERSION" will cause
   348			// the shell to create an empty VERSION file and set dist's
   349			// stdout to its fd. dist in turn looks at VERSION and uses
   350			// its content if available, which is empty at this point.
   351			// Only use the VERSION file if it is non-empty.
   352			if b != "" {
   353				// Some builders cross-compile the toolchain on linux-amd64
   354				// and then copy the toolchain to the target builder (say, linux-arm)
   355				// for use there. But on non-release (devel) branches, the compiler
   356				// used on linux-amd64 will be an amd64 binary, and the compiler
   357				// shipped to linux-arm will be an arm binary, so they will have different
   358				// content IDs (they are binaries for different architectures) and so the
   359				// packages compiled by the running-on-amd64 compiler will appear
   360				// stale relative to the running-on-arm compiler. Avoid this by setting
   361				// the version string to something that doesn't begin with devel.
   362				// Then the version string will be used in place of the content ID,
   363				// and the packages will look up-to-date.
   364				// TODO(rsc): Really the builders could be writing out a better VERSION file instead,
   365				// but it is easier to change cmd/dist than to try to make changes to
   366				// the builder while Brad is away.
   367				if strings.HasPrefix(b, "devel") {
   368					if hostType := os.Getenv("META_BUILDLET_HOST_TYPE"); strings.Contains(hostType, "-cross") {
   369						fmt.Fprintf(os.Stderr, "warning: changing VERSION from %q to %q\n", b, "builder "+hostType)
   370						b = "builder " + hostType
   371					}
   372				}
   373				return b
   374			}
   375		}
   376	
   377		// The $GOROOT/VERSION.cache file is a cache to avoid invoking
   378		// git every time we run this command. Unlike VERSION, it gets
   379		// deleted by the clean command.
   380		path = pathf("%s/VERSION.cache", goroot)
   381		if isfile(path) {
   382			return chomp(readfile(path))
   383		}
   384	
   385		// Show a nicer error message if this isn't a Git repo.
   386		if !isGitRepo() {
   387			fatalf("FAILED: not a Git repo; must put a VERSION file in $GOROOT")
   388		}
   389	
   390		// Otherwise, use Git.
   391		// What is the current branch?
   392		branch := chomp(run(goroot, CheckExit, "git", "rev-parse", "--abbrev-ref", "HEAD"))
   393	
   394		// What are the tags along the current branch?
   395		tag := "devel"
   396		precise := false
   397	
   398		// If we're on a release branch, use the closest matching tag
   399		// that is on the release branch (and not on the master branch).
   400		if strings.HasPrefix(branch, "release-branch.") {
   401			tag, precise = branchtag(branch)
   402		}
   403	
   404		if !precise {
   405			// Tag does not point at HEAD; add hash and date to version.
   406			tag += chomp(run(goroot, CheckExit, "git", "log", "-n", "1", "--format=format: +%h %cd", "HEAD"))
   407		}
   408	
   409		// Cache version.
   410		writefile(tag, path, 0)
   411	
   412		return tag
   413	}
   414	
   415	// isGitRepo reports whether the working directory is inside a Git repository.
   416	func isGitRepo() bool {
   417		// NB: simply checking the exit code of `git rev-parse --git-dir` would
   418		// suffice here, but that requires deviating from the infrastructure
   419		// provided by `run`.
   420		gitDir := chomp(run(goroot, 0, "git", "rev-parse", "--git-dir"))
   421		if !filepath.IsAbs(gitDir) {
   422			gitDir = filepath.Join(goroot, gitDir)
   423		}
   424		return isdir(gitDir)
   425	}
   426	
   427	/*
   428	 * Initial tree setup.
   429	 */
   430	
   431	// The old tools that no longer live in $GOBIN or $GOROOT/bin.
   432	var oldtool = []string{
   433		"5a", "5c", "5g", "5l",
   434		"6a", "6c", "6g", "6l",
   435		"8a", "8c", "8g", "8l",
   436		"9a", "9c", "9g", "9l",
   437		"6cov",
   438		"6nm",
   439		"6prof",
   440		"cgo",
   441		"ebnflint",
   442		"goapi",
   443		"gofix",
   444		"goinstall",
   445		"gomake",
   446		"gopack",
   447		"gopprof",
   448		"gotest",
   449		"gotype",
   450		"govet",
   451		"goyacc",
   452		"quietgcc",
   453	}
   454	
   455	// Unreleased directories (relative to $GOROOT) that should
   456	// not be in release branches.
   457	var unreleased = []string{
   458		"src/cmd/newlink",
   459		"src/cmd/objwriter",
   460		"src/debug/goobj",
   461		"src/old",
   462	}
   463	
   464	// setup sets up the tree for the initial build.
   465	func setup() {
   466		// Create bin directory.
   467		if p := pathf("%s/bin", goroot); !isdir(p) {
   468			xmkdir(p)
   469		}
   470	
   471		// Create package directory.
   472		if p := pathf("%s/pkg", goroot); !isdir(p) {
   473			xmkdir(p)
   474		}
   475	
   476		p := pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch)
   477		if rebuildall {
   478			xremoveall(p)
   479		}
   480		xmkdirall(p)
   481	
   482		if goos != gohostos || goarch != gohostarch {
   483			p := pathf("%s/pkg/%s_%s", goroot, goos, goarch)
   484			if rebuildall {
   485				xremoveall(p)
   486			}
   487			xmkdirall(p)
   488		}
   489	
   490		// Create object directory.
   491		// We used to use it for C objects.
   492		// Now we use it for the build cache, to separate dist's cache
   493		// from any other cache the user might have.
   494		p = pathf("%s/pkg/obj/go-build", goroot)
   495		if rebuildall {
   496			xremoveall(p)
   497		}
   498		xmkdirall(p)
   499		xatexit(func() { xremoveall(p) })
   500	
   501		// Create tool directory.
   502		// We keep it in pkg/, just like the object directory above.
   503		if rebuildall {
   504			xremoveall(tooldir)
   505		}
   506		xmkdirall(tooldir)
   507	
   508		// Remove tool binaries from before the tool/gohostos_gohostarch
   509		xremoveall(pathf("%s/bin/tool", goroot))
   510	
   511		// Remove old pre-tool binaries.
   512		for _, old := range oldtool {
   513			xremove(pathf("%s/bin/%s", goroot, old))
   514		}
   515	
   516		// If $GOBIN is set and has a Go compiler, it must be cleaned.
   517		for _, char := range "56789" {
   518			if isfile(pathf("%s/%c%s", gobin, char, "g")) {
   519				for _, old := range oldtool {
   520					xremove(pathf("%s/%s", gobin, old))
   521				}
   522				break
   523			}
   524		}
   525	
   526		// For release, make sure excluded things are excluded.
   527		goversion := findgoversion()
   528		if strings.HasPrefix(goversion, "release.") || (strings.HasPrefix(goversion, "go") && !strings.Contains(goversion, "beta")) {
   529			for _, dir := range unreleased {
   530				if p := pathf("%s/%s", goroot, dir); isdir(p) {
   531					fatalf("%s should not exist in release build", p)
   532				}
   533			}
   534		}
   535	}
   536	
   537	/*
   538	 * Tool building
   539	 */
   540	
   541	// deptab lists changes to the default dependencies for a given prefix.
   542	// deps ending in /* read the whole directory; deps beginning with -
   543	// exclude files with that prefix.
   544	// Note that this table applies only to the build of cmd/go,
   545	// after the main compiler bootstrap.
   546	var deptab = []struct {
   547		prefix string   // prefix of target
   548		dep    []string // dependency tweaks for targets with that prefix
   549	}{
   550		{"cmd/go/internal/cfg", []string{
   551			"zdefaultcc.go",
   552			"zosarch.go",
   553		}},
   554		{"runtime/internal/sys", []string{
   555			"zversion.go",
   556		}},
   557		{"go/build", []string{
   558			"zcgo.go",
   559		}},
   560	}
   561	
   562	// depsuffix records the allowed suffixes for source files.
   563	var depsuffix = []string{
   564		".s",
   565		".go",
   566	}
   567	
   568	// gentab records how to generate some trivial files.
   569	var gentab = []struct {
   570		nameprefix string
   571		gen        func(string, string)
   572	}{
   573		{"zdefaultcc.go", mkzdefaultcc},
   574		{"zosarch.go", mkzosarch},
   575		{"zversion.go", mkzversion},
   576		{"zcgo.go", mkzcgo},
   577	
   578		// not generated anymore, but delete the file if we see it
   579		{"enam.c", nil},
   580		{"anames5.c", nil},
   581		{"anames6.c", nil},
   582		{"anames8.c", nil},
   583		{"anames9.c", nil},
   584	}
   585	
   586	// installed maps from a dir name (as given to install) to a chan
   587	// closed when the dir's package is installed.
   588	var installed = make(map[string]chan struct{})
   589	var installedMu sync.Mutex
   590	
   591	func install(dir string) {
   592		<-startInstall(dir)
   593	}
   594	
   595	func startInstall(dir string) chan struct{} {
   596		installedMu.Lock()
   597		ch := installed[dir]
   598		if ch == nil {
   599			ch = make(chan struct{})
   600			installed[dir] = ch
   601			go runInstall(dir, ch)
   602		}
   603		installedMu.Unlock()
   604		return ch
   605	}
   606	
   607	// runInstall installs the library, package, or binary associated with dir,
   608	// which is relative to $GOROOT/src.
   609	func runInstall(dir string, ch chan struct{}) {
   610		if dir == "net" || dir == "os/user" || dir == "crypto/x509" {
   611			fatalf("go_bootstrap cannot depend on cgo package %s", dir)
   612		}
   613	
   614		defer close(ch)
   615	
   616		if dir == "unsafe" {
   617			return
   618		}
   619	
   620		if vflag > 0 {
   621			if goos != gohostos || goarch != gohostarch {
   622				errprintf("%s (%s/%s)\n", dir, goos, goarch)
   623			} else {
   624				errprintf("%s\n", dir)
   625			}
   626		}
   627	
   628		workdir := pathf("%s/%s", workdir, dir)
   629		xmkdirall(workdir)
   630	
   631		var clean []string
   632		defer func() {
   633			for _, name := range clean {
   634				xremove(name)
   635			}
   636		}()
   637	
   638		// path = full path to dir.
   639		path := pathf("%s/src/%s", goroot, dir)
   640		name := filepath.Base(dir)
   641	
   642		ispkg := !strings.HasPrefix(dir, "cmd/") || strings.Contains(dir, "/internal/")
   643	
   644		// Start final link command line.
   645		// Note: code below knows that link.p[targ] is the target.
   646		var (
   647			link      []string
   648			targ      int
   649			ispackcmd bool
   650		)
   651		if ispkg {
   652			// Go library (package).
   653			ispackcmd = true
   654			link = []string{"pack", pathf("%s/pkg/%s_%s/%s.a", goroot, goos, goarch, dir)}
   655			targ = len(link) - 1
   656			xmkdirall(filepath.Dir(link[targ]))
   657		} else {
   658			// Go command.
   659			elem := name
   660			if elem == "go" {
   661				elem = "go_bootstrap"
   662			}
   663			link = []string{pathf("%s/link", tooldir)}
   664			if goos == "android" {
   665				link = append(link, "-buildmode=pie")
   666			}
   667			if goldflags != "" {
   668				link = append(link, goldflags)
   669			}
   670			link = append(link, "-extld="+compilerEnvLookup(defaultcc, goos, goarch))
   671			link = append(link, "-o", pathf("%s/%s%s", tooldir, elem, exe))
   672			targ = len(link) - 1
   673		}
   674		ttarg := mtime(link[targ])
   675	
   676		// Gather files that are sources for this target.
   677		// Everything in that directory, and any target-specific
   678		// additions.
   679		files := xreaddir(path)
   680	
   681		// Remove files beginning with . or _,
   682		// which are likely to be editor temporary files.
   683		// This is the same heuristic build.ScanDir uses.
   684		// There do exist real C files beginning with _,
   685		// so limit that check to just Go files.
   686		files = filter(files, func(p string) bool {
   687			return !strings.HasPrefix(p, ".") && (!strings.HasPrefix(p, "_") || !strings.HasSuffix(p, ".go"))
   688		})
   689	
   690		for _, dt := range deptab {
   691			if dir == dt.prefix || strings.HasSuffix(dt.prefix, "/") && strings.HasPrefix(dir, dt.prefix) {
   692				for _, p := range dt.dep {
   693					p = os.ExpandEnv(p)
   694					files = append(files, p)
   695				}
   696			}
   697		}
   698		files = uniq(files)
   699	
   700		// Convert to absolute paths.
   701		for i, p := range files {
   702			if !filepath.IsAbs(p) {
   703				files[i] = pathf("%s/%s", path, p)
   704			}
   705		}
   706	
   707		// Is the target up-to-date?
   708		var gofiles, sfiles, missing []string
   709		stale := rebuildall
   710		files = filter(files, func(p string) bool {
   711			for _, suf := range depsuffix {
   712				if strings.HasSuffix(p, suf) {
   713					goto ok
   714				}
   715			}
   716			return false
   717		ok:
   718			t := mtime(p)
   719			if !t.IsZero() && !strings.HasSuffix(p, ".a") && !shouldbuild(p, dir) {
   720				return false
   721			}
   722			if strings.HasSuffix(p, ".go") {
   723				gofiles = append(gofiles, p)
   724			} else if strings.HasSuffix(p, ".s") {
   725				sfiles = append(sfiles, p)
   726			}
   727			if t.After(ttarg) {
   728				stale = true
   729			}
   730			if t.IsZero() {
   731				missing = append(missing, p)
   732			}
   733			return true
   734		})
   735	
   736		// If there are no files to compile, we're done.
   737		if len(files) == 0 {
   738			return
   739		}
   740	
   741		if !stale {
   742			return
   743		}
   744	
   745		// For package runtime, copy some files into the work space.
   746		if dir == "runtime" {
   747			xmkdirall(pathf("%s/pkg/include", goroot))
   748			// For use by assembly and C files.
   749			copyfile(pathf("%s/pkg/include/textflag.h", goroot),
   750				pathf("%s/src/runtime/textflag.h", goroot), 0)
   751			copyfile(pathf("%s/pkg/include/funcdata.h", goroot),
   752				pathf("%s/src/runtime/funcdata.h", goroot), 0)
   753			copyfile(pathf("%s/pkg/include/asm_ppc64x.h", goroot),
   754				pathf("%s/src/runtime/asm_ppc64x.h", goroot), 0)
   755		}
   756	
   757		// Generate any missing files; regenerate existing ones.
   758		for _, p := range files {
   759			elem := filepath.Base(p)
   760			for _, gt := range gentab {
   761				if gt.gen == nil {
   762					continue
   763				}
   764				if strings.HasPrefix(elem, gt.nameprefix) {
   765					if vflag > 1 {
   766						errprintf("generate %s\n", p)
   767					}
   768					gt.gen(path, p)
   769					// Do not add generated file to clean list.
   770					// In runtime, we want to be able to
   771					// build the package with the go tool,
   772					// and it assumes these generated files already
   773					// exist (it does not know how to build them).
   774					// The 'clean' command can remove
   775					// the generated files.
   776					goto built
   777				}
   778			}
   779			// Did not rebuild p.
   780			if find(p, missing) >= 0 {
   781				fatalf("missing file %s", p)
   782			}
   783		built:
   784		}
   785	
   786		// Make sure dependencies are installed.
   787		var deps []string
   788		for _, p := range gofiles {
   789			deps = append(deps, readimports(p)...)
   790		}
   791		for _, dir1 := range deps {
   792			startInstall(dir1)
   793		}
   794		for _, dir1 := range deps {
   795			install(dir1)
   796		}
   797	
   798		if goos != gohostos || goarch != gohostarch {
   799			// We've generated the right files; the go command can do the build.
   800			if vflag > 1 {
   801				errprintf("skip build for cross-compile %s\n", dir)
   802			}
   803			return
   804		}
   805	
   806		asmArgs := []string{
   807			pathf("%s/asm", tooldir),
   808			"-I", workdir,
   809			"-I", pathf("%s/pkg/include", goroot),
   810			"-D", "GOOS_" + goos,
   811			"-D", "GOARCH_" + goarch,
   812			"-D", "GOOS_GOARCH_" + goos + "_" + goarch,
   813		}
   814		if goarch == "mips" || goarch == "mipsle" {
   815			// Define GOMIPS_value from gomips.
   816			asmArgs = append(asmArgs, "-D", "GOMIPS_"+gomips)
   817		}
   818		if goarch == "mips64" || goarch == "mipsle64" {
   819			// Define GOMIPS64_value from gomips64.
   820			asmArgs = append(asmArgs, "-D", "GOMIPS64_"+gomips64)
   821		}
   822		goasmh := pathf("%s/go_asm.h", workdir)
   823	
   824		// Collect symabis from assembly code.
   825		var symabis string
   826		if len(sfiles) > 0 {
   827			symabis = pathf("%s/symabis", workdir)
   828			var wg sync.WaitGroup
   829			asmabis := append(asmArgs[:len(asmArgs):len(asmArgs)], "-gensymabis", "-o", symabis)
   830			asmabis = append(asmabis, sfiles...)
   831			if err := ioutil.WriteFile(goasmh, nil, 0666); err != nil {
   832				fatalf("cannot write empty go_asm.h: %s", err)
   833			}
   834			bgrun(&wg, path, asmabis...)
   835			bgwait(&wg)
   836		}
   837	
   838		var archive string
   839		// The next loop will compile individual non-Go files.
   840		// Hand the Go files to the compiler en masse.
   841		// For packages containing assembly, this writes go_asm.h, which
   842		// the assembly files will need.
   843		pkg := dir
   844		if strings.HasPrefix(dir, "cmd/") && strings.Count(dir, "/") == 1 {
   845			pkg = "main"
   846		}
   847		b := pathf("%s/_go_.a", workdir)
   848		clean = append(clean, b)
   849		if !ispackcmd {
   850			link = append(link, b)
   851		} else {
   852			archive = b
   853		}
   854	
   855		// Compile Go code.
   856		compile := []string{pathf("%s/compile", tooldir), "-std", "-pack", "-o", b, "-p", pkg}
   857		if gogcflags != "" {
   858			compile = append(compile, strings.Fields(gogcflags)...)
   859		}
   860		if dir == "runtime" {
   861			compile = append(compile, "-+")
   862		}
   863		if len(sfiles) > 0 {
   864			compile = append(compile, "-asmhdr", goasmh)
   865		}
   866		if symabis != "" {
   867			compile = append(compile, "-symabis", symabis)
   868		}
   869		if goos == "android" {
   870			compile = append(compile, "-shared")
   871		}
   872	
   873		compile = append(compile, gofiles...)
   874		var wg sync.WaitGroup
   875		// We use bgrun and immediately wait for it instead of calling run() synchronously.
   876		// This executes all jobs through the bgwork channel and allows the process
   877		// to exit cleanly in case an error occurs.
   878		bgrun(&wg, path, compile...)
   879		bgwait(&wg)
   880	
   881		// Compile the files.
   882		for _, p := range sfiles {
   883			// Assembly file for a Go package.
   884			compile := asmArgs[:len(asmArgs):len(asmArgs)]
   885	
   886			doclean := true
   887			b := pathf("%s/%s", workdir, filepath.Base(p))
   888	
   889			// Change the last character of the output file (which was c or s).
   890			b = b[:len(b)-1] + "o"
   891			compile = append(compile, "-o", b, p)
   892			bgrun(&wg, path, compile...)
   893	
   894			link = append(link, b)
   895			if doclean {
   896				clean = append(clean, b)
   897			}
   898		}
   899		bgwait(&wg)
   900	
   901		if ispackcmd {
   902			xremove(link[targ])
   903			dopack(link[targ], archive, link[targ+1:])
   904			return
   905		}
   906	
   907		// Remove target before writing it.
   908		xremove(link[targ])
   909		bgrun(&wg, "", link...)
   910		bgwait(&wg)
   911	}
   912	
   913	// matchfield reports whether the field (x,y,z) matches this build.
   914	// all the elements in the field must be satisfied.
   915	func matchfield(f string) bool {
   916		for _, tag := range strings.Split(f, ",") {
   917			if !matchtag(tag) {
   918				return false
   919			}
   920		}
   921		return true
   922	}
   923	
   924	// matchtag reports whether the tag (x or !x) matches this build.
   925	func matchtag(tag string) bool {
   926		if tag == "" {
   927			return false
   928		}
   929		if tag[0] == '!' {
   930			if len(tag) == 1 || tag[1] == '!' {
   931				return false
   932			}
   933			return !matchtag(tag[1:])
   934		}
   935		return tag == "gc" || tag == goos || tag == goarch || tag == "cmd_go_bootstrap" || tag == "go1.1" || (goos == "android" && tag == "linux") || (goos == "illumos" && tag == "solaris")
   936	}
   937	
   938	// shouldbuild reports whether we should build this file.
   939	// It applies the same rules that are used with context tags
   940	// in package go/build, except it's less picky about the order
   941	// of GOOS and GOARCH.
   942	// We also allow the special tag cmd_go_bootstrap.
   943	// See ../go/bootstrap.go and package go/build.
   944	func shouldbuild(file, dir string) bool {
   945		// Check file name for GOOS or GOARCH.
   946		name := filepath.Base(file)
   947		excluded := func(list []string, ok string) bool {
   948			for _, x := range list {
   949				if x == ok || (ok == "android" && x == "linux") || (ok == "illumos" && x == "solaris") {
   950					continue
   951				}
   952				i := strings.Index(name, x)
   953				if i <= 0 || name[i-1] != '_' {
   954					continue
   955				}
   956				i += len(x)
   957				if i == len(name) || name[i] == '.' || name[i] == '_' {
   958					return true
   959				}
   960			}
   961			return false
   962		}
   963		if excluded(okgoos, goos) || excluded(okgoarch, goarch) {
   964			return false
   965		}
   966	
   967		// Omit test files.
   968		if strings.Contains(name, "_test") {
   969			return false
   970		}
   971	
   972		// Check file contents for // +build lines.
   973		for _, p := range strings.Split(readfile(file), "\n") {
   974			p = strings.TrimSpace(p)
   975			if p == "" {
   976				continue
   977			}
   978			code := p
   979			i := strings.Index(code, "//")
   980			if i > 0 {
   981				code = strings.TrimSpace(code[:i])
   982			}
   983			if code == "package documentation" {
   984				return false
   985			}
   986			if code == "package main" && dir != "cmd/go" && dir != "cmd/cgo" {
   987				return false
   988			}
   989			if !strings.HasPrefix(p, "//") {
   990				break
   991			}
   992			if !strings.Contains(p, "+build") {
   993				continue
   994			}
   995			fields := strings.Fields(p[2:])
   996			if len(fields) < 1 || fields[0] != "+build" {
   997				continue
   998			}
   999			for _, p := range fields[1:] {
  1000				if matchfield(p) {
  1001					goto fieldmatch
  1002				}
  1003			}
  1004			return false
  1005		fieldmatch:
  1006		}
  1007	
  1008		return true
  1009	}
  1010	
  1011	// copy copies the file src to dst, via memory (so only good for small files).
  1012	func copyfile(dst, src string, flag int) {
  1013		if vflag > 1 {
  1014			errprintf("cp %s %s\n", src, dst)
  1015		}
  1016		writefile(readfile(src), dst, flag)
  1017	}
  1018	
  1019	// dopack copies the package src to dst,
  1020	// appending the files listed in extra.
  1021	// The archive format is the traditional Unix ar format.
  1022	func dopack(dst, src string, extra []string) {
  1023		bdst := bytes.NewBufferString(readfile(src))
  1024		for _, file := range extra {
  1025			b := readfile(file)
  1026			// find last path element for archive member name
  1027			i := strings.LastIndex(file, "/") + 1
  1028			j := strings.LastIndex(file, `\`) + 1
  1029			if i < j {
  1030				i = j
  1031			}
  1032			fmt.Fprintf(bdst, "%-16.16s%-12d%-6d%-6d%-8o%-10d`\n", file[i:], 0, 0, 0, 0644, len(b))
  1033			bdst.WriteString(b)
  1034			if len(b)&1 != 0 {
  1035				bdst.WriteByte(0)
  1036			}
  1037		}
  1038		writefile(bdst.String(), dst, 0)
  1039	}
  1040	
  1041	var runtimegen = []string{
  1042		"zaexperiment.h",
  1043		"zversion.go",
  1044	}
  1045	
  1046	// cleanlist is a list of packages with generated files and commands.
  1047	var cleanlist = []string{
  1048		"runtime/internal/sys",
  1049		"cmd/cgo",
  1050		"cmd/go/internal/cfg",
  1051		"go/build",
  1052	}
  1053	
  1054	func clean() {
  1055		for _, name := range cleanlist {
  1056			path := pathf("%s/src/%s", goroot, name)
  1057			// Remove generated files.
  1058			for _, elem := range xreaddir(path) {
  1059				for _, gt := range gentab {
  1060					if strings.HasPrefix(elem, gt.nameprefix) {
  1061						xremove(pathf("%s/%s", path, elem))
  1062					}
  1063				}
  1064			}
  1065			// Remove generated binary named for directory.
  1066			if strings.HasPrefix(name, "cmd/") {
  1067				xremove(pathf("%s/%s", path, name[4:]))
  1068			}
  1069		}
  1070	
  1071		// remove runtimegen files.
  1072		path := pathf("%s/src/runtime", goroot)
  1073		for _, elem := range runtimegen {
  1074			xremove(pathf("%s/%s", path, elem))
  1075		}
  1076	
  1077		if rebuildall {
  1078			// Remove object tree.
  1079			xremoveall(pathf("%s/pkg/obj/%s_%s", goroot, gohostos, gohostarch))
  1080	
  1081			// Remove installed packages and tools.
  1082			xremoveall(pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch))
  1083			xremoveall(pathf("%s/pkg/%s_%s", goroot, goos, goarch))
  1084			xremoveall(pathf("%s/pkg/%s_%s_race", goroot, gohostos, gohostarch))
  1085			xremoveall(pathf("%s/pkg/%s_%s_race", goroot, goos, goarch))
  1086			xremoveall(tooldir)
  1087	
  1088			// Remove cached version info.
  1089			xremove(pathf("%s/VERSION.cache", goroot))
  1090		}
  1091	}
  1092	
  1093	/*
  1094	 * command implementations
  1095	 */
  1096	
  1097	// The env command prints the default environment.
  1098	func cmdenv() {
  1099		path := flag.Bool("p", false, "emit updated PATH")
  1100		plan9 := flag.Bool("9", false, "emit plan 9 syntax")
  1101		windows := flag.Bool("w", false, "emit windows syntax")
  1102		xflagparse(0)
  1103	
  1104		format := "%s=\"%s\"\n"
  1105		switch {
  1106		case *plan9:
  1107			format = "%s='%s'\n"
  1108		case *windows:
  1109			format = "set %s=%s\r\n"
  1110		}
  1111	
  1112		xprintf(format, "GOARCH", goarch)
  1113		xprintf(format, "GOBIN", gobin)
  1114		xprintf(format, "GOCACHE", os.Getenv("GOCACHE"))
  1115		xprintf(format, "GODEBUG", os.Getenv("GODEBUG"))
  1116		xprintf(format, "GOHOSTARCH", gohostarch)
  1117		xprintf(format, "GOHOSTOS", gohostos)
  1118		xprintf(format, "GOOS", goos)
  1119		xprintf(format, "GOPROXY", os.Getenv("GOPROXY"))
  1120		xprintf(format, "GOROOT", goroot)
  1121		xprintf(format, "GOTMPDIR", os.Getenv("GOTMPDIR"))
  1122		xprintf(format, "GOTOOLDIR", tooldir)
  1123		if goarch == "arm" {
  1124			xprintf(format, "GOARM", goarm)
  1125		}
  1126		if goarch == "386" {
  1127			xprintf(format, "GO386", go386)
  1128		}
  1129		if goarch == "mips" || goarch == "mipsle" {
  1130			xprintf(format, "GOMIPS", gomips)
  1131		}
  1132		if goarch == "mips64" || goarch == "mips64le" {
  1133			xprintf(format, "GOMIPS64", gomips64)
  1134		}
  1135		if goarch == "ppc64" || goarch == "ppc64le" {
  1136			xprintf(format, "GOPPC64", goppc64)
  1137		}
  1138	
  1139		if *path {
  1140			sep := ":"
  1141			if gohostos == "windows" {
  1142				sep = ";"
  1143			}
  1144			xprintf(format, "PATH", fmt.Sprintf("%s%s%s", gobin, sep, os.Getenv("PATH")))
  1145		}
  1146	}
  1147	
  1148	var (
  1149		timeLogEnabled = os.Getenv("GOBUILDTIMELOGFILE") != ""
  1150		timeLogMu      sync.Mutex
  1151		timeLogFile    *os.File
  1152		timeLogStart   time.Time
  1153	)
  1154	
  1155	func timelog(op, name string) {
  1156		if !timeLogEnabled {
  1157			return
  1158		}
  1159		timeLogMu.Lock()
  1160		defer timeLogMu.Unlock()
  1161		if timeLogFile == nil {
  1162			f, err := os.OpenFile(os.Getenv("GOBUILDTIMELOGFILE"), os.O_RDWR|os.O_APPEND, 0666)
  1163			if err != nil {
  1164				log.Fatal(err)
  1165			}
  1166			buf := make([]byte, 100)
  1167			n, _ := f.Read(buf)
  1168			s := string(buf[:n])
  1169			if i := strings.Index(s, "\n"); i >= 0 {
  1170				s = s[:i]
  1171			}
  1172			i := strings.Index(s, " start")
  1173			if i < 0 {
  1174				log.Fatalf("time log %s does not begin with start line", os.Getenv("GOBULDTIMELOGFILE"))
  1175			}
  1176			t, err := time.Parse(time.UnixDate, s[:i])
  1177			if err != nil {
  1178				log.Fatalf("cannot parse time log line %q: %v", s, err)
  1179			}
  1180			timeLogStart = t
  1181			timeLogFile = f
  1182		}
  1183		t := time.Now()
  1184		fmt.Fprintf(timeLogFile, "%s %+.1fs %s %s\n", t.Format(time.UnixDate), t.Sub(timeLogStart).Seconds(), op, name)
  1185	}
  1186	
  1187	var toolchain = []string{"cmd/asm", "cmd/cgo", "cmd/compile", "cmd/link"}
  1188	
  1189	// The bootstrap command runs a build from scratch,
  1190	// stopping at having installed the go_bootstrap command.
  1191	//
  1192	// WARNING: This command runs after cmd/dist is built with Go 1.4.
  1193	// It rebuilds and installs cmd/dist with the new toolchain, so other
  1194	// commands (like "go tool dist test" in run.bash) can rely on bug fixes
  1195	// made since Go 1.4, but this function cannot. In particular, the uses
  1196	// of os/exec in this function cannot assume that
  1197	//	cmd.Env = append(os.Environ(), "X=Y")
  1198	// sets $X to Y in the command's environment. That guarantee was
  1199	// added after Go 1.4, and in fact in Go 1.4 it was typically the opposite:
  1200	// if $X was already present in os.Environ(), most systems preferred
  1201	// that setting, not the new one.
  1202	func cmdbootstrap() {
  1203		timelog("start", "dist bootstrap")
  1204		defer timelog("end", "dist bootstrap")
  1205	
  1206		var noBanner bool
  1207		var debug bool
  1208		flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all")
  1209		flag.BoolVar(&debug, "d", debug, "enable debugging of bootstrap process")
  1210		flag.BoolVar(&noBanner, "no-banner", noBanner, "do not print banner")
  1211	
  1212		xflagparse(0)
  1213	
  1214		// Set GOPATH to an internal directory. We shouldn't actually
  1215		// need to store files here, since the toolchain won't
  1216		// depend on modules outside of vendor directories, but if
  1217		// GOPATH points somewhere else (e.g., to GOROOT), the
  1218		// go tool may complain.
  1219		os.Setenv("GOPATH", pathf("%s/pkg/obj/gopath", goroot))
  1220	
  1221		if debug {
  1222			// cmd/buildid is used in debug mode.
  1223			toolchain = append(toolchain, "cmd/buildid")
  1224		}
  1225	
  1226		if isdir(pathf("%s/src/pkg", goroot)) {
  1227			fatalf("\n\n"+
  1228				"The Go package sources have moved to $GOROOT/src.\n"+
  1229				"*** %s still exists. ***\n"+
  1230				"It probably contains stale files that may confuse the build.\n"+
  1231				"Please (check what's there and) remove it and try again.\n"+
  1232				"See https://golang.org/s/go14nopkg\n",
  1233				pathf("%s/src/pkg", goroot))
  1234		}
  1235	
  1236		if rebuildall {
  1237			clean()
  1238		}
  1239	
  1240		setup()
  1241	
  1242		timelog("build", "toolchain1")
  1243		checkCC()
  1244		bootstrapBuildTools()
  1245	
  1246		// Remember old content of $GOROOT/bin for comparison below.
  1247		oldBinFiles, _ := filepath.Glob(pathf("%s/bin/*", goroot))
  1248	
  1249		// For the main bootstrap, building for host os/arch.
  1250		oldgoos = goos
  1251		oldgoarch = goarch
  1252		goos = gohostos
  1253		goarch = gohostarch
  1254		os.Setenv("GOHOSTARCH", gohostarch)
  1255		os.Setenv("GOHOSTOS", gohostos)
  1256		os.Setenv("GOARCH", goarch)
  1257		os.Setenv("GOOS", goos)
  1258	
  1259		timelog("build", "go_bootstrap")
  1260		xprintf("Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.\n")
  1261		install("runtime") // dependency not visible in sources; also sets up textflag.h
  1262		install("cmd/go")
  1263		if vflag > 0 {
  1264			xprintf("\n")
  1265		}
  1266	
  1267		gogcflags = os.Getenv("GO_GCFLAGS") // we were using $BOOT_GO_GCFLAGS until now
  1268		goldflags = os.Getenv("GO_LDFLAGS") // we were using $BOOT_GO_LDFLAGS until now
  1269		goBootstrap := pathf("%s/go_bootstrap", tooldir)
  1270		cmdGo := pathf("%s/go", gobin)
  1271		if debug {
  1272			run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
  1273			copyfile(pathf("%s/compile1", tooldir), pathf("%s/compile", tooldir), writeExec)
  1274		}
  1275	
  1276		// To recap, so far we have built the new toolchain
  1277		// (cmd/asm, cmd/cgo, cmd/compile, cmd/link)
  1278		// using Go 1.4's toolchain and go command.
  1279		// Then we built the new go command (as go_bootstrap)
  1280		// using the new toolchain and our own build logic (above).
  1281		//
  1282		//	toolchain1 = mk(new toolchain, go1.4 toolchain, go1.4 cmd/go)
  1283		//	go_bootstrap = mk(new cmd/go, toolchain1, cmd/dist)
  1284		//
  1285		// The toolchain1 we built earlier is built from the new sources,
  1286		// but because it was built using cmd/go it has no build IDs.
  1287		// The eventually installed toolchain needs build IDs, so we need
  1288		// to do another round:
  1289		//
  1290		//	toolchain2 = mk(new toolchain, toolchain1, go_bootstrap)
  1291		//
  1292		timelog("build", "toolchain2")
  1293		if vflag > 0 {
  1294			xprintf("\n")
  1295		}
  1296		xprintf("Building Go toolchain2 using go_bootstrap and Go toolchain1.\n")
  1297		os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch))
  1298		goInstall(goBootstrap, append([]string{"-i"}, toolchain...)...)
  1299		if debug {
  1300			run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
  1301			run("", ShowOutput|CheckExit, pathf("%s/buildid", tooldir), pathf("%s/pkg/%s_%s/runtime/internal/sys.a", goroot, goos, goarch))
  1302			copyfile(pathf("%s/compile2", tooldir), pathf("%s/compile", tooldir), writeExec)
  1303		}
  1304	
  1305		// Toolchain2 should be semantically equivalent to toolchain1,
  1306		// but it was built using the new compilers instead of the Go 1.4 compilers,
  1307		// so it should at the least run faster. Also, toolchain1 had no build IDs
  1308		// in the binaries, while toolchain2 does. In non-release builds, the
  1309		// toolchain's build IDs feed into constructing the build IDs of built targets,
  1310		// so in non-release builds, everything now looks out-of-date due to
  1311		// toolchain2 having build IDs - that is, due to the go command seeing
  1312		// that there are new compilers. In release builds, the toolchain's reported
  1313		// version is used in place of the build ID, and the go command does not
  1314		// see that change from toolchain1 to toolchain2, so in release builds,
  1315		// nothing looks out of date.
  1316		// To keep the behavior the same in both non-release and release builds,
  1317		// we force-install everything here.
  1318		//
  1319		//	toolchain3 = mk(new toolchain, toolchain2, go_bootstrap)
  1320		//
  1321		timelog("build", "toolchain3")
  1322		if vflag > 0 {
  1323			xprintf("\n")
  1324		}
  1325		xprintf("Building Go toolchain3 using go_bootstrap and Go toolchain2.\n")
  1326		goInstall(goBootstrap, append([]string{"-a", "-i"}, toolchain...)...)
  1327		if debug {
  1328			run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
  1329			run("", ShowOutput|CheckExit, pathf("%s/buildid", tooldir), pathf("%s/pkg/%s_%s/runtime/internal/sys.a", goroot, goos, goarch))
  1330			copyfile(pathf("%s/compile3", tooldir), pathf("%s/compile", tooldir), writeExec)
  1331		}
  1332		checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...)
  1333	
  1334		if goos == oldgoos && goarch == oldgoarch {
  1335			// Common case - not setting up for cross-compilation.
  1336			timelog("build", "toolchain")
  1337			if vflag > 0 {
  1338				xprintf("\n")
  1339			}
  1340			xprintf("Building packages and commands for %s/%s.\n", goos, goarch)
  1341		} else {
  1342			// GOOS/GOARCH does not match GOHOSTOS/GOHOSTARCH.
  1343			// Finish GOHOSTOS/GOHOSTARCH installation and then
  1344			// run GOOS/GOARCH installation.
  1345			timelog("build", "host toolchain")
  1346			if vflag > 0 {
  1347				xprintf("\n")
  1348			}
  1349			xprintf("Building packages and commands for host, %s/%s.\n", goos, goarch)
  1350			goInstall(goBootstrap, "std", "cmd")
  1351			checkNotStale(goBootstrap, "std", "cmd")
  1352			checkNotStale(cmdGo, "std", "cmd")
  1353	
  1354			timelog("build", "target toolchain")
  1355			if vflag > 0 {
  1356				xprintf("\n")
  1357			}
  1358			goos = oldgoos
  1359			goarch = oldgoarch
  1360			os.Setenv("GOOS", goos)
  1361			os.Setenv("GOARCH", goarch)
  1362			os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch))
  1363			xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch)
  1364		}
  1365		targets := []string{"std", "cmd"}
  1366		if goos == "js" && goarch == "wasm" {
  1367			// Skip the cmd tools for js/wasm. They're not usable.
  1368			targets = targets[:1]
  1369		}
  1370		goInstall(goBootstrap, targets...)
  1371		checkNotStale(goBootstrap, targets...)
  1372		checkNotStale(cmdGo, targets...)
  1373		if debug {
  1374			run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
  1375			run("", ShowOutput|CheckExit, pathf("%s/buildid", tooldir), pathf("%s/pkg/%s_%s/runtime/internal/sys.a", goroot, goos, goarch))
  1376			checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...)
  1377			copyfile(pathf("%s/compile4", tooldir), pathf("%s/compile", tooldir), writeExec)
  1378		}
  1379	
  1380		// Check that there are no new files in $GOROOT/bin other than
  1381		// go and gofmt and $GOOS_$GOARCH (target bin when cross-compiling).
  1382		binFiles, _ := filepath.Glob(pathf("%s/bin/*", goroot))
  1383		ok := map[string]bool{}
  1384		for _, f := range oldBinFiles {
  1385			ok[f] = true
  1386		}
  1387		for _, f := range binFiles {
  1388			elem := strings.TrimSuffix(filepath.Base(f), ".exe")
  1389			if !ok[f] && elem != "go" && elem != "gofmt" && elem != goos+"_"+goarch {
  1390				fatalf("unexpected new file in $GOROOT/bin: %s", elem)
  1391			}
  1392		}
  1393	
  1394		// Remove go_bootstrap now that we're done.
  1395		xremove(pathf("%s/go_bootstrap", tooldir))
  1396	
  1397		if goos == "android" {
  1398			// Make sure the exec wrapper will sync a fresh $GOROOT to the device.
  1399			xremove(pathf("%s/go_android_exec-adb-sync-status", os.TempDir()))
  1400		}
  1401	
  1402		if wrapperPath := wrapperPathFor(goos, goarch); wrapperPath != "" {
  1403			oldcc := os.Getenv("CC")
  1404			os.Setenv("GOOS", gohostos)
  1405			os.Setenv("GOARCH", gohostarch)
  1406			os.Setenv("CC", compilerEnvLookup(defaultcc, gohostos, gohostarch))
  1407			goCmd(cmdGo, "build", "-o", pathf("%s/go_%s_%s_exec%s", gobin, goos, goarch, exe), wrapperPath)
  1408			// Restore environment.
  1409			// TODO(elias.naur): support environment variables in goCmd?
  1410			os.Setenv("GOOS", goos)
  1411			os.Setenv("GOARCH", goarch)
  1412			os.Setenv("CC", oldcc)
  1413		}
  1414	
  1415		// Print trailing banner unless instructed otherwise.
  1416		if !noBanner {
  1417			banner()
  1418		}
  1419	}
  1420	
  1421	func wrapperPathFor(goos, goarch string) string {
  1422		switch {
  1423		case goos == "android":
  1424			if gohostos != "android" {
  1425				return pathf("%s/misc/android/go_android_exec.go", goroot)
  1426			}
  1427		case goos == "darwin" && (goarch == "arm" || goarch == "arm64"):
  1428			if gohostos != "darwin" || (gohostarch != "arm" && gohostarch != "arm64") {
  1429				return pathf("%s/misc/ios/go_darwin_arm_exec.go", goroot)
  1430			}
  1431		}
  1432		return ""
  1433	}
  1434	
  1435	func goInstall(goBinary string, args ...string) {
  1436		goCmd(goBinary, "install", args...)
  1437	}
  1438	
  1439	func goCmd(goBinary string, cmd string, args ...string) {
  1440		goCmd := []string{goBinary, cmd, "-gcflags=all=" + gogcflags, "-ldflags=all=" + goldflags}
  1441		if vflag > 0 {
  1442			goCmd = append(goCmd, "-v")
  1443		}
  1444	
  1445		// Force only one process at a time on vx32 emulation.
  1446		if gohostos == "plan9" && os.Getenv("sysname") == "vx32" {
  1447			goCmd = append(goCmd, "-p=1")
  1448		}
  1449	
  1450		run(goroot, ShowOutput|CheckExit, append(goCmd, args...)...)
  1451	}
  1452	
  1453	func checkNotStale(goBinary string, targets ...string) {
  1454		out := run(goroot, CheckExit,
  1455			append([]string{
  1456				goBinary,
  1457				"list", "-gcflags=all=" + gogcflags, "-ldflags=all=" + goldflags,
  1458				"-f={{if .Stale}}\tSTALE {{.ImportPath}}: {{.StaleReason}}{{end}}",
  1459			}, targets...)...)
  1460		if strings.Contains(out, "\tSTALE ") {
  1461			os.Setenv("GODEBUG", "gocachehash=1")
  1462			for _, target := range []string{"runtime/internal/sys", "cmd/dist", "cmd/link"} {
  1463				if strings.Contains(out, "STALE "+target) {
  1464					run(goroot, ShowOutput|CheckExit, goBinary, "list", "-f={{.ImportPath}} {{.Stale}}", target)
  1465					break
  1466				}
  1467			}
  1468			fatalf("unexpected stale targets reported by %s list -gcflags=\"%s\" -ldflags=\"%s\" for %v:\n%s", goBinary, gogcflags, goldflags, targets, out)
  1469		}
  1470	}
  1471	
  1472	// Cannot use go/build directly because cmd/dist for a new release
  1473	// builds against an old release's go/build, which may be out of sync.
  1474	// To reduce duplication, we generate the list for go/build from this.
  1475	//
  1476	// We list all supported platforms in this list, so that this is the
  1477	// single point of truth for supported platforms. This list is used
  1478	// by 'go tool dist list'.
  1479	var cgoEnabled = map[string]bool{
  1480		"aix/ppc64":       true,
  1481		"darwin/386":      false, // Issue 31751
  1482		"darwin/amd64":    true,
  1483		"darwin/arm":      true,
  1484		"darwin/arm64":    true,
  1485		"dragonfly/amd64": true,
  1486		"freebsd/386":     true,
  1487		"freebsd/amd64":   true,
  1488		"freebsd/arm":     true,
  1489		"illumos/amd64":   true,
  1490		"linux/386":       true,
  1491		"linux/amd64":     true,
  1492		"linux/arm":       true,
  1493		"linux/arm64":     true,
  1494		"linux/ppc64":     false,
  1495		"linux/ppc64le":   true,
  1496		"linux/mips":      true,
  1497		"linux/mipsle":    true,
  1498		"linux/mips64":    true,
  1499		"linux/mips64le":  true,
  1500		"linux/riscv64":   true,
  1501		"linux/s390x":     true,
  1502		"linux/sparc64":   true,
  1503		"android/386":     true,
  1504		"android/amd64":   true,
  1505		"android/arm":     true,
  1506		"android/arm64":   true,
  1507		"js/wasm":         false,
  1508		"nacl/386":        false,
  1509		"nacl/amd64p32":   false,
  1510		"nacl/arm":        false,
  1511		"netbsd/386":      true,
  1512		"netbsd/amd64":    true,
  1513		"netbsd/arm":      true,
  1514		"netbsd/arm64":    true,
  1515		"openbsd/386":     true,
  1516		"openbsd/amd64":   true,
  1517		"openbsd/arm":     true,
  1518		"openbsd/arm64":   true,
  1519		"plan9/386":       false,
  1520		"plan9/amd64":     false,
  1521		"plan9/arm":       false,
  1522		"solaris/amd64":   true,
  1523		"windows/386":     true,
  1524		"windows/amd64":   true,
  1525		"windows/arm":     false,
  1526	}
  1527	
  1528	// List of platforms which are supported but not complete yet. These get
  1529	// filtered out of cgoEnabled for 'dist list'. See golang.org/issue/28944
  1530	var incomplete = map[string]bool{
  1531		"linux/riscv64": true,
  1532		"linux/sparc64": true,
  1533	}
  1534	
  1535	func needCC() bool {
  1536		switch os.Getenv("CGO_ENABLED") {
  1537		case "1":
  1538			return true
  1539		case "0":
  1540			return false
  1541		}
  1542		return cgoEnabled[gohostos+"/"+gohostarch]
  1543	}
  1544	
  1545	func checkCC() {
  1546		if !needCC() {
  1547			return
  1548		}
  1549		if output, err := exec.Command(defaultcc[""], "--help").CombinedOutput(); err != nil {
  1550			outputHdr := ""
  1551			if len(output) > 0 {
  1552				outputHdr = "\nCommand output:\n\n"
  1553			}
  1554			fatalf("cannot invoke C compiler %q: %v\n\n"+
  1555				"Go needs a system C compiler for use with cgo.\n"+
  1556				"To set a C compiler, set CC=the-compiler.\n"+
  1557				"To disable cgo, set CGO_ENABLED=0.\n%s%s", defaultcc[""], err, outputHdr, output)
  1558		}
  1559	}
  1560	
  1561	func defaulttarg() string {
  1562		// xgetwd might return a path with symlinks fully resolved, and if
  1563		// there happens to be symlinks in goroot, then the hasprefix test
  1564		// will never succeed. Instead, we use xrealwd to get a canonical
  1565		// goroot/src before the comparison to avoid this problem.
  1566		pwd := xgetwd()
  1567		src := pathf("%s/src/", goroot)
  1568		real_src := xrealwd(src)
  1569		if !strings.HasPrefix(pwd, real_src) {
  1570			fatalf("current directory %s is not under %s", pwd, real_src)
  1571		}
  1572		pwd = pwd[len(real_src):]
  1573		// guard against xrealwd returning the directory without the trailing /
  1574		pwd = strings.TrimPrefix(pwd, "/")
  1575	
  1576		return pwd
  1577	}
  1578	
  1579	// Install installs the list of packages named on the command line.
  1580	func cmdinstall() {
  1581		xflagparse(-1)
  1582	
  1583		if flag.NArg() == 0 {
  1584			install(defaulttarg())
  1585		}
  1586	
  1587		for _, arg := range flag.Args() {
  1588			install(arg)
  1589		}
  1590	}
  1591	
  1592	// Clean deletes temporary objects.
  1593	func cmdclean() {
  1594		xflagparse(0)
  1595		clean()
  1596	}
  1597	
  1598	// Banner prints the 'now you've installed Go' banner.
  1599	func cmdbanner() {
  1600		xflagparse(0)
  1601		banner()
  1602	}
  1603	
  1604	func banner() {
  1605		if vflag > 0 {
  1606			xprintf("\n")
  1607		}
  1608		xprintf("---\n")
  1609		xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot)
  1610		xprintf("Installed commands in %s\n", gobin)
  1611	
  1612		if !xsamefile(goroot_final, goroot) {
  1613			// If the files are to be moved, don't check that gobin
  1614			// is on PATH; assume they know what they are doing.
  1615		} else if gohostos == "plan9" {
  1616			// Check that gobin is bound before /bin.
  1617			pid := strings.Replace(readfile("#c/pid"), " ", "", -1)
  1618			ns := fmt.Sprintf("/proc/%s/ns", pid)
  1619			if !strings.Contains(readfile(ns), fmt.Sprintf("bind -b %s /bin", gobin)) {
  1620				xprintf("*** You need to bind %s before /bin.\n", gobin)
  1621			}
  1622		} else {
  1623			// Check that gobin appears in $PATH.
  1624			pathsep := ":"
  1625			if gohostos == "windows" {
  1626				pathsep = ";"
  1627			}
  1628			if !strings.Contains(pathsep+os.Getenv("PATH")+pathsep, pathsep+gobin+pathsep) {
  1629				xprintf("*** You need to add %s to your PATH.\n", gobin)
  1630			}
  1631		}
  1632	
  1633		if !xsamefile(goroot_final, goroot) {
  1634			xprintf("\n"+
  1635				"The binaries expect %s to be copied or moved to %s\n",
  1636				goroot, goroot_final)
  1637		}
  1638	}
  1639	
  1640	// Version prints the Go version.
  1641	func cmdversion() {
  1642		xflagparse(0)
  1643		xprintf("%s\n", findgoversion())
  1644	}
  1645	
  1646	// cmdlist lists all supported platforms.
  1647	func cmdlist() {
  1648		jsonFlag := flag.Bool("json", false, "produce JSON output")
  1649		xflagparse(0)
  1650	
  1651		var plats []string
  1652		for p := range cgoEnabled {
  1653			if incomplete[p] {
  1654				continue
  1655			}
  1656			plats = append(plats, p)
  1657		}
  1658		sort.Strings(plats)
  1659	
  1660		if !*jsonFlag {
  1661			for _, p := range plats {
  1662				xprintf("%s\n", p)
  1663			}
  1664			return
  1665		}
  1666	
  1667		type jsonResult struct {
  1668			GOOS         string
  1669			GOARCH       string
  1670			CgoSupported bool
  1671		}
  1672		var results []jsonResult
  1673		for _, p := range plats {
  1674			fields := strings.Split(p, "/")
  1675			results = append(results, jsonResult{
  1676				GOOS:         fields[0],
  1677				GOARCH:       fields[1],
  1678				CgoSupported: cgoEnabled[p]})
  1679		}
  1680		out, err := json.MarshalIndent(results, "", "\t")
  1681		if err != nil {
  1682			fatalf("json marshal error: %v", err)
  1683		}
  1684		if _, err := os.Stdout.Write(out); err != nil {
  1685			fatalf("write failed: %v", err)
  1686		}
  1687	}
  1688	

View as plain text