From 83c10b204d619d18100716c9588404200acdf6e0 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Mon, 26 Jan 2015 20:58:17 -0500 Subject: [PATCH] cmd/go: add build flag -toolexec Like the -exec flag, which specifies a program to use to run a built executable, the -toolexec flag specifies a program to use to run a tool like 5a, 5g, or 5l. This flag enables running the toolchain under common testing environments, such as valgrind. This flag also enables the use of custom testing environments or the substitution of alternate tools. See https://godoc.org/rsc.io/toolstash for one possibility. Change-Id: I256aa7af2d96a4bc7911dc58151cc2155dbd4121 Reviewed-on: https://go-review.googlesource.com/3351 Reviewed-by: Rob Pike --- src/cmd/go/build.go | 19 +++++++++++++------ src/cmd/go/doc.go | 4 ++++ src/cmd/go/fix.go | 2 +- src/cmd/go/get.go | 2 +- src/cmd/go/vet.go | 2 +- 5 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/cmd/go/build.go b/src/cmd/go/build.go index e201f29e766..a3916cae28c 100644 --- a/src/cmd/go/build.go +++ b/src/cmd/go/build.go @@ -93,6 +93,10 @@ and test commands: a list of build tags to consider satisfied during the build. For more information about build tags, see the description of build constraints in the documentation for the go/build package. + -toolexec 'cmd args' + a program to use to invoke toolchain programs like 5a, 5g, and 5l. + For example, instead of running 5g, the go command will run + 'cmd args /path/to/5g '. The list flags accept a space-separated list of strings. To embed spaces in an element in the list, surround it with either single or double quotes. @@ -131,6 +135,7 @@ var buildCcflags []string // -ccflags flag var buildLdflags []string // -ldflags flag var buildGccgoflags []string // -gccgoflags flag var buildRace bool // -race flag +var buildToolExec []string // -toolexec flag var buildContext = build.Default var buildToolchain toolchain = noToolchain{} @@ -184,6 +189,7 @@ func addBuildFlags(cmd *Command) { cmd.Flag.Var((*stringsFlag)(&buildContext.BuildTags), "tags", "") cmd.Flag.Var(buildCompiler{}, "compiler", "") cmd.Flag.BoolVar(&buildRace, "race", false, "") + cmd.Flag.Var((*stringsFlag)(&buildToolExec), "toolexec", "") } func addBuildFlagsNX(cmd *Command) { @@ -1229,6 +1235,7 @@ func (b *builder) copyFile(a *action, dst, src string, perm os.FileMode) error { // 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, tool("cover"), "-mode", a.p.coverMode, "-var", varName, @@ -1657,7 +1664,7 @@ func (gcToolchain) gc(b *builder, p *Package, archive, obj string, asmhdr bool, gcargs = append(gcargs, "-installsuffix", buildContext.InstallSuffix) } - args := stringList(tool(archChar+"g"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs) + args := stringList(buildToolExec, tool(archChar+"g"), "-o", ofile, "-trimpath", b.work, buildGcflags, gcargs, "-D", p.localPrefix, importArgs) if ofile == archive { args = append(args, "-pack") } @@ -1676,7 +1683,7 @@ func (gcToolchain) asm(b *builder, p *Package, obj, ofile, sfile string) error { // Add -I pkg/GOOS_GOARCH so #include "textflag.h" works in .s files. inc := filepath.Join(goroot, "pkg", fmt.Sprintf("%s_%s", goos, goarch)) sfile = mkAbs(p.Dir, sfile) - return b.run(p.Dir, p.ImportPath, nil, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-I", inc, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile) + return b.run(p.Dir, p.ImportPath, nil, stringList(buildToolExec, tool(archChar+"a"), "-trimpath", b.work, "-I", obj, "-I", inc, "-o", ofile, "-D", "GOOS_"+goos, "-D", "GOARCH_"+goarch, sfile)) } func (gcToolchain) pkgpath(basedir string, p *Package) string { @@ -1715,7 +1722,7 @@ func (gcToolchain) pack(b *builder, p *Package, objDir, afile string, ofiles []s // Need actual pack. cmdline[0] = tool("pack") - return b.run(p.Dir, p.ImportPath, nil, cmdline) + return b.run(p.Dir, p.ImportPath, nil, buildToolExec, cmdline) } func packInternal(b *builder, afile string, ofiles []string) error { @@ -1823,7 +1830,7 @@ func (gcToolchain) ld(b *builder, p *Package, out string, allactions []*action, } } ldflags = append(ldflags, buildLdflags...) - return b.run(".", p.ImportPath, nil, tool(archChar+"l"), "-o", out, importArgs, ldflags, mainpkg) + return b.run(".", p.ImportPath, nil, stringList(buildToolExec, tool(archChar+"l"), "-o", out, importArgs, ldflags, mainpkg)) } func (gcToolchain) cc(b *builder, p *Package, objdir, ofile, cfile string) error { @@ -2212,7 +2219,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi } objExt = "o" } - if err := b.run(p.Dir, p.ImportPath, cgoenv, cgoExe, "-objdir", obj, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, p.CgoFiles); err != nil { + if err := b.run(p.Dir, p.ImportPath, cgoenv, buildToolExec, cgoExe, "-objdir", obj, cgoflags, "--", cgoCPPFLAGS, cgoexeCFLAGS, p.CgoFiles); err != nil { return nil, nil, err } outGo = append(outGo, gofiles...) @@ -2344,7 +2351,7 @@ func (b *builder) cgo(p *Package, cgoExe, obj string, pcCFLAGS, pcLDFLAGS, gccfi if p.Standard && p.ImportPath == "runtime/cgo" { cgoflags = append(cgoflags, "-dynlinker") // record path to dynamic linker } - if err := b.run(p.Dir, p.ImportPath, nil, cgoExe, "-objdir", obj, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags); err != nil { + if err := b.run(p.Dir, p.ImportPath, nil, buildToolExec, cgoExe, "-objdir", obj, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags); err != nil { return nil, nil, err } outGo = append(outGo, importGo) diff --git a/src/cmd/go/doc.go b/src/cmd/go/doc.go index fac6ba8fe26..9b642019454 100644 --- a/src/cmd/go/doc.go +++ b/src/cmd/go/doc.go @@ -112,6 +112,10 @@ and test commands: a list of build tags to consider satisfied during the build. For more information about build tags, see the description of build constraints in the documentation for the go/build package. + -toolexec 'cmd args' + a program to use to invoke toolchain programs like 5a, 5g, and 5l. + For example, instead of running 5g, the go command will run + 'cmd args /path/to/5g '. The list flags accept a space-separated list of strings. To embed spaces in an element in the list, surround it with either single or double quotes. diff --git a/src/cmd/go/fix.go b/src/cmd/go/fix.go index 8736cce3e2a..858feab24b7 100644 --- a/src/cmd/go/fix.go +++ b/src/cmd/go/fix.go @@ -25,6 +25,6 @@ func runFix(cmd *Command, args []string) { // Use pkg.gofiles instead of pkg.Dir so that // the command only applies to this package, // not to packages in subdirectories. - run(stringList(tool("fix"), relPaths(pkg.allgofiles))) + run(stringList(buildToolExec, tool("fix"), relPaths(pkg.allgofiles))) } } diff --git a/src/cmd/go/get.go b/src/cmd/go/get.go index 50e0ca93bf4..01ca4b2acdf 100644 --- a/src/cmd/go/get.go +++ b/src/cmd/go/get.go @@ -223,7 +223,7 @@ func download(arg string, stk *importStack, getTestDeps bool) { // due to wildcard expansion. for _, p := range pkgs { if *getFix { - run(stringList(tool("fix"), relPaths(p.allgofiles))) + run(buildToolExec, stringList(tool("fix"), relPaths(p.allgofiles))) // The imports might have changed, so reload again. p = reloadPackage(arg, stk) diff --git a/src/cmd/go/vet.go b/src/cmd/go/vet.go index 02ff54b2ac8..2634536afff 100644 --- a/src/cmd/go/vet.go +++ b/src/cmd/go/vet.go @@ -46,5 +46,5 @@ func runVetFiles(p *Package, files []string) { for i := range files { files[i] = filepath.Join(p.Dir, files[i]) } - run(tool("vet"), relPaths(files)) + run(buildToolExec, tool("vet"), relPaths(files)) }