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