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