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  }