github.com/zxy12/go_duplicate_1_12@v0.0.0-20200217043740-b1636fc0368b/src/cmd/dist/cmdbootstrap.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"os"
     6  	"os/exec"
     7  	"path/filepath"
     8  	"strings"
     9  )
    10  
    11  // The bootstrap command runs a build from scratch,
    12  // stopping at having installed the go_bootstrap command.
    13  //
    14  // WARNING: This command runs after cmd/dist is built with Go 1.4.
    15  // It rebuilds and installs cmd/dist with the new toolchain, so other
    16  // commands (like "go tool dist test" in run.bash) can rely on bug fixes
    17  // made since Go 1.4, but this function cannot. In particular, the uses
    18  // of os/exec in this function cannot assume that
    19  //  cmd.Env = append(os.Environ(), "X=Y")
    20  // sets $X to Y in the command's environment. That guarantee was
    21  // added after Go 1.4, and in fact in Go 1.4 it was typically the opposite:
    22  // if $X was already present in os.Environ(), most systems preferred
    23  // that setting, not the new one.
    24  func _cmdbootstrap() {
    25  	timelog("start", "dist bootstrap")
    26  	defer timelog("end", "dist bootstrap")
    27  
    28  	var noBanner bool
    29  	var debug bool
    30  	flag.BoolVar(&rebuildall, "a", rebuildall, "rebuild all")
    31  	flag.BoolVar(&debug, "d", debug, "enable debugging of bootstrap process")
    32  	flag.BoolVar(&noBanner, "no-banner", noBanner, "do not print banner")
    33  
    34  	xflagparse(0)
    35  
    36  	if debug {
    37  		// cmd/buildid is used in debug mode.
    38  		toolchain = append(toolchain, "cmd/buildid")
    39  	}
    40  
    41  	if isdir(pathf("%s/src/pkg", goroot)) {
    42  		fatalf("\n\n"+
    43  			"The Go package sources have moved to $GOROOT/src.\n"+
    44  			"*** %s still exists. ***\n"+
    45  			"It probably contains stale files that may confuse the build.\n"+
    46  			"Please (check what's there and) remove it and try again.\n"+
    47  			"See https://golang.org/s/go14nopkg\n",
    48  			pathf("%s/src/pkg", goroot))
    49  	}
    50  
    51  	if rebuildall {
    52  		clean()
    53  	}
    54  
    55  	setup()
    56  
    57  	timelog("build", "toolchain1")
    58  	checkCC()
    59  	bootstrapBuildTools()
    60  
    61  	// Remember old content of $GOROOT/bin for comparison below.
    62  	oldBinFiles, _ := filepath.Glob(pathf("%s/bin/*", goroot))
    63  
    64  	// For the main bootstrap, building for host os/arch.
    65  	oldgoos = goos
    66  	oldgoarch = goarch
    67  	goos = gohostos
    68  	goarch = gohostarch
    69  	os.Setenv("GOHOSTARCH", gohostarch)
    70  	os.Setenv("GOHOSTOS", gohostos)
    71  	os.Setenv("GOARCH", goarch)
    72  	os.Setenv("GOOS", goos)
    73  
    74  	timelog("build", "go_bootstrap")
    75  	xprintf("Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.\n")
    76  
    77  	install("runtime") // dependency not visible in sources; also sets up textflag.h
    78  
    79  	_logret()
    80  	return
    81  	install("cmd/go")
    82  	if vflag > 0 {
    83  		xprintf("\n")
    84  	}
    85  
    86  	gogcflags = os.Getenv("GO_GCFLAGS") // we were using $BOOT_GO_GCFLAGS until now
    87  	goldflags = os.Getenv("GO_LDFLAGS")
    88  	goBootstrap := pathf("%s/go_bootstrap", tooldir)
    89  	cmdGo := pathf("%s/go", gobin)
    90  	if debug {
    91  		run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
    92  		copyfile(pathf("%s/compile1", tooldir), pathf("%s/compile", tooldir), writeExec)
    93  	}
    94  
    95  	// To recap, so far we have built the new toolchain
    96  	// (cmd/asm, cmd/cgo, cmd/compile, cmd/link)
    97  	// using Go 1.4's toolchain and go command.
    98  	// Then we built the new go command (as go_bootstrap)
    99  	// using the new toolchain and our own build logic (above).
   100  	//
   101  	//  toolchain1 = mk(new toolchain, go1.4 toolchain, go1.4 cmd/go)
   102  	//  go_bootstrap = mk(new cmd/go, toolchain1, cmd/dist)
   103  	//
   104  	// The toolchain1 we built earlier is built from the new sources,
   105  	// but because it was built using cmd/go it has no build IDs.
   106  	// The eventually installed toolchain needs build IDs, so we need
   107  	// to do another round:
   108  	//
   109  	//  toolchain2 = mk(new toolchain, toolchain1, go_bootstrap)
   110  	//
   111  	timelog("build", "toolchain2")
   112  	if vflag > 0 {
   113  		xprintf("\n")
   114  	}
   115  	xprintf("Building Go toolchain2 using go_bootstrap and Go toolchain1.\n")
   116  	os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch))
   117  
   118  	_pf(1, "goBootstrap=[%s,%v]", goBootstrap, toolchain)
   119  
   120  	goInstall(goBootstrap, append([]string{"-i"}, toolchain...)...)
   121  	if debug {
   122  		run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
   123  		run("", ShowOutput|CheckExit, pathf("%s/buildid", tooldir), pathf("%s/pkg/%s_%s/runtime/internal/sys.a", goroot, goos, goarch))
   124  		copyfile(pathf("%s/compile2", tooldir), pathf("%s/compile", tooldir), writeExec)
   125  	}
   126  
   127  	// Toolchain2 should be semantically equivalent to toolchain1,
   128  	// but it was built using the new compilers instead of the Go 1.4 compilers,
   129  	// so it should at the least run faster. Also, toolchain1 had no build IDs
   130  	// in the binaries, while toolchain2 does. In non-release builds, the
   131  	// toolchain's build IDs feed into constructing the build IDs of built targets,
   132  	// so in non-release builds, everything now looks out-of-date due to
   133  	// toolchain2 having build IDs - that is, due to the go command seeing
   134  	// that there are new compilers. In release builds, the toolchain's reported
   135  	// version is used in place of the build ID, and the go command does not
   136  	// see that change from toolchain1 to toolchain2, so in release builds,
   137  	// nothing looks out of date.
   138  	// To keep the behavior the same in both non-release and release builds,
   139  	// we force-install everything here.
   140  	//
   141  	//  toolchain3 = mk(new toolchain, toolchain2, go_bootstrap)
   142  	//
   143  	timelog("build", "toolchain3")
   144  	if vflag > 0 {
   145  		xprintf("\n")
   146  	}
   147  	xprintf("Building Go toolchain3 using go_bootstrap and Go toolchain2.\n")
   148  	goInstall(goBootstrap, append([]string{"-a", "-i"}, toolchain...)...)
   149  	if debug {
   150  		run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
   151  		run("", ShowOutput|CheckExit, pathf("%s/buildid", tooldir), pathf("%s/pkg/%s_%s/runtime/internal/sys.a", goroot, goos, goarch))
   152  		copyfile(pathf("%s/compile3", tooldir), pathf("%s/compile", tooldir), writeExec)
   153  	}
   154  	checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...)
   155  
   156  	if goos == oldgoos && goarch == oldgoarch {
   157  		// Common case - not setting up for cross-compilation.
   158  		timelog("build", "toolchain")
   159  		if vflag > 0 {
   160  			xprintf("\n")
   161  		}
   162  		xprintf("Building packages and commands for %s/%s.\n", goos, goarch)
   163  	} else {
   164  		// GOOS/GOARCH does not match GOHOSTOS/GOHOSTARCH.
   165  		// Finish GOHOSTOS/GOHOSTARCH installation and then
   166  		// run GOOS/GOARCH installation.
   167  		timelog("build", "host toolchain")
   168  		if vflag > 0 {
   169  			xprintf("\n")
   170  		}
   171  		xprintf("Building packages and commands for host, %s/%s.\n", goos, goarch)
   172  		goInstall(goBootstrap, "std", "cmd")
   173  		checkNotStale(goBootstrap, "std", "cmd")
   174  		checkNotStale(cmdGo, "std", "cmd")
   175  
   176  		timelog("build", "target toolchain")
   177  		if vflag > 0 {
   178  			xprintf("\n")
   179  		}
   180  		goos = oldgoos
   181  		goarch = oldgoarch
   182  		os.Setenv("GOOS", goos)
   183  		os.Setenv("GOARCH", goarch)
   184  		os.Setenv("CC", compilerEnvLookup(defaultcc, goos, goarch))
   185  		xprintf("Building packages and commands for target, %s/%s.\n", goos, goarch)
   186  	}
   187  	targets := []string{"std", "cmd"}
   188  	if goos == "js" && goarch == "wasm" {
   189  		// Skip the cmd tools for js/wasm. They're not usable.
   190  		targets = targets[:1]
   191  	}
   192  	goInstall(goBootstrap, targets...)
   193  	checkNotStale(goBootstrap, targets...)
   194  	checkNotStale(cmdGo, targets...)
   195  	if debug {
   196  		run("", ShowOutput|CheckExit, pathf("%s/compile", tooldir), "-V=full")
   197  		run("", ShowOutput|CheckExit, pathf("%s/buildid", tooldir), pathf("%s/pkg/%s_%s/runtime/internal/sys.a", goroot, goos, goarch))
   198  		checkNotStale(goBootstrap, append(toolchain, "runtime/internal/sys")...)
   199  		copyfile(pathf("%s/compile4", tooldir), pathf("%s/compile", tooldir), writeExec)
   200  	}
   201  
   202  	// Check that there are no new files in $GOROOT/bin other than
   203  	// go and gofmt and $GOOS_$GOARCH (target bin when cross-compiling).
   204  	binFiles, _ := filepath.Glob(pathf("%s/bin/*", goroot))
   205  	ok := map[string]bool{}
   206  	for _, f := range oldBinFiles {
   207  		ok[f] = true
   208  	}
   209  	for _, f := range binFiles {
   210  		elem := strings.TrimSuffix(filepath.Base(f), ".exe")
   211  		if !ok[f] && elem != "go" && elem != "gofmt" && elem != goos+"_"+goarch {
   212  			fatalf("unexpected new file in $GOROOT/bin: %s", elem)
   213  		}
   214  	}
   215  
   216  	// Remove go_bootstrap now that we're done.
   217  	xremove(pathf("%s/go_bootstrap", tooldir))
   218  
   219  	// Print trailing banner unless instructed otherwise.
   220  	if !noBanner {
   221  		banner()
   222  	}
   223  }
   224  
   225  // setup sets up the tree for the initial build.
   226  func setup() {
   227  	// Create bin directory.
   228  	if p := pathf("%s/bin", goroot); !isdir(p) {
   229  		xmkdir(p)
   230  	}
   231  
   232  	// Create package directory.
   233  	if p := pathf("%s/pkg", goroot); !isdir(p) {
   234  		xmkdir(p)
   235  	}
   236  
   237  	p := pathf("%s/pkg/%s_%s", goroot, gohostos, gohostarch)
   238  	if rebuildall {
   239  		xremoveall(p)
   240  	}
   241  	xmkdirall(p)
   242  
   243  	if goos != gohostos || goarch != gohostarch {
   244  		p := pathf("%s/pkg/%s_%s", goroot, goos, goarch)
   245  		if rebuildall {
   246  			xremoveall(p)
   247  		}
   248  		xmkdirall(p)
   249  	}
   250  
   251  	// Create object directory.
   252  	// We used to use it for C objects.
   253  	// Now we use it for the build cache, to separate dist's cache
   254  	// from any other cache the user might have.
   255  	p = pathf("%s/pkg/obj/go-build", goroot)
   256  	if rebuildall {
   257  		xremoveall(p)
   258  	}
   259  	xmkdirall(p)
   260  
   261  	// Create tool directory.
   262  	// We keep it in pkg/, just like the object directory above.
   263  	if rebuildall {
   264  		xremoveall(tooldir)
   265  	}
   266  	xmkdirall(tooldir)
   267  
   268  	// Remove tool binaries from before the tool/gohostos_gohostarch
   269  	xremoveall(pathf("%s/bin/tool", goroot))
   270  
   271  	// Remove old pre-tool binaries.
   272  	for _, old := range oldtool {
   273  		xremove(pathf("%s/bin/%s", goroot, old))
   274  	}
   275  
   276  	// If $GOBIN is set and has a Go compiler, it must be cleaned.
   277  	for _, char := range "56789" {
   278  		if isfile(pathf("%s/%c%s", gobin, char, "g")) {
   279  			for _, old := range oldtool {
   280  				xremove(pathf("%s/%s", gobin, old))
   281  			}
   282  			break
   283  		}
   284  	}
   285  
   286  	// For release, make sure excluded things are excluded.
   287  	goversion := findgoversion()
   288  	if strings.HasPrefix(goversion, "release.") || (strings.HasPrefix(goversion, "go") && !strings.Contains(goversion, "beta")) {
   289  		for _, dir := range unreleased {
   290  			if p := pathf("%s/%s", goroot, dir); isdir(p) {
   291  				fatalf("%s should not exist in release build", p)
   292  			}
   293  		}
   294  	}
   295  }
   296  
   297  func checkCC() {
   298  	if !needCC() {
   299  		return
   300  	}
   301  	if output, err := exec.Command(defaultcc[""], "--help").CombinedOutput(); err != nil {
   302  		outputHdr := ""
   303  		if len(output) > 0 {
   304  			outputHdr = "\nCommand output:\n\n"
   305  		}
   306  		fatalf("cannot invoke C compiler %q: %v\n\n"+
   307  			"Go needs a system C compiler for use with cgo.\n"+
   308  			"To set a C compiler, set CC=the-compiler.\n"+
   309  			"To disable cgo, set CGO_ENABLED=0.\n%s%s", defaultcc[""], err, outputHdr, output)
   310  	}
   311  }
   312  
   313  func needCC() bool {
   314  	switch os.Getenv("CGO_ENABLED") {
   315  	case "1":
   316  		return true
   317  	case "0":
   318  		return false
   319  	}
   320  	return cgoEnabled[gohostos+"/"+gohostarch]
   321  }