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