github.com/peggyl/go@v0.0.0-20151008231540-ae315999c2d5/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/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  }