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