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