github.com/FenixAra/go@v0.0.0-20170127160404-96ea0918e670/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.
    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  }