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 }