import (
"bufio"
"bytes"
- "cmd/go/internal/str"
"container/heap"
"debug/elf"
"errors"
"strings"
"sync"
"time"
+
+ "cmd/go/internal/cfg"
+ "cmd/go/internal/str"
)
var cmdBuild = &Command{
cmdBuild.Run = runBuild
cmdInstall.Run = runInstall
- cmdBuild.Flag.BoolVar(&buildI, "i", false, "")
- cmdBuild.Flag.StringVar(&buildO, "o", "", "output file")
+ cmdBuild.Flag.BoolVar(&cfg.BuildI, "i", false, "")
+ cmdBuild.Flag.StringVar(&cfg.BuildO, "o", "", "output file")
addBuildFlags(cmdBuild)
addBuildFlags(cmdInstall)
}
-// Flags set by multiple commands.
-var buildA bool // -a flag
-var buildN bool // -n flag
-var buildP = runtime.NumCPU() // -p flag
-var buildV bool // -v flag
-var buildX bool // -x flag
-var buildI bool // -i flag
-var buildO string // -o flag
-var buildWork bool // -work flag
-var buildAsmflags []string // -asmflags flag
-var buildGcflags []string // -gcflags flag
-var buildLdflags []string // -ldflags flag
-var buildGccgoflags []string // -gccgoflags flag
-var buildRace bool // -race flag
-var buildMSan bool // -msan flag
-var buildToolExec []string // -toolexec flag
-var buildBuildmode string // -buildmode flag
-var buildLinkshared bool // -linkshared flag
-var buildPkgdir string // -pkgdir flag
-
-var buildContext = build.Default
+// Note that flags consulted by other parts of the code
+// (for example, buildV) are in cmd/go/internal/cfg.
+
+var buildAsmflags []string // -asmflags flag
+var buildGcflags []string // -gcflags flag
+var buildGccgoflags []string // -gccgoflags flag
+
var buildToolchain toolchain = noToolchain{}
-var buildToolchainName string
-var buildToolchainCompiler string
-var buildToolchainLinker string
var ldBuildmode string
// buildCompiler implements flag.Var.
default:
return fmt.Errorf("unknown compiler %q", value)
}
- buildToolchainName = value
- buildToolchainCompiler = buildToolchain.compiler()
- buildToolchainLinker = buildToolchain.linker()
- buildContext.Compiler = value
+ cfg.BuildToolchainName = value
+ cfg.BuildToolchainCompiler = buildToolchain.compiler()
+ cfg.BuildToolchainLinker = buildToolchain.linker()
+ cfg.BuildContext.Compiler = value
return nil
}
func (c buildCompiler) String() string {
- return buildContext.Compiler
+ return cfg.BuildContext.Compiler
}
func init() {
// addBuildFlags adds the flags common to the build, clean, get,
// install, list, run, and test commands.
func addBuildFlags(cmd *Command) {
- cmd.Flag.BoolVar(&buildA, "a", false, "")
- cmd.Flag.BoolVar(&buildN, "n", false, "")
- cmd.Flag.IntVar(&buildP, "p", buildP, "")
- cmd.Flag.BoolVar(&buildV, "v", false, "")
- cmd.Flag.BoolVar(&buildX, "x", false, "")
+ cmd.Flag.BoolVar(&cfg.BuildA, "a", false, "")
+ cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "")
+ cmd.Flag.IntVar(&cfg.BuildP, "p", cfg.BuildP, "")
+ cmd.Flag.BoolVar(&cfg.BuildV, "v", false, "")
+ cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "")
cmd.Flag.Var((*stringsFlag)(&buildAsmflags), "asmflags", "")
cmd.Flag.Var(buildCompiler{}, "compiler", "")
- cmd.Flag.StringVar(&buildBuildmode, "buildmode", "default", "")
+ cmd.Flag.StringVar(&cfg.BuildBuildmode, "buildmode", "default", "")
cmd.Flag.Var((*stringsFlag)(&buildGcflags), "gcflags", "")
cmd.Flag.Var((*stringsFlag)(&buildGccgoflags), "gccgoflags", "")
- cmd.Flag.StringVar(&buildContext.InstallSuffix, "installsuffix", "", "")
- cmd.Flag.Var((*stringsFlag)(&buildLdflags), "ldflags", "")
- cmd.Flag.BoolVar(&buildLinkshared, "linkshared", false, "")
- cmd.Flag.StringVar(&buildPkgdir, "pkgdir", "", "")
- cmd.Flag.BoolVar(&buildRace, "race", false, "")
- cmd.Flag.BoolVar(&buildMSan, "msan", false, "")
- cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "")
- cmd.Flag.Var((*stringsFlag)(&buildToolExec), "toolexec", "")
- cmd.Flag.BoolVar(&buildWork, "work", false, "")
+ cmd.Flag.StringVar(&cfg.BuildContext.InstallSuffix, "installsuffix", "", "")
+ cmd.Flag.Var((*stringsFlag)(&cfg.BuildLdflags), "ldflags", "")
+ cmd.Flag.BoolVar(&cfg.BuildLinkshared, "linkshared", false, "")
+ cmd.Flag.StringVar(&cfg.BuildPkgdir, "pkgdir", "", "")
+ cmd.Flag.BoolVar(&cfg.BuildRace, "race", false, "")
+ cmd.Flag.BoolVar(&cfg.BuildMSan, "msan", false, "")
+ cmd.Flag.Var((*stringsFlag)(&cfg.BuildContext.BuildTags), "tags", "")
+ cmd.Flag.Var((*stringsFlag)(&cfg.BuildToolexec), "toolexec", "")
+ cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
}
func addBuildFlagsNX(cmd *Command) {
- cmd.Flag.BoolVar(&buildN, "n", false, "")
- cmd.Flag.BoolVar(&buildX, "x", false, "")
+ cmd.Flag.BoolVar(&cfg.BuildN, "n", false, "")
+ cmd.Flag.BoolVar(&cfg.BuildX, "x", false, "")
}
func isSpaceByte(c byte) bool {
var pkgsFilter = func(pkgs []*Package) []*Package { return pkgs }
func buildModeInit() {
- gccgo := buildToolchainName == "gccgo"
+ gccgo := cfg.BuildToolchainName == "gccgo"
var codegenArg string
- platform := goos + "/" + goarch
- switch buildBuildmode {
+ platform := cfg.Goos + "/" + cfg.Goarch
+ switch cfg.BuildBuildmode {
case "archive":
pkgsFilter = pkgsNotMain
case "c-archive":
case "darwin/arm", "darwin/arm64":
codegenArg = "-shared"
default:
- switch goos {
+ switch cfg.Goos {
case "dragonfly", "freebsd", "linux", "netbsd", "openbsd", "solaris":
// Use -shared so that the result is
// suitable for inclusion in a PIE or
codegenArg = "-shared"
}
}
- exeSuffix = ".a"
+ cfg.ExeSuffix = ".a"
ldBuildmode = "c-archive"
case "c-shared":
pkgsFilter = pkgsMain
}
codegenArg = "-dynlink"
}
- if buildO != "" {
+ if cfg.BuildO != "" {
fatalf("-buildmode=shared and -o not supported together")
}
ldBuildmode = "shared"
}
codegenArg = "-dynlink"
}
- exeSuffix = ".so"
+ cfg.ExeSuffix = ".so"
ldBuildmode = "plugin"
default:
- fatalf("buildmode=%s not supported", buildBuildmode)
+ fatalf("buildmode=%s not supported", cfg.BuildBuildmode)
}
- if buildLinkshared {
+ if cfg.BuildLinkshared {
if gccgo {
codegenArg = "-fPIC"
} else {
}
codegenArg = "-dynlink"
// TODO(mwhudson): remove -w when that gets fixed in linker.
- buildLdflags = append(buildLdflags, "-linkshared", "-w")
+ cfg.BuildLdflags = append(cfg.BuildLdflags, "-linkshared", "-w")
}
}
if codegenArg != "" {
buildGcflags = append(buildGcflags, codegenArg)
}
// Don't alter InstallSuffix when modifying default codegen args.
- if buildBuildmode != "default" || buildLinkshared {
- if buildContext.InstallSuffix != "" {
- buildContext.InstallSuffix += "_"
+ if cfg.BuildBuildmode != "default" || cfg.BuildLinkshared {
+ if cfg.BuildContext.InstallSuffix != "" {
+ cfg.BuildContext.InstallSuffix += "_"
}
- buildContext.InstallSuffix += codegenArg[1:]
+ cfg.BuildContext.InstallSuffix += codegenArg[1:]
}
}
}
pkgs := packagesForBuild(args)
- if len(pkgs) == 1 && pkgs[0].Name == "main" && buildO == "" {
- _, buildO = path.Split(pkgs[0].ImportPath)
- buildO += exeSuffix
+ if len(pkgs) == 1 && pkgs[0].Name == "main" && cfg.BuildO == "" {
+ _, cfg.BuildO = path.Split(pkgs[0].ImportPath)
+ cfg.BuildO += cfg.ExeSuffix
}
// Special case -o /dev/null by not writing at all.
- if buildO == os.DevNull {
- buildO = ""
+ if cfg.BuildO == os.DevNull {
+ cfg.BuildO = ""
}
// sanity check some often mis-used options
- switch buildContext.Compiler {
+ switch cfg.BuildContext.Compiler {
case "gccgo":
if len(buildGcflags) != 0 {
fmt.Println("go build: when using gccgo toolchain, please pass compiler flags using -gccgoflags, not -gcflags")
}
- if len(buildLdflags) != 0 {
+ if len(cfg.BuildLdflags) != 0 {
fmt.Println("go build: when using gccgo toolchain, please pass linker flags using -gccgoflags, not -ldflags")
}
case "gc":
}
depMode := modeBuild
- if buildI {
+ if cfg.BuildI {
depMode = modeInstall
}
- if buildO != "" {
+ if cfg.BuildO != "" {
if len(pkgs) > 1 {
fatalf("go build: cannot use -o with multiple packages")
} else if len(pkgs) == 0 {
fatalf("no packages to build")
}
p := pkgs[0]
- p.target = buildO
+ p.target = cfg.BuildO
p.Stale = true // must build - not up to date
p.StaleReason = "build -o flag in use"
a := b.action(modeInstall, depMode, p)
}
var a *action
- if buildBuildmode == "shared" {
+ if cfg.BuildBuildmode == "shared" {
pkgs := pkgsFilter(packages(args))
if libName, err := libname(args, pkgs); err != nil {
fatalf("%s", err.Error())
arg := strings.TrimSuffix(args[0], "/...")
if build.IsLocalImport(arg) {
cwd, _ := os.Getwd()
- bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
+ bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
if bp.ImportPath != "" && bp.ImportPath != "." {
arg = bp.ImportPath
}
// Set the behavior for `go get` to not error on packages with test files only.
b.testFilesOnlyOK = forGet
var a *action
- if buildBuildmode == "shared" {
+ if cfg.BuildBuildmode == "shared" {
if libName, err := libname(args, pkgs); err != nil {
fatalf("%s", err.Error())
} else {
// Compute file 'go build' would have created.
// If it exists and is an executable file, remove it.
_, targ := filepath.Split(pkgs[0].ImportPath)
- targ += exeSuffix
+ targ += cfg.ExeSuffix
if filepath.Join(pkgs[0].Dir, targ) != pkgs[0].Target { // maybe $GOBIN is the current directory
fi, err := os.Stat(targ)
if err == nil {
m := fi.Mode()
if m.IsRegular() {
- if m&0111 != 0 || goos == "windows" { // windows never sets executable bit
+ if m&0111 != 0 || cfg.Goos == "windows" { // windows never sets executable bit
os.Remove(targ)
}
}
}
}
-// Global build parameters (used during package load)
-var (
- goarch string
- goos string
- exeSuffix string
- gopath []string
-)
-
func init() {
- goarch = buildContext.GOARCH
- goos = buildContext.GOOS
+ cfg.Goarch = cfg.BuildContext.GOARCH
+ cfg.Goos = cfg.BuildContext.GOOS
- if goos == "windows" {
- exeSuffix = ".exe"
+ if cfg.Goos == "windows" {
+ cfg.ExeSuffix = ".exe"
}
- gopath = filepath.SplitList(buildContext.GOPATH)
+ cfg.Gopath = filepath.SplitList(cfg.BuildContext.GOPATH)
}
// A builder holds global state about a build.
b.actionCache = make(map[cacheKey]*action)
b.mkdirCache = make(map[string]bool)
- if buildN {
+ if cfg.BuildN {
b.work = "$WORK"
} else {
b.work, err = ioutil.TempDir("", "go-build")
if err != nil {
fatalf("%s", err)
}
- if buildX || buildWork {
+ if cfg.BuildX || cfg.BuildWork {
fmt.Fprintf(os.Stderr, "WORK=%s\n", b.work)
}
- if !buildWork {
+ if !cfg.BuildWork {
workdir := b.work
atexit(func() { os.RemoveAll(workdir) })
}
}
var stk importStack
- ctxt := buildContext
+ ctxt := cfg.BuildContext
ctxt.UseAllFiles = true
// Synthesize fake "directory" that only shows the named files,
if pkg.Name == "main" {
_, elem := filepath.Split(gofiles[0])
- exe := elem[:len(elem)-len(".go")] + exeSuffix
- if buildO == "" {
- buildO = exe
+ exe := elem[:len(elem)-len(".go")] + cfg.ExeSuffix
+ if cfg.BuildO == "" {
+ cfg.BuildO = exe
}
if gobin != "" {
pkg.target = filepath.Join(gobin, exe)
// .go_export section.
func readpkglist(shlibpath string) (pkgs []*Package) {
var stk importStack
- if buildToolchainName == "gccgo" {
+ if cfg.BuildToolchainName == "gccgo" {
f, _ := elf.Open(shlibpath)
sect := f.Section(".go_export")
data, _ := sect.Data()
// p is not part of a shared library.
// If p1 is in a shared library, put the action for that into
// a.deps, otherwise put the action for p1 into a.deps.
- a.deps = append(a.deps, b.action1(depMode, depMode, p1, buildLinkshared, p1.Shlib))
+ a.deps = append(a.deps, b.action1(depMode, depMode, p1, cfg.BuildLinkshared, p1.Shlib))
}
}
// using cgo, to make sure we do not overwrite the binary while
// a package is using it. If this is a cross-build, then the cgo we
// are writing is not the cgo we need to use.
- if goos == runtime.GOOS && goarch == runtime.GOARCH && !buildRace && !buildMSan {
- if (len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo") && !buildLinkshared && buildBuildmode != "shared" {
+ if cfg.Goos == runtime.GOOS && cfg.Goarch == runtime.GOARCH && !cfg.BuildRace && !cfg.BuildMSan {
+ if (len(p.CgoFiles) > 0 || p.Standard && p.ImportPath == "runtime/cgo") && !cfg.BuildLinkshared && cfg.BuildBuildmode != "shared" {
var stk importStack
p1 := loadPackage("cmd/cgo", &stk)
if p1.Error != nil {
return a
}
// gccgo standard library is "fake" too.
- if buildToolchainName == "gccgo" {
+ if cfg.BuildToolchainName == "gccgo" {
// the target name is needed for cgo.
a.target = p.target
return a
a.target = a.p.target
// Install header for cgo in c-archive and c-shared modes.
- if p.usesCgo() && (buildBuildmode == "c-archive" || buildBuildmode == "c-shared") {
+ if p.usesCgo() && (cfg.BuildBuildmode == "c-archive" || cfg.BuildBuildmode == "c-shared") {
hdrTarget := a.target[:len(a.target)-len(filepath.Ext(a.target))] + ".h"
- if buildContext.Compiler == "gccgo" {
+ if cfg.BuildContext.Compiler == "gccgo" {
// For the header file, remove the "lib"
// added by go/build, so we generate pkg.h
// rather than libpkg.h.
name := "a.out"
if p.exeName != "" {
name = p.exeName
- } else if goos == "darwin" && buildBuildmode == "c-shared" && p.target != "" {
+ } else if cfg.Goos == "darwin" && cfg.BuildBuildmode == "c-shared" && p.target != "" {
// On OS X, the linker output name gets recorded in the
// shared library's LC_ID_DYLIB load command.
// The code invoking the linker knows to pass only the final
// we'll install it as; otherwise the library is only loadable as "a.out".
_, name = filepath.Split(p.target)
}
- a.target = a.objdir + filepath.Join("exe", name) + exeSuffix
+ a.target = a.objdir + filepath.Join("exe", name) + cfg.ExeSuffix
}
}
// external linking mode forces an import of runtime/cgo (and
// math on arm). So if it was not passed on the command line and
// it is not present in another shared library, add it here.
- gccgo := buildToolchainName == "gccgo"
+ gccgo := cfg.BuildToolchainName == "gccgo"
if !gccgo {
seencgo := false
for _, p := range pkgs {
pkgs = append(pkgs, p)
}
}
- if goarch == "arm" {
+ if cfg.Goarch == "arm" {
seenmath := false
for _, p := range pkgs {
seenmath = seenmath || (p.Standard && p.ImportPath == "math")
// do runs the action graph rooted at root.
func (b *builder) do(root *action) {
- if _, ok := osArchSupportsCgo[goos+"/"+goarch]; !ok && buildContext.Compiler == "gc" {
- fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", goos, goarch)
+ if _, ok := osArchSupportsCgo[cfg.Goos+"/"+cfg.Goarch]; !ok && cfg.BuildContext.Compiler == "gc" {
+ fmt.Fprintf(os.Stderr, "cmd/go: unsupported GOOS/GOARCH pair %s/%s\n", cfg.Goos, cfg.Goarch)
os.Exit(2)
}
// If we are using the -n flag (just printing commands)
// drop the parallelism to 1, both to make the output
// deterministic and because there is no real work anyway.
- par := buildP
- if buildN {
+ par := cfg.BuildP
+ if cfg.BuildN {
par = 1
}
for i := 0; i < par; i++ {
err = fmt.Errorf("go build %s: %v", a.p.ImportPath, err)
}
}()
- if buildN {
+ if cfg.BuildN {
// In -n mode, print a banner between packages.
// The banner is five lines so that when changes to
// different sections of the bootstrap script have to
b.print("\n#\n# " + a.p.ImportPath + "\n#\n\n")
}
- if buildV {
+ if cfg.BuildV {
b.print(a.p.ImportPath + "\n")
}
if err != nil {
return err
}
- if buildToolchainName == "gccgo" {
+ if cfg.BuildToolchainName == "gccgo" {
cgoObjects = append(cgoObjects, filepath.Join(a.objdir, "_cgo_flags"))
}
cgoObjects = append(cgoObjects, outObj...)
// Copy .h files named for goos or goarch or goos_goarch
// to names using GOOS and GOARCH.
// For example, defs_linux_amd64.h becomes defs_GOOS_GOARCH.h.
- _goos_goarch := "_" + goos + "_" + goarch
- _goos := "_" + goos
- _goarch := "_" + goarch
+ _goos_goarch := "_" + cfg.Goos + "_" + cfg.Goarch
+ _goos := "_" + cfg.Goos
+ _goarch := "_" + cfg.Goarch
for _, file := range a.p.HFiles {
name, ext := fileExtSplit(file)
switch {
if err != nil {
return err
}
- if buildX {
+ if cfg.BuildX {
b.showcmd("", "echo '%s' > %s # internal", filepath.Base(a1.target), a.target)
}
return nil
a1 := a.deps[0]
perm := os.FileMode(0666)
if a1.link {
- switch buildBuildmode {
+ switch cfg.BuildBuildmode {
case "c-archive", "c-shared", "plugin":
default:
perm = 0777
// garbage down in a large build. On an operating system
// with aggressive buffering, cleaning incrementally like
// this keeps the intermediate objects from hitting the disk.
- if !buildWork {
+ if !cfg.BuildWork {
defer os.RemoveAll(a1.objdir)
defer os.Remove(a1.target)
}
need[a1.p.build.Root] = a1.p.build
}
}
- for _, root := range gopath {
+ for _, root := range cfg.Gopath {
if p := need[root]; p != nil && !incMap[p.PkgRoot] {
incMap[p.PkgRoot] = true
inc = append(inc, flag, p.PkgTargetRoot)
// moveOrCopyFile is like 'mv src dst' or 'cp src dst'.
func (b *builder) moveOrCopyFile(a *action, dst, src string, perm os.FileMode, force bool) error {
- if buildN {
+ if cfg.BuildN {
b.showcmd("", "mv %s %s", src, dst)
return nil
}
if err := os.Chmod(src, mode); err == nil {
if err := os.Rename(src, dst); err == nil {
- if buildX {
+ if cfg.BuildX {
b.showcmd("", "mv %s %s", src, dst)
}
return nil
// copyFile is like 'cp src dst'.
func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode, force bool) error {
- if buildN || buildX {
+ if cfg.BuildN || cfg.BuildX {
b.showcmd("", "cp %s %s", src, dst)
- if buildN {
+ if cfg.BuildN {
return nil
}
}
// go tool cover -mode=b.coverMode -var="varName" -o dst.go src.go
func (b *builder) cover(a *action, dst, src string, perm os.FileMode, varName string) error {
return b.run(a.objdir, "cover "+a.p.ImportPath, nil,
- buildToolExec,
+ cfg.BuildToolexec,
tool("cover"),
"-mode", a.p.coverMode,
"-var", varName,
// Replace x.go:19[/tmp/.../x.cgo1.go:18] with x.go:19.
// Replace *[100]_Ctype_foo with *[100]C.foo.
// If we're using -x, assume we're debugging and want the full dump, so disable the rewrite.
- if !buildX && cgoLine.MatchString(messages) {
+ if !cfg.BuildX && cgoLine.MatchString(messages) {
messages = cgoLine.ReplaceAllString(messages, "")
messages = cgoTypeSigRe.ReplaceAllString(messages, "C.")
}
// It returns the command output and any errors that occurred.
func (b *builder) runOut(dir string, desc string, env []string, cmdargs ...interface{}) ([]byte, error) {
cmdline := str.StringList(cmdargs...)
- if buildN || buildX {
+ if cfg.BuildN || cfg.BuildX {
var envcmdline string
for i := range env {
envcmdline += env[i]
}
envcmdline += joinUnambiguously(cmdline)
b.showcmd(dir, "%s", envcmdline)
- if buildN {
+ if cfg.BuildN {
return nil, nil
}
}
}
b.mkdirCache[dir] = true
- if buildN || buildX {
+ if cfg.BuildN || cfg.BuildX {
b.showcmd("", "mkdir -p %s", dir)
- if buildN {
+ if cfg.BuildN {
return nil
}
}
type noToolchain struct{}
func noCompiler() error {
- log.Fatalf("unknown compiler %q", buildContext.Compiler)
+ log.Fatalf("unknown compiler %q", cfg.BuildContext.Compiler)
return nil
}
if extFiles == 0 {
gcargs = append(gcargs, "-complete")
}
- if buildContext.InstallSuffix != "" {
- gcargs = append(gcargs, "-installsuffix", buildContext.InstallSuffix)
+ if cfg.BuildContext.InstallSuffix != "" {
+ gcargs = append(gcargs, "-installsuffix", cfg.BuildContext.InstallSuffix)
}
if p.buildID != "" {
gcargs = append(gcargs, "-buildid", p.buildID)
}
}
- args := []interface{}{buildToolExec, tool("compile"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs}
+ args := []interface{}{cfg.BuildToolexec, tool("compile"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs}
if ofile == archive {
args = append(args, "-pack")
}
func (gcToolchain) asm(b *builder, p *Package, obj string, sfiles []string) ([]string, error) {
// Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files.
inc := filepath.Join(goroot, "pkg", "include")
- args := []interface{}{buildToolExec, tool("asm"), "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch, buildAsmflags}
- if p.ImportPath == "runtime" && goarch == "386" {
+ args := []interface{}{cfg.BuildToolexec, tool("asm"), "-trimpath", b.work, "-I", obj, "-I", inc, "-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch, buildAsmflags}
+ if p.ImportPath == "runtime" && cfg.Goarch == "386" {
for _, arg := range buildAsmflags {
if arg == "-dynlink" {
args = append(args, "-D=GOBUILDMODE_shared=1")
// The archive file should have been created by the compiler.
// Since it used to not work that way, verify.
- if !buildN {
+ if !cfg.BuildN {
if _, err := os.Stat(absAfile); err != nil {
fatalf("os.Stat of archive file failed: %v", err)
}
}
- if buildN || buildX {
+ if cfg.BuildN || cfg.BuildX {
cmdline := str.StringList("pack", "r", absAfile, absOfiles)
b.showcmd(p.Dir, "%s # internal", joinUnambiguously(cmdline))
}
- if buildN {
+ if cfg.BuildN {
return nil
}
if err := packInternal(b, absAfile, absOfiles); err != nil {
}
}
var ldflags []string
- if buildContext.InstallSuffix != "" {
- ldflags = append(ldflags, "-installsuffix", buildContext.InstallSuffix)
+ if cfg.BuildContext.InstallSuffix != "" {
+ ldflags = append(ldflags, "-installsuffix", cfg.BuildContext.InstallSuffix)
}
if root.p.omitDWARF {
ldflags = append(ldflags, "-w")
}
- if buildBuildmode == "plugin" {
+ if cfg.BuildBuildmode == "plugin" {
pluginpath := root.p.ImportPath
if pluginpath == "command-line-arguments" {
pluginpath = "plugin/unnamed-" + root.p.buildID
if root.p.buildID != "" {
ldflags = append(ldflags, "-buildid="+root.p.buildID)
}
- ldflags = append(ldflags, buildLdflags...)
+ ldflags = append(ldflags, cfg.BuildLdflags...)
// On OS X when using external linking to build a shared library,
// the argument passed here to -o ends up recorded in the final
// run the link in the output directory so that -o can name
// just the final path element.
dir := "."
- if goos == "darwin" && buildBuildmode == "c-shared" {
+ if cfg.Goos == "darwin" && cfg.BuildBuildmode == "c-shared" {
dir, out = filepath.Split(out)
}
- return b.run(dir, root.p.ImportPath, nil, buildToolExec, tool("link"), "-o", out, importArgs, ldflags, mainpkg)
+ return b.run(dir, root.p.ImportPath, nil, cfg.BuildToolexec, tool("link"), "-o", out, importArgs, ldflags, mainpkg)
}
func (gcToolchain) ldShared(b *builder, toplevelactions []*action, out string, allactions []*action) error {
importArgs := b.includeArgs("-L", allactions)
- ldflags := []string{"-installsuffix", buildContext.InstallSuffix}
+ ldflags := []string{"-installsuffix", cfg.BuildContext.InstallSuffix}
ldflags = append(ldflags, "-buildmode=shared")
- ldflags = append(ldflags, buildLdflags...)
+ ldflags = append(ldflags, cfg.BuildLdflags...)
cxx := false
for _, a := range allactions {
if a.p != nil && (len(a.p.CXXFiles) > 0 || len(a.p.SwigCXXFiles) > 0) {
}
ldflags = append(ldflags, d.p.ImportPath+"="+d.target)
}
- return b.run(".", out, nil, buildToolExec, tool("link"), "-o", out, importArgs, ldflags)
+ return b.run(".", out, nil, cfg.BuildToolexec, tool("link"), "-o", out, importArgs, ldflags)
}
func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
ofile := obj + sfile[:len(sfile)-len(".s")] + ".o"
ofiles = append(ofiles, ofile)
sfile = mkAbs(p.Dir, sfile)
- defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
+ defs := []string{"-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch}
if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
defs = append(defs, `-D`, `GOPKGPATH=`+pkgpath)
}
var realOut string
switch buildmode {
case "exe":
- if usesCgo && goos == "linux" {
+ if usesCgo && cfg.Goos == "linux" {
ldflags = append(ldflags, "-Wl,-E")
}
func (tools gccgoToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error {
inc := filepath.Join(goroot, "pkg", "include")
cfile = mkAbs(p.Dir, cfile)
- defs := []string{"-D", "GOOS_" + goos, "-D", "GOARCH_" + goarch}
+ defs := []string{"-D", "GOOS_" + cfg.Goos, "-D", "GOARCH_" + cfg.Goarch}
defs = append(defs, b.gccArchArgs()...)
if pkgpath := gccgoCleanPkgpath(p); pkgpath != "" {
defs = append(defs, `-D`, `GOPKGPATH="`+pkgpath+`"`)
}
- switch goarch {
+ switch cfg.Goarch {
case "386", "amd64":
defs = append(defs, "-fsplit-stack")
}
// maybePIC adds -fPIC to the list of arguments if needed.
func (tools gccgoToolchain) maybePIC(args []string) []string {
- switch buildBuildmode {
+ switch cfg.BuildBuildmode {
case "c-shared", "shared", "plugin":
args = append(args, "-fPIC")
}
// Definitely want -fPIC but on Windows gcc complains
// "-fPIC ignored for target (all code is position independent)"
- if goos != "windows" {
+ if cfg.Goos != "windows" {
a = append(a, "-fPIC")
}
a = append(a, b.gccArchArgs()...)
// gcc-4.5 and beyond require explicit "-pthread" flag
// for multithreading with pthread library.
- if buildContext.CgoEnabled {
- switch goos {
+ if cfg.BuildContext.CgoEnabled {
+ switch cfg.Goos {
case "windows":
a = append(a, "-mthreads")
default:
// On OS X, some of the compilers behave as if -fno-common
// is always set, and the Mach-O linker in 6l/8l assumes this.
// See https://golang.org/issue/3253.
- if goos == "darwin" {
+ if cfg.Goos == "darwin" {
a = append(a, "-fno-common")
}
b.flagCache = make(map[string]bool)
}
cmdArgs := append(envList("CC", defaultCC), flag, "-c", "trivial.c")
- if buildN || buildX {
+ if cfg.BuildN || cfg.BuildX {
b.showcmd(b.work, "%s", joinUnambiguously(cmdArgs))
- if buildN {
+ if cfg.BuildN {
return false
}
}
// gccArchArgs returns arguments to pass to gcc based on the architecture.
func (b *builder) gccArchArgs() []string {
- switch goarch {
+ switch cfg.Goarch {
case "386":
return []string{"-m32"}
case "amd64", "amd64p32":
}
}
- if buildMSan {
+ if cfg.BuildMSan {
cgoCFLAGS = append([]string{"-fsanitize=memory"}, cgoCFLAGS...)
cgoLDFLAGS = append([]string{"-fsanitize=memory"}, cgoLDFLAGS...)
}
cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
}
- if buildToolchainName == "gccgo" {
- switch goarch {
+ if cfg.BuildToolchainName == "gccgo" {
+ switch cfg.Goarch {
case "386", "amd64":
cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack")
}
}
}
- switch buildBuildmode {
+ switch cfg.BuildBuildmode {
case "c-archive", "c-shared":
// Tell cgo that if there are any exported functions
// it should generate a header file that C code can
cgoflags = append(cgoflags, "-exportheader="+obj+"_cgo_install.h")
}
- if err := b.run(p.Dir, p.ImportPath, cgoenv, buildToolExec, cgoExe, srcdirarg, "-objdir", obj, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
+ if err := b.run(p.Dir, p.ImportPath, cgoenv, cfg.BuildToolexec, cgoExe, srcdirarg, "-objdir", obj, "-importpath", p.ImportPath, cgoflags, "--", cgoCPPFLAGS, cgoCFLAGS, cgofiles); err != nil {
return nil, nil, err
}
outGo = append(outGo, gofiles...)
outObj = append(outObj, ofile)
}
- switch buildToolchainName {
+ switch cfg.BuildToolchainName {
case "gc":
importGo := obj + "_cgo_import.go"
if err := b.dynimport(p, obj, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil {
// we need to use -pie for Linux/ARM to get accurate imported sym
ldflags := cgoLDFLAGS
- if (goarch == "arm" && goos == "linux") || goos == "android" {
+ if (cfg.Goarch == "arm" && cfg.Goos == "linux") || cfg.Goos == "android" {
ldflags = append(ldflags, "-pie")
}
if err := b.gccld(p, dynobj, ldflags, linkobj); err != nil {
if p.Standard && p.ImportPath == "runtime/cgo" {
cgoflags = []string{"-dynlinker"} // record path to dynamic linker
}
- return b.run(p.Dir, p.ImportPath, nil, buildToolExec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
+ return b.run(p.Dir, p.ImportPath, nil, cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
}
// collect partially links the object files outObj into a single
i++
}
// skip "-framework X" on Darwin
- case goos == "darwin" && f == "-framework":
+ case cfg.Goos == "darwin" && f == "-framework":
i++
// skip "*.{dylib,so,dll,o,a}"
case strings.HasSuffix(f, ".dylib"),
// Determine the size of int on the target system for the -intgosize option
// of swig >= 2.0.9. Run only once.
func (b *builder) swigDoIntSize(obj string) (intsize string, err error) {
- if buildN {
+ if cfg.BuildN {
return "$INTBITS", nil
}
src := filepath.Join(b.work, "swig_intsize.go")
gccExt = "cxx"
}
- gccgo := buildToolchainName == "gccgo"
+ gccgo := cfg.BuildToolchainName == "gccgo"
// swig
args := []string{
// do, but only on systems likely to support it, which is to say,
// systems that normally use gold or the GNU linker.
func (b *builder) disableBuildID(ldflags []string) []string {
- switch goos {
+ switch cfg.Goos {
case "android", "dragonfly", "linux", "netbsd":
ldflags = append(ldflags, "-Wl,--build-id=none")
}
}
func instrumentInit() {
- if !buildRace && !buildMSan {
+ if !cfg.BuildRace && !cfg.BuildMSan {
return
}
- if buildRace && buildMSan {
+ if cfg.BuildRace && cfg.BuildMSan {
fmt.Fprintf(os.Stderr, "go %s: may not use -race and -msan simultaneously\n", flag.Args()[0])
os.Exit(2)
}
- if buildMSan && (goos != "linux" || goarch != "amd64") {
- fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", goos, goarch)
+ if cfg.BuildMSan && (cfg.Goos != "linux" || cfg.Goarch != "amd64") {
+ fmt.Fprintf(os.Stderr, "-msan is not supported on %s/%s\n", cfg.Goos, cfg.Goarch)
os.Exit(2)
}
- if goarch != "amd64" || goos != "linux" && goos != "freebsd" && goos != "darwin" && goos != "windows" {
+ if cfg.Goarch != "amd64" || cfg.Goos != "linux" && cfg.Goos != "freebsd" && cfg.Goos != "darwin" && cfg.Goos != "windows" {
fmt.Fprintf(os.Stderr, "go %s: -race and -msan are only supported on linux/amd64, freebsd/amd64, darwin/amd64 and windows/amd64\n", flag.Args()[0])
os.Exit(2)
}
- if !buildContext.CgoEnabled {
+ if !cfg.BuildContext.CgoEnabled {
fmt.Fprintf(os.Stderr, "go %s: -race requires cgo; enable cgo by setting CGO_ENABLED=1\n", flag.Args()[0])
os.Exit(2)
}
- if buildRace {
+ if cfg.BuildRace {
buildGcflags = append(buildGcflags, "-race")
- buildLdflags = append(buildLdflags, "-race")
+ cfg.BuildLdflags = append(cfg.BuildLdflags, "-race")
} else {
buildGcflags = append(buildGcflags, "-msan")
- buildLdflags = append(buildLdflags, "-msan")
+ cfg.BuildLdflags = append(cfg.BuildLdflags, "-msan")
}
- if buildContext.InstallSuffix != "" {
- buildContext.InstallSuffix += "_"
+ if cfg.BuildContext.InstallSuffix != "" {
+ cfg.BuildContext.InstallSuffix += "_"
}
- if buildRace {
- buildContext.InstallSuffix += "race"
- buildContext.BuildTags = append(buildContext.BuildTags, "race")
+ if cfg.BuildRace {
+ cfg.BuildContext.InstallSuffix += "race"
+ cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "race")
} else {
- buildContext.InstallSuffix += "msan"
- buildContext.BuildTags = append(buildContext.BuildTags, "msan")
+ cfg.BuildContext.InstallSuffix += "msan"
+ cfg.BuildContext.BuildTags = append(cfg.BuildContext.BuildTags, "msan")
}
}
import (
"bytes"
+ "cmd/go/internal/cfg"
"cmd/go/internal/str"
"crypto/sha1"
"errors"
func (p *Package) copyBuild(pp *build.Package) {
p.build = pp
- if pp.PkgTargetRoot != "" && buildPkgdir != "" {
+ if pp.PkgTargetRoot != "" && cfg.BuildPkgdir != "" {
old := pp.PkgTargetRoot
- pp.PkgRoot = buildPkgdir
- pp.PkgTargetRoot = buildPkgdir
- pp.PkgObj = filepath.Join(buildPkgdir, strings.TrimPrefix(pp.PkgObj, old))
+ pp.PkgRoot = cfg.BuildPkgdir
+ pp.PkgTargetRoot = cfg.BuildPkgdir
+ pp.PkgObj = filepath.Join(cfg.BuildPkgdir, strings.TrimPrefix(pp.PkgObj, old))
}
p.Dir = pp.Dir
// Not vendoring, or we already found the vendored path.
buildMode |= build.IgnoreVendor
}
- bp, err := buildContext.Import(path, srcDir, buildMode)
+ bp, err := cfg.BuildContext.Import(path, srcDir, buildMode)
bp.ImportPath = importPath
if gobin != "" {
bp.BinDir = gobin
}
// We can't check standard packages with gccgo.
- if buildContext.Compiler == "gccgo" && p.Standard {
+ if cfg.BuildContext.Compiler == "gccgo" && p.Standard {
return p
}
useBindir := p.Name == "main"
if !p.Standard {
- switch buildBuildmode {
+ switch cfg.BuildBuildmode {
case "c-archive", "c-shared", "plugin":
useBindir = false
}
return p
}
_, elem := filepath.Split(p.Dir)
- full := buildContext.GOOS + "_" + buildContext.GOARCH + "/" + elem
- if buildContext.GOOS != toolGOOS || buildContext.GOARCH != toolGOARCH {
+ full := cfg.BuildContext.GOOS + "_" + cfg.BuildContext.GOARCH + "/" + elem
+ if cfg.BuildContext.GOOS != toolGOOS || cfg.BuildContext.GOARCH != toolGOARCH {
// Install cross-compiled binaries to subdirectories of bin.
elem = full
}
// Override all the usual logic and force it into the tool directory.
p.target = filepath.Join(gorootPkg, "tool", full)
}
- if p.target != "" && buildContext.GOOS == "windows" {
+ if p.target != "" && cfg.BuildContext.GOOS == "windows" {
p.target += ".exe"
}
} else if p.local {
p.target = ""
} else {
p.target = p.build.PkgObj
- if buildLinkshared {
+ if cfg.BuildLinkshared {
shlibnamefile := p.target[:len(p.target)-2] + ".shlibname"
shlib, err := ioutil.ReadFile(shlibnamefile)
if err == nil {
libname := strings.TrimSpace(string(shlib))
- if buildContext.Compiler == "gccgo" {
+ if cfg.BuildContext.Compiler == "gccgo" {
p.Shlib = filepath.Join(p.build.PkgTargetRoot, "shlibs", libname)
} else {
p.Shlib = filepath.Join(p.build.PkgTargetRoot, libname)
importPaths = append(importPaths, "syscall")
}
- if buildContext.CgoEnabled && p.Name == "main" && !p.Goroot {
+ if cfg.BuildContext.CgoEnabled && p.Name == "main" && !p.Goroot {
// Currently build modes c-shared, pie (on systems that do not
// support PIE with internal linking mode), plugin, and
// -linkshared force external linking mode, as of course does
// -ldflags=-linkmode=external. External linking mode forces
// an import of runtime/cgo.
- pieCgo := buildBuildmode == "pie" && (buildContext.GOOS != "linux" || buildContext.GOARCH != "amd64")
+ pieCgo := cfg.BuildBuildmode == "pie" && (cfg.BuildContext.GOOS != "linux" || cfg.BuildContext.GOARCH != "amd64")
linkmodeExternal := false
- for i, a := range buildLdflags {
+ for i, a := range cfg.BuildLdflags {
if a == "-linkmode=external" {
linkmodeExternal = true
}
- if a == "-linkmode" && i+1 < len(buildLdflags) && buildLdflags[i+1] == "external" {
+ if a == "-linkmode" && i+1 < len(cfg.BuildLdflags) && cfg.BuildLdflags[i+1] == "external" {
linkmodeExternal = true
}
}
- if buildBuildmode == "c-shared" || buildBuildmode == "plugin" || pieCgo || buildLinkshared || linkmodeExternal {
+ if cfg.BuildBuildmode == "c-shared" || cfg.BuildBuildmode == "plugin" || pieCgo || cfg.BuildLinkshared || linkmodeExternal {
importPaths = append(importPaths, "runtime/cgo")
}
}
importPaths = append(importPaths, "runtime")
// When race detection enabled everything depends on runtime/race.
// Exclude certain packages to avoid circular dependencies.
- if buildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
+ if cfg.BuildRace && (!p.Standard || !raceExclude[p.ImportPath]) {
importPaths = append(importPaths, "runtime/race")
}
// MSan uses runtime/msan.
- if buildMSan && (!p.Standard || !raceExclude[p.ImportPath]) {
+ if cfg.BuildMSan && (!p.Standard || !raceExclude[p.ImportPath]) {
importPaths = append(importPaths, "runtime/msan")
}
// On ARM with GOARM=5, everything depends on math for the link.
- if p.Name == "main" && goarch == "arm" {
+ if p.Name == "main" && cfg.Goarch == "arm" {
importPaths = append(importPaths, "math")
}
// In coverage atomic mode everything depends on sync/atomic.
- if testCoverMode == "atomic" && (!p.Standard || (p.ImportPath != "runtime/cgo" && p.ImportPath != "runtime/race" && p.ImportPath != "sync/atomic")) {
+ if cfg.TestCoverMode == "atomic" && (!p.Standard || (p.ImportPath != "runtime/cgo" && p.ImportPath != "runtime/race" && p.ImportPath != "sync/atomic")) {
importPaths = append(importPaths, "sync/atomic")
}
}
}
// unsafe is a fake package.
- if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
+ if p.Standard && (p.ImportPath == "unsafe" || cfg.BuildContext.Compiler == "gccgo") {
p.target = ""
}
p.Target = p.target
// If cgo is not enabled, ignore cgo supporting sources
// just as we ignore go files containing import "C".
- if !buildContext.CgoEnabled {
+ if !cfg.BuildContext.CgoEnabled {
p.CFiles = nil
p.CXXFiles = nil
p.MFiles = nil
}
// The gc toolchain only permits C source files with cgo.
- if len(p.CFiles) > 0 && !p.usesCgo() && !p.usesSwig() && buildContext.Compiler == "gc" {
+ if len(p.CFiles) > 0 && !p.usesCgo() && !p.usesSwig() && cfg.BuildContext.Compiler == "gc" {
p.Error = &PackageError{
ImportStack: stk.copy(),
Err: fmt.Sprintf("C source files not allowed when not using cgo or SWIG: %s", strings.Join(p.CFiles, " ")),
// isStale reports whether package p needs to be rebuilt,
// along with the reason why.
func isStale(p *Package) (bool, string) {
- if p.Standard && (p.ImportPath == "unsafe" || buildContext.Compiler == "gccgo") {
+ if p.Standard && (p.ImportPath == "unsafe" || cfg.BuildContext.Compiler == "gccgo") {
// fake, builtin package
return false, "builtin package"
}
}
// If the -a flag is given, rebuild everything.
- if buildA {
+ if cfg.BuildA {
return true, "build -a flag in use"
}
// Excluding $GOROOT used to also fix issue 4106, but that's now
// taken care of above (at least when the installed Go is a released version).
if p.Root != goroot {
- if olderThan(buildToolchainCompiler) {
+ if olderThan(cfg.BuildToolchainCompiler) {
return true, "newer compiler"
}
- if p.build.IsCommand() && olderThan(buildToolchainLinker) {
+ if p.build.IsCommand() && olderThan(cfg.BuildToolchainLinker) {
return true, "newer linker"
}
}
// Include the content of runtime/internal/sys/zversion.go in the hash
// for package runtime. This will give package runtime a
// different build ID in each Go release.
- if p.Standard && p.ImportPath == "runtime/internal/sys" && buildContext.Compiler != "gccgo" {
+ if p.Standard && p.ImportPath == "runtime/internal/sys" && cfg.BuildContext.Compiler != "gccgo" {
data, err := ioutil.ReadFile(filepath.Join(p.Dir, "zversion.go"))
if err != nil {
fatalf("go: %s", err)
stk.push(arg)
defer stk.pop()
- bp, err := buildContext.ImportDir(filepath.Join(gorootSrc, arg), 0)
+ bp, err := cfg.BuildContext.ImportDir(filepath.Join(gorootSrc, arg), 0)
bp.ImportPath = arg
bp.Goroot = true
bp.BinDir = gorootBin
// referring to io/ioutil rather than a hypothetical import of
// "./ioutil".
if build.IsLocalImport(arg) {
- bp, _ := buildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
+ bp, _ := cfg.BuildContext.ImportDir(filepath.Join(cwd, arg), build.FindOnly)
if bp.ImportPath != "" && bp.ImportPath != "." {
arg = bp.ImportPath
}
// It only supports the gc toolchain.
// Other toolchain maintainers should adjust this function.
func readBuildID(name, target string) (id string, err error) {
- if buildToolchainName != "gc" {
+ if cfg.BuildToolchainName != "gc" {
return "", errBuildIDToolchain
}