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.
5 // Build toolchain using Go 1.4.
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.
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{
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/ssa",
40 "compile/internal/x86",
49 "link/internal/amd64",
51 "link/internal/arm64",
53 "link/internal/mips64",
54 "link/internal/ppc64",
58 func bootstrapBuildTools() {
59 goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP")
60 if goroot_bootstrap == "" {
61 goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME"))
63 xprintf("##### Building Go toolchain using %s.\n", goroot_bootstrap)
65 mkzbootstrap(pathf("%s/src/cmd/internal/obj/zbootstrap.go", goroot))
67 // Use $GOROOT/pkg/bootstrap as the bootstrap workspace root.
68 // We use a subdirectory of $GOROOT/pkg because that's the
69 // space within $GOROOT where we store all generated objects.
70 // We could use a temporary directory outside $GOROOT instead,
71 // but it is easier to debug on failure if the files are in a known location.
72 workspace := pathf("%s/pkg/bootstrap", goroot)
74 base := pathf("%s/src/bootstrap", workspace)
77 // Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths.
78 for _, dir := range bootstrapDirs {
79 src := pathf("%s/src/cmd/%s", goroot, dir)
80 dst := pathf("%s/%s", base, dir)
82 for _, name := range xreaddirfiles(src) {
83 srcFile := pathf("%s/%s", src, name)
84 text := readfile(srcFile)
85 text = bootstrapFixImports(text, srcFile)
86 writefile(text, pathf("%s/%s", dst, name), 0)
90 // Set up environment for invoking Go 1.4 go command.
91 // GOROOT points at Go 1.4 GOROOT,
92 // GOPATH points at our bootstrap workspace,
93 // GOBIN is empty, so that binaries are installed to GOPATH/bin,
94 // and GOOS, GOHOSTOS, GOARCH, and GOHOSTOS are empty,
95 // so that Go 1.4 builds whatever kind of binary it knows how to build.
96 // Restore GOROOT, GOPATH, and GOBIN when done.
97 // Don't bother with GOOS, GOHOSTOS, GOARCH, and GOHOSTARCH,
98 // because setup will take care of those when bootstrapBuildTools returns.
100 defer os.Setenv("GOROOT", os.Getenv("GOROOT"))
101 os.Setenv("GOROOT", goroot_bootstrap)
103 defer os.Setenv("GOPATH", os.Getenv("GOPATH"))
104 os.Setenv("GOPATH", workspace)
106 defer os.Setenv("GOBIN", os.Getenv("GOBIN"))
107 os.Setenv("GOBIN", "")
109 os.Setenv("GOOS", "")
110 os.Setenv("GOHOSTOS", "")
111 os.Setenv("GOARCH", "")
112 os.Setenv("GOHOSTARCH", "")
114 // Run Go 1.4 to build binaries.
115 run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-v", "bootstrap/...")
117 // Copy binaries into tool binary directory.
118 for _, name := range bootstrapDirs {
119 if !strings.Contains(name, "/") {
120 copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec)
127 func bootstrapFixImports(text, srcFile string) string {
128 lines := strings.SplitAfter(text, "\n")
130 for i, line := range lines {
131 if strings.HasPrefix(line, "import (") {
135 if inBlock && strings.HasPrefix(line, ")") {
139 if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) ||
140 inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) {
141 lines[i] = strings.Replace(line, `"cmd/`, `"bootstrap/`, -1)
145 lines[0] = "// Do not edit. Bootstrap copy of " + srcFile + "\n\n//line " + srcFile + ":1\n" + lines[0]
147 return strings.Join(lines, "")