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