github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/dist/buildtool.go (about) 1 // Copyright 2015 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 // Build toolchain using Go 1.4. 6 // 7 // The general strategy is to copy the source files we need into 8 // a new GOPATH workspace, adjust import paths appropriately, 9 // invoke the Go 1.4 go command to build those sources, 10 // and then copy the binaries back. 11 12 package main 13 14 import ( 15 "fmt" 16 "os" 17 "path/filepath" 18 "runtime" 19 "strings" 20 ) 21 22 // bootstrapDirs is a list of directories holding code that must be 23 // compiled with a Go 1.4 toolchain to produce the bootstrapTargets. 24 // All directories in this list are relative to and must be below $GOROOT/src. 25 // 26 // The list has have two kinds of entries: names beginning with cmd/ with 27 // no other slashes, which are commands, and other paths, which are packages 28 // supporting the commands. Packages in the standard library can be listed 29 // if a newer copy needs to be substituted for the Go 1.4 copy when used 30 // by the command packages. 31 // These will be imported during bootstrap as bootstrap/name, like bootstrap/math/big. 32 var bootstrapDirs = []string{ 33 "cmd/asm", 34 "cmd/asm/internal/arch", 35 "cmd/asm/internal/asm", 36 "cmd/asm/internal/flags", 37 "cmd/asm/internal/lex", 38 "cmd/cgo", 39 "cmd/compile", 40 "cmd/compile/internal/amd64", 41 "cmd/compile/internal/arm", 42 "cmd/compile/internal/arm64", 43 "cmd/compile/internal/gc", 44 "cmd/compile/internal/mips", 45 "cmd/compile/internal/mips64", 46 "cmd/compile/internal/ppc64", 47 "cmd/compile/internal/types", 48 "cmd/compile/internal/s390x", 49 "cmd/compile/internal/ssa", 50 "cmd/compile/internal/syntax", 51 "cmd/compile/internal/x86", 52 "cmd/compile/internal/wasm", 53 "cmd/internal/bio", 54 "cmd/internal/gcprog", 55 "cmd/internal/dwarf", 56 "cmd/internal/edit", 57 "cmd/internal/objabi", 58 "cmd/internal/obj", 59 "cmd/internal/obj/arm", 60 "cmd/internal/obj/arm64", 61 "cmd/internal/obj/mips", 62 "cmd/internal/obj/ppc64", 63 "cmd/internal/obj/s390x", 64 "cmd/internal/obj/x86", 65 "cmd/internal/obj/wasm", 66 "cmd/internal/src", 67 "cmd/internal/sys", 68 "cmd/link", 69 "cmd/link/internal/amd64", 70 "cmd/link/internal/arm", 71 "cmd/link/internal/arm64", 72 "cmd/link/internal/ld", 73 "cmd/link/internal/loadelf", 74 "cmd/link/internal/loadmacho", 75 "cmd/link/internal/loadpe", 76 "cmd/link/internal/loadxcoff", 77 "cmd/link/internal/mips", 78 "cmd/link/internal/mips64", 79 "cmd/link/internal/objfile", 80 "cmd/link/internal/ppc64", 81 "cmd/link/internal/s390x", 82 "cmd/link/internal/sym", 83 "cmd/link/internal/x86", 84 "compress/flate", 85 "compress/zlib", 86 "cmd/link/internal/wasm", 87 "container/heap", 88 "debug/dwarf", 89 "debug/elf", 90 "debug/macho", 91 "debug/pe", 92 "internal/xcoff", 93 "math/big", 94 "math/bits", 95 "sort", 96 } 97 98 // File prefixes that are ignored by go/build anyway, and cause 99 // problems with editor generated temporary files (#18931). 100 var ignorePrefixes = []string{ 101 ".", 102 "_", 103 } 104 105 // File suffixes that use build tags introduced since Go 1.4. 106 // These must not be copied into the bootstrap build directory. 107 var ignoreSuffixes = []string{ 108 "_arm64.s", 109 "_arm64.go", 110 "_wasm.s", 111 "_wasm.go", 112 } 113 114 func bootstrapBuildTools() { 115 goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP") 116 if goroot_bootstrap == "" { 117 goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME")) 118 } 119 xprintf("Building Go toolchain1 using %s.\n", goroot_bootstrap) 120 121 mkzbootstrap(pathf("%s/src/cmd/internal/objabi/zbootstrap.go", goroot)) 122 123 // Use $GOROOT/pkg/bootstrap as the bootstrap workspace root. 124 // We use a subdirectory of $GOROOT/pkg because that's the 125 // space within $GOROOT where we store all generated objects. 126 // We could use a temporary directory outside $GOROOT instead, 127 // but it is easier to debug on failure if the files are in a known location. 128 workspace := pathf("%s/pkg/bootstrap", goroot) 129 xremoveall(workspace) 130 base := pathf("%s/src/bootstrap", workspace) 131 xmkdirall(base) 132 133 // Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths. 134 for _, dir := range bootstrapDirs { 135 src := pathf("%s/src/%s", goroot, dir) 136 dst := pathf("%s/%s", base, dir) 137 xmkdirall(dst) 138 if dir == "cmd/cgo" { 139 // Write to src because we need the file both for bootstrap 140 // and for later in the main build. 141 mkzdefaultcc("", pathf("%s/zdefaultcc.go", src)) 142 } 143 Dir: 144 for _, name := range xreaddirfiles(src) { 145 for _, pre := range ignorePrefixes { 146 if strings.HasPrefix(name, pre) { 147 continue Dir 148 } 149 } 150 for _, suf := range ignoreSuffixes { 151 if strings.HasSuffix(name, suf) { 152 continue Dir 153 } 154 } 155 srcFile := pathf("%s/%s", src, name) 156 dstFile := pathf("%s/%s", dst, name) 157 text := bootstrapRewriteFile(srcFile) 158 writefile(text, dstFile, 0) 159 } 160 } 161 162 // Set up environment for invoking Go 1.4 go command. 163 // GOROOT points at Go 1.4 GOROOT, 164 // GOPATH points at our bootstrap workspace, 165 // GOBIN is empty, so that binaries are installed to GOPATH/bin, 166 // and GOOS, GOHOSTOS, GOARCH, and GOHOSTOS are empty, 167 // so that Go 1.4 builds whatever kind of binary it knows how to build. 168 // Restore GOROOT, GOPATH, and GOBIN when done. 169 // Don't bother with GOOS, GOHOSTOS, GOARCH, and GOHOSTARCH, 170 // because setup will take care of those when bootstrapBuildTools returns. 171 172 defer os.Setenv("GOROOT", os.Getenv("GOROOT")) 173 os.Setenv("GOROOT", goroot_bootstrap) 174 175 defer os.Setenv("GOPATH", os.Getenv("GOPATH")) 176 os.Setenv("GOPATH", workspace) 177 178 defer os.Setenv("GOBIN", os.Getenv("GOBIN")) 179 os.Setenv("GOBIN", "") 180 181 os.Setenv("GOOS", "") 182 os.Setenv("GOHOSTOS", "") 183 os.Setenv("GOARCH", "") 184 os.Setenv("GOHOSTARCH", "") 185 186 // Run Go 1.4 to build binaries. Use -gcflags=-l to disable inlining to 187 // workaround bugs in Go 1.4's compiler. See discussion thread: 188 // https://groups.google.com/d/msg/golang-dev/Ss7mCKsvk8w/Gsq7VYI0AwAJ 189 // Use the math_big_pure_go build tag to disable the assembly in math/big 190 // which may contain unsupported instructions. 191 // Note that if we are using Go 1.10 or later as bootstrap, the -gcflags=-l 192 // only applies to the final cmd/go binary, but that's OK: if this is Go 1.10 193 // or later we don't need to disable inlining to work around bugs in the Go 1.4 compiler. 194 cmd := []string{ 195 pathf("%s/bin/go", goroot_bootstrap), 196 "install", 197 "-gcflags=-l", 198 "-tags=math_big_pure_go compiler_bootstrap", 199 } 200 if vflag > 0 { 201 cmd = append(cmd, "-v") 202 } 203 if tool := os.Getenv("GOBOOTSTRAP_TOOLEXEC"); tool != "" { 204 cmd = append(cmd, "-toolexec="+tool) 205 } 206 cmd = append(cmd, "bootstrap/cmd/...") 207 run(workspace, ShowOutput|CheckExit, cmd...) 208 209 // Copy binaries into tool binary directory. 210 for _, name := range bootstrapDirs { 211 if !strings.HasPrefix(name, "cmd/") { 212 continue 213 } 214 name = name[len("cmd/"):] 215 if !strings.Contains(name, "/") { 216 copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec) 217 } 218 } 219 220 if vflag > 0 { 221 xprintf("\n") 222 } 223 } 224 225 var ssaRewriteFileSubstring = filepath.FromSlash("src/cmd/compile/internal/ssa/rewrite") 226 227 // isUnneededSSARewriteFile reports whether srcFile is a 228 // src/cmd/compile/internal/ssa/rewriteARCHNAME.go file for an 229 // architecture that isn't for the current runtime.GOARCH. 230 // 231 // When unneeded is true archCaps is the rewrite base filename without 232 // the "rewrite" prefix or ".go" suffix: AMD64, 386, ARM, ARM64, etc. 233 func isUnneededSSARewriteFile(srcFile string) (archCaps string, unneeded bool) { 234 if !strings.Contains(srcFile, ssaRewriteFileSubstring) { 235 return "", false 236 } 237 fileArch := strings.TrimSuffix(strings.TrimPrefix(filepath.Base(srcFile), "rewrite"), ".go") 238 if fileArch == "" { 239 return "", false 240 } 241 b := fileArch[0] 242 if b == '_' || ('a' <= b && b <= 'z') { 243 return "", false 244 } 245 archCaps = fileArch 246 fileArch = strings.ToLower(fileArch) 247 if fileArch == strings.TrimSuffix(runtime.GOARCH, "le") { 248 return "", false 249 } 250 if fileArch == strings.TrimSuffix(os.Getenv("GOARCH"), "le") { 251 return "", false 252 } 253 return archCaps, true 254 } 255 256 func bootstrapRewriteFile(srcFile string) string { 257 // During bootstrap, generate dummy rewrite files for 258 // irrelevant architectures. We only need to build a bootstrap 259 // binary that works for the current runtime.GOARCH. 260 // This saves 6+ seconds of bootstrap. 261 if archCaps, ok := isUnneededSSARewriteFile(srcFile); ok { 262 return fmt.Sprintf(`// Code generated by go tool dist; DO NOT EDIT. 263 264 package ssa 265 266 func rewriteValue%s(v *Value) bool { panic("unused during bootstrap") } 267 func rewriteBlock%s(b *Block) bool { panic("unused during bootstrap") } 268 `, archCaps, archCaps) 269 } 270 271 return bootstrapFixImports(srcFile) 272 } 273 274 func bootstrapFixImports(srcFile string) string { 275 lines := strings.SplitAfter(readfile(srcFile), "\n") 276 inBlock := false 277 for i, line := range lines { 278 if strings.HasPrefix(line, "import (") { 279 inBlock = true 280 continue 281 } 282 if inBlock && strings.HasPrefix(line, ")") { 283 inBlock = false 284 continue 285 } 286 if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) || 287 inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) { 288 line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1) 289 for _, dir := range bootstrapDirs { 290 if strings.HasPrefix(dir, "cmd/") { 291 continue 292 } 293 line = strings.Replace(line, `"`+dir+`"`, `"bootstrap/`+dir+`"`, -1) 294 } 295 lines[i] = line 296 } 297 } 298 299 lines[0] = "// Code generated by go tool dist; DO NOT EDIT.\n// This is a bootstrap copy of " + srcFile + "\n\n//line " + srcFile + ":1\n" + lines[0] 300 301 return strings.Join(lines, "") 302 }