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