// Copyright 2015 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // Build toolchain using Go 1.4. // // The general strategy is to copy the source files we need into // a new GOPATH workspace, adjust import paths appropriately, // invoke the Go 1.4 go command to build those sources, // and then copy the binaries back. package main import ( "os" "strings" ) // bootstrapDirs is a list of directories holding code that must be // compiled with a Go 1.4 toolchain to produce the bootstrapTargets. // All directories in this list are relative to and must be below $GOROOT/src/cmd. // The list is assumed to have two kinds of entries: names without slashes, // which are commands, and entries beginning with internal/, which are // packages supporting the commands. var bootstrapDirs = []string{ "asm", "asm/internal/arch", "asm/internal/asm", "asm/internal/flags", "asm/internal/lex", "compile", "compile/internal/amd64", "compile/internal/arm", "compile/internal/arm64", "compile/internal/big", "compile/internal/gc", "compile/internal/ppc64", "compile/internal/x86", "internal/gcprog", "internal/obj", "internal/obj/arm", "internal/obj/arm64", "internal/obj/ppc64", "internal/obj/x86", "link", "link/internal/amd64", "link/internal/arm", "link/internal/arm64", "link/internal/ld", "link/internal/ppc64", "link/internal/x86", } func bootstrapBuildTools() { goroot_bootstrap := os.Getenv("GOROOT_BOOTSTRAP") if goroot_bootstrap == "" { goroot_bootstrap = pathf("%s/go1.4", os.Getenv("HOME")) } xprintf("##### Building Go toolchain using %s.\n", goroot_bootstrap) mkzbootstrap(pathf("%s/src/cmd/internal/obj/zbootstrap.go", goroot)) // Use $GOROOT/pkg/bootstrap as the bootstrap workspace root. // We use a subdirectory of $GOROOT/pkg because that's the // space within $GOROOT where we store all generated objects. // We could use a temporary directory outside $GOROOT instead, // but it is easier to debug on failure if the files are in a known location. workspace := pathf("%s/pkg/bootstrap", goroot) xremoveall(workspace) base := pathf("%s/src/bootstrap", workspace) xmkdirall(base) // Copy source code into $GOROOT/pkg/bootstrap and rewrite import paths. for _, dir := range bootstrapDirs { src := pathf("%s/src/cmd/%s", goroot, dir) dst := pathf("%s/%s", base, dir) xmkdirall(dst) for _, name := range xreaddirfiles(src) { srcFile := pathf("%s/%s", src, name) text := readfile(srcFile) text = bootstrapFixImports(text, srcFile) writefile(text, pathf("%s/%s", dst, name), 0) } } // Set up environment for invoking Go 1.4 go command. // GOROOT points at Go 1.4 GOROOT, // GOPATH points at our bootstrap workspace, // GOBIN is empty, so that binaries are installed to GOPATH/bin, // and GOOS, GOHOSTOS, GOARCH, and GOHOSTOS are empty, // so that Go 1.4 builds whatever kind of binary it knows how to build. // Restore GOROOT, GOPATH, and GOBIN when done. // Don't bother with GOOS, GOHOSTOS, GOARCH, and GOHOSTARCH, // because setup will take care of those when bootstrapBuildTools returns. defer os.Setenv("GOROOT", os.Getenv("GOROOT")) os.Setenv("GOROOT", goroot_bootstrap) defer os.Setenv("GOPATH", os.Getenv("GOPATH")) os.Setenv("GOPATH", workspace) defer os.Setenv("GOBIN", os.Getenv("GOBIN")) os.Setenv("GOBIN", "") os.Setenv("GOOS", "") os.Setenv("GOHOSTOS", "") os.Setenv("GOARCH", "") os.Setenv("GOHOSTARCH", "") // Run Go 1.4 to build binaries. run(workspace, ShowOutput|CheckExit, pathf("%s/bin/go", goroot_bootstrap), "install", "-v", "bootstrap/...") // Copy binaries into tool binary directory. for _, name := range bootstrapDirs { if !strings.Contains(name, "/") { copyfile(pathf("%s/%s%s", tooldir, name, exe), pathf("%s/bin/%s%s", workspace, name, exe), writeExec) } } xprintf("\n") } func bootstrapFixImports(text, srcFile string) string { lines := strings.SplitAfter(text, "\n") inBlock := false for i, line := range lines { if strings.HasPrefix(line, "import (") { inBlock = true continue } if inBlock && strings.HasPrefix(line, ")") { inBlock = false continue } if strings.HasPrefix(line, `import "`) || strings.HasPrefix(line, `import . "`) || inBlock && (strings.HasPrefix(line, "\t\"") || strings.HasPrefix(line, "\t. \"")) { lines[i] = strings.Replace(line, `"cmd/`, `"bootstrap/`, -1) } } lines[0] = "// Do not edit. Bootstrap copy of " + srcFile + "\n\n//line " + srcFile + ":1\n" + lines[0] return strings.Join(lines, "") }