cmdInstall.Run = runInstall
cmdBuild.Flag.BoolVar(&buildI, "i", false, "")
+ cmdBuild.Flag.StringVar(&buildO, "o", "", "output file")
addBuildFlags(cmdBuild)
addBuildFlags(cmdInstall)
var buildV bool // -v flag
var buildX bool // -x flag
var buildI bool // -i flag
-var buildO = cmdBuild.Flag.String("o", "", "output file")
-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 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
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
return nil
}
func init() {
switch build.Default.Compiler {
- case "gc":
- buildToolchain = gcToolchain{}
- case "gccgo":
- buildToolchain = gccgoToolchain{}
+ case "gc", "gccgo":
+ buildCompiler{}.Set(build.Default.Compiler)
}
}
var pkgsFilter = func(pkgs []*Package) []*Package { return pkgs }
func buildModeInit() {
- _, gccgo := buildToolchain.(gccgoToolchain)
+ gccgo := buildToolchainName == "gccgo"
var codegenArg string
platform := goos + "/" + goarch
switch buildBuildmode {
}
codegenArg = "-dynlink"
}
- if *buildO != "" {
+ if buildO != "" {
fatalf("-buildmode=shared and -o not supported together")
}
ldBuildmode = "shared"
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" && buildO == "" {
+ _, buildO = path.Split(pkgs[0].ImportPath)
+ buildO += exeSuffix
}
// Special case -o /dev/null by not writing at all.
- if *buildO == os.DevNull {
- *buildO = ""
+ if buildO == os.DevNull {
+ buildO = ""
}
// sanity check some often mis-used options
depMode = modeInstall
}
- if *buildO != "" {
+ if 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 = buildO
p.Stale = true // must build - not up to date
p.StaleReason = "build -o flag in use"
a := b.action(modeInstall, depMode, p)
if pkg.Name == "main" {
_, elem := filepath.Split(gofiles[0])
exe := elem[:len(elem)-len(".go")] + exeSuffix
- if *buildO == "" {
- *buildO = exe
+ if buildO == "" {
+ buildO = exe
}
if gobin != "" {
pkg.target = filepath.Join(gobin, exe)
// .go_export section.
func readpkglist(shlibpath string) (pkgs []*Package) {
var stk importStack
- if _, gccgo := buildToolchain.(gccgoToolchain); gccgo {
+ if buildToolchainName == "gccgo" {
f, _ := elf.Open(shlibpath)
sect := f.Section(".go_export")
data, _ := sect.Data()
return a
}
// gccgo standard library is "fake" too.
- if _, ok := buildToolchain.(gccgoToolchain); ok {
+ if buildToolchainName == "gccgo" {
// the target name is needed for cgo.
a.target = p.target
return a
// 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 := buildToolchain.(gccgoToolchain)
+ gccgo := buildToolchainName == "gccgo"
if !gccgo {
seencgo := false
for _, p := range pkgs {
if err != nil {
return err
}
- if _, ok := buildToolchain.(gccgoToolchain); ok {
+ if buildToolchainName == "gccgo" {
cgoObjects = append(cgoObjects, filepath.Join(a.objdir, "_cgo_flags"))
}
cgoObjects = append(cgoObjects, outObj...)
cgoenv = []string{"CGO_LDFLAGS=" + strings.Join(flags, " ")}
}
- if _, ok := buildToolchain.(gccgoToolchain); ok {
+ if buildToolchainName == "gccgo" {
switch goarch {
case "386", "amd64":
cgoCFLAGS = append(cgoCFLAGS, "-fsplit-stack")
outObj = append(outObj, ofile)
}
- switch buildToolchain.(type) {
- case gcToolchain:
+ switch buildToolchainName {
+ case "gc":
importGo := obj + "_cgo_import.go"
if err := b.dynimport(p, obj, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil {
return nil, nil, err
}
outObj = []string{ofile}
- case gccgoToolchain:
+ case "gccgo":
defunC := obj + "_cgo_defun.c"
defunObj := obj + "_cgo_defun.o"
if err := buildToolchain.cc(b, p, obj, defunObj, defunC); err != nil {
gccExt = "cxx"
}
- _, gccgo := buildToolchain.(gccgoToolchain)
+ gccgo := buildToolchainName == "gccgo"
// swig
args := []string{
// Commands lists the available commands and help topics.
// The order here is the order in which they are printed by 'go help'.
-var commands = []*Command{
- cmdBuild,
- cmdClean,
- cmdDoc,
- cmdEnv,
- cmdBug,
- cmdFix,
- cmdFmt,
- cmdGenerate,
- cmdGet,
- cmdInstall,
- cmdList,
- cmdRun,
- cmdTest,
- cmdTool,
- cmdVersion,
- cmdVet,
-
- helpC,
- helpBuildmode,
- helpFileType,
- helpGopath,
- helpEnvironment,
- helpImportPath,
- helpPackages,
- helpTestflag,
- helpTestfunc,
+var commands []*Command
+
+func init() {
+ commands = []*Command{
+ cmdBuild,
+ cmdClean,
+ cmdDoc,
+ cmdEnv,
+ cmdBug,
+ cmdFix,
+ cmdFmt,
+ cmdGenerate,
+ cmdGet,
+ cmdInstall,
+ cmdList,
+ cmdRun,
+ cmdTest,
+ cmdTool,
+ cmdVersion,
+ cmdVet,
+
+ helpC,
+ helpBuildmode,
+ helpFileType,
+ helpGopath,
+ helpEnvironment,
+ helpImportPath,
+ helpPackages,
+ helpTestflag,
+ helpTestfunc,
+ }
}
var exitStatus = 0
bw.Flush()
}
-func usage() {
+var usage func()
+
+func init() {
+ usage = mainUsage
+}
+
+func mainUsage() {
// special case "go test -h"
if len(os.Args) > 1 && os.Args[1] == "test" {
os.Stderr.WriteString(testUsage + "\n\n" +
if p.BinaryOnly {
// For binary-only package, use build ID from supplied package binary.
- buildID, err := readBuildID(p)
+ buildID, err := readBuildID(p.Name, p.Target)
if err == nil {
p.buildID = buildID
}
// It also catches changes in toolchain, like when flipping between
// two versions of Go compiling a single GOPATH.
// See issue 8290 and issue 10702.
- targetBuildID, err := readBuildID(p)
+ targetBuildID, err := readBuildID(p.Name, p.Target)
if err == nil && targetBuildID != p.buildID {
return true, "build ID mismatch"
}
// 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(buildToolchain.compiler()) {
+ if olderThan(buildToolchainCompiler) {
return true, "newer compiler"
}
- if p.build.IsCommand() && olderThan(buildToolchain.linker()) {
+ if p.build.IsCommand() && olderThan(buildToolchainLinker) {
return true, "newer linker"
}
}
// readBuildID reads the build ID from an archive or binary.
// It only supports the gc toolchain.
// Other toolchain maintainers should adjust this function.
-func readBuildID(p *Package) (id string, err error) {
- if buildToolchain != (gcToolchain{}) {
+func readBuildID(name, target string) (id string, err error) {
+ if buildToolchainName != "gc" {
return "", errBuildIDToolchain
}
// For commands, read build ID directly from binary.
- if p.Name == "main" {
- return ReadBuildIDFromBinary(p.Target)
+ if name == "main" {
+ return ReadBuildIDFromBinary(target)
}
// Otherwise, we expect to have an archive (.a) file,
// and we can read the build ID from the Go export data.
- if !strings.HasSuffix(p.Target, ".a") {
- return "", &os.PathError{Op: "parse", Path: p.Target, Err: errBuildIDUnknown}
+ if !strings.HasSuffix(target, ".a") {
+ return "", &os.PathError{Op: "parse", Path: target, Err: errBuildIDUnknown}
}
// Read just enough of the target to fetch the build ID.
//
// The variable-sized strings are GOOS, GOARCH, and the experiment list (X:none).
// Reading the first 1024 bytes should be plenty.
- f, err := os.Open(p.Target)
+ f, err := os.Open(target)
if err != nil {
return "", err
}
}
bad := func() (string, error) {
- return "", &os.PathError{Op: "parse", Path: p.Target, Err: errBuildIDMalformed}
+ return "", &os.PathError{Op: "parse", Path: target, Err: errBuildIDMalformed}
}
// Archive header.
// Prepare build + run + print actions for all packages being tested.
for _, p := range pkgs {
- buildTest, runTest, printTest, err := b.test(p)
+ buildTest, runTest, printTest, err := builderTest(&b, p)
if err != nil {
str := err.Error()
if strings.HasPrefix(str, "\n") {
"update",
}
-func (b *builder) test(p *Package) (buildAction, runAction, printAction *action, err error) {
+func builderTest(b *builder, p *Package) (buildAction, runAction, printAction *action, err error) {
if len(p.TestGoFiles)+len(p.XTestGoFiles) == 0 {
build := b.action(modeBuild, modeBuild, p)
run := &action{p: p, deps: []*action{build}}
- print := &action{f: (*builder).notest, p: p, deps: []*action{run}}
+ print := &action{f: builderNoTest, p: p, deps: []*action{run}}
return build, run, print, nil
}
} else {
// run test
runAction = &action{
- f: (*builder).runTest,
+ f: builderRunTest,
deps: []*action{buildAction},
p: p,
ignoreFail: true,
}
cleanAction := &action{
- f: (*builder).cleanTest,
+ f: builderCleanTest,
deps: []*action{runAction},
p: p,
}
printAction = &action{
- f: (*builder).printTest,
+ f: builderPrintTest,
deps: []*action{cleanAction},
p: p,
}
var noTestsToRun = []byte("\ntesting: warning: no tests to run\n")
-// runTest is the action for running a test binary.
-func (b *builder) runTest(a *action) error {
+// builderRunTest is the action for running a test binary.
+func builderRunTest(b *builder, a *action) error {
args := stringList(findExecCmd(), a.deps[0].target, testArgs)
a.testOutput = new(bytes.Buffer)
return fmt.Sprintf("\tcoverage: %s", matches[1])
}
-// cleanTest is the action for cleaning up after a test.
-func (b *builder) cleanTest(a *action) error {
+// builderCleanTest is the action for cleaning up after a test.
+func builderCleanTest(b *builder, a *action) error {
if buildWork {
return nil
}
return nil
}
-// printTest is the action for printing a test result.
-func (b *builder) printTest(a *action) error {
+// builderPrintTest is the action for printing a test result.
+func builderPrintTest(b *builder, a *action) error {
clean := a.deps[0]
run := clean.deps[0]
os.Stdout.Write(run.testOutput.Bytes())
return nil
}
-// notest is the action for testing a package with no test files.
-func (b *builder) notest(a *action) error {
+// builderNoTest is the action for testing a package with no test files.
+func builderNoTest(b *builder, a *action) error {
fmt.Printf("? \t%s\t[no test files]\n", a.p.ImportPath)
return nil
}