github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/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 "os" 16 "strings" 17 ) 18 19 // bootstrapDirs is a list of directories holding code that must be 20 // compiled with a Go 1.4 toolchain to produce the bootstrapTargets. 21 // All directories in this list are relative to and must be below $GOROOT/src. 22 // 23 // The list has have two kinds of entries: names beginning with cmd/ with 24 // no other slashes, which are commands, and other paths, which are packages 25 // supporting the commands. Packages in the standard library can be listed 26 // if a newer copy needs to be substituted for the Go 1.4 copy when used 27 // by the command packages. 28 // These will be imported during bootstrap as bootstrap/name, like bootstrap/math/big. 29 var bootstrapDirs = []string{ 30 "cmd/asm", 31 "cmd/asm/internal/arch", 32 "cmd/asm/internal/asm", 33 "cmd/asm/internal/flags", 34 "cmd/asm/internal/lex", 35 "cmd/compile", 36 "cmd/compile/internal/amd64", 37 "cmd/compile/internal/arm", 38 "cmd/compile/internal/arm64", 39 "cmd/compile/internal/gc", 40 "cmd/compile/internal/mips64", 41 "cmd/compile/internal/ppc64", 42 "cmd/compile/internal/s390x", 43 "cmd/compile/internal/ssa", 44 "cmd/compile/internal/syntax", 45 "cmd/compile/internal/x86", 46 "cmd/internal/bio", 47 "cmd/internal/gcprog", 48 "cmd/internal/dwarf", 49 "cmd/internal/obj", 50 "cmd/internal/obj/arm", 51 "cmd/internal/obj/arm64", 52 "cmd/internal/obj/mips", 53 "cmd/internal/obj/ppc64", 54 "cmd/internal/obj/s390x", 55 "cmd/internal/obj/x86", 56 "cmd/internal/sys", 57 "cmd/link", 58 "cmd/link/internal/amd64", 59 "cmd/link/internal/arm", 60 "cmd/link/internal/arm64", 61 "cmd/link/internal/ld", 62 "cmd/link/internal/mips64", 63 "cmd/link/internal/ppc64", 64 "cmd/link/internal/s390x", 65 "cmd/link/internal/x86", 66 "debug/pe", 67 "math/big", 68 } 69 70 // File suffixes that use build tags introduced since Go 1.4. 71 // These must not be copied into the bootstrap build directory. 72 var ignoreSuffixes = []string{ 73 "_arm64.s", 74 "_arm64.go", 75 } 76 77 func bootstrapBuildTools() { 78 goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP") 79 if goroot_bootstrap == "" { 80 goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME")) 81 } 82 xprintf("##### Building Go toolchain using %s.\n", goroot_bootstrap) 83 84 mkzbootstrap(pathf("%s/src/cmd/internal/obj/zbootstrap.go", goroot)) 85 86 // Use $GOROOT/pkg/bootstrap as the bootstrap workspace root. 87 // We use a subdirectory of $GOROOT/pkg because that's the 88 // space within $GOROOT where we store all generated objects. 89 // We could use a temporary directory outside $GOROOT instead, 90 // but it is easier to debug on failure if the files are in a known location. 91 workspace := pathf("%s/pkg/bootstrap", goroot) 92 xremoveall(workspace) 93 base := pathf("%s/src/bootstrap", workspace) 94 xmkdirall(base) 95 96 // Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths. 97 for _, dir := range bootstrapDirs { 98 src := pathf("%s/src/%s", goroot, dir) 99 dst := pathf("%s/%s", base, dir) 100 xmkdirall(dst) 101 Dir: 102 for _, name := range xreaddirfiles(src) { 103 for _, suf := range ignoreSuffixes { 104 if strings.HasSuffix(name, suf) { 105 continue Dir 106 } 107 } 108 srcFile := pathf("%s/%s", src, name) 109 text := readfile(srcFile) 110 text = bootstrapFixImports(text, srcFile) 111 writefile(text, pathf("%s/%s", dst, name), 0) 112 } 113 } 114 115 // Set up environment for invoking Go 1.4 go command. 116 // GOROOT points at Go 1.4 GOROOT, 117 // GOPATH points at our bootstrap workspace, 118 // GOBIN is empty, so that binaries are installed to GOPATH/bin, 119 // and GOOS, GOHOSTOS, GOARCH, and GOHOSTOS are empty, 120 // so that Go 1.4 builds whatever kind of binary it knows how to build. 121 // Restore GOROOT, GOPATH, and GOBIN when done. 122 // Don't bother with GOOS, GOHOSTOS, GOARCH, and GOHOSTARCH, 123 // because setup will take care of those when bootstrapBuildTools returns. 124 125 defer os.Setenv("GOROOT", os.Getenv("GOROOT")) 126 os.Setenv("GOROOT", goroot_bootstrap) 127 128 defer os.Setenv("GOPATH", os.Getenv("GOPATH")) 129 os.Setenv("GOPATH", workspace) 130 131 defer os.Setenv("GOBIN", os.Getenv("GOBIN")) 132 os.Setenv("GOBIN", "") 133 134 os.Setenv("GOOS", "") 135 os.Setenv("GOHOSTOS", "") 136 os.Setenv("GOARCH", "") 137 os.Setenv("GOHOSTARCH", "") 138 139 // Run Go 1.4 to build binaries. Use -gcflags=-l to disable inlining to 140 // workaround bugs in Go 1.4's compiler. See discussion thread: 141 // https://groups.google.com/d/msg/golang-dev/Ss7mCKsvk8w/Gsq7VYI0AwAJ 142 // Use the math_big_pure_go build tag to disable the assembly in math/big 143 // which may contain unsupported instructions. 144 run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-gcflags=-l", "-tags=math_big_pure_go", "-v", "bootstrap/cmd/...") 145 146 // Copy binaries into tool binary directory. 147 for _, name := range bootstrapDirs { 148 if !strings.HasPrefix(name, "cmd/") { 149 continue 150 } 151 name = name[len("cmd/"):] 152 if !strings.Contains(name, "/") { 153 copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec) 154 } 155 } 156 157 xprintf("\n") 158 } 159 160 func bootstrapFixImports(text, srcFile string) string { 161 lines := strings.SplitAfter(text, "\n") 162 inBlock := false 163 for i, line := range lines { 164 if strings.HasPrefix(line, "import (") { 165 inBlock = true 166 continue 167 } 168 if inBlock && strings.HasPrefix(line, ")") { 169 inBlock = false 170 continue 171 } 172 if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) || 173 inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) { 174 line = strings.Replace(line, `"cmd/`, `"bootstrap/cmd/`, -1) 175 for _, dir := range bootstrapDirs { 176 if strings.HasPrefix(dir, "cmd/") { 177 continue 178 } 179 line = strings.Replace(line, `"`+dir+`"`, `"bootstrap/`+dir+`"`, -1) 180 } 181 lines[i] = line 182 } 183 } 184 185 lines[0] = "// Do not edit. Bootstrap copy of " + srcFile + "\n\n//line " + srcFile + ":1\n" + lines[0] 186 187 return strings.Join(lines, "") 188 }