1
0
mirror of https://github.com/golang/go synced 2024-11-12 04:00:23 -07:00

cmd/go: set TOOLEXEC_IMPORTPATH for -toolexec tools

This way, a -toolexec tool can tell precisely what package is being
built when it's run. This was very hard to do before, because the tool
had to piece together that information given the build action's
arguments or flags.

Since there wasn't a good set of tests for -toolexec, add one in the
form of a test script. It builds a simple set of packages with a variety
of build tools, to ensure that all the cases behave as expected.

Like other recent master changes, include the changelog item for this
user-facing change too.

Fixes #15677.

Change-Id: I0a5a1d9485840323ec138b2e64b7e7dd803fdf90
Reviewed-on: https://go-review.googlesource.com/c/go/+/263357
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
Trust: Daniel Martí <mvdan@mvdan.cc>
This commit is contained in:
Daniel Martí 2020-10-17 20:03:19 +01:00
parent 61313dab52
commit de74ea5d74
3 changed files with 99 additions and 0 deletions

View File

@ -122,6 +122,15 @@ Do not send CLs removing the interior tags from such phrases.
by <code>go</code> <code>mod</code> <code>vendor</code> since Go 1.11.
</p>
<h4 id="toolexec">The <code>-toolexec</code> build flag</h4>
<p><!-- golang.org/cl/263357 -->
When the <code>-toolexec</code> build flag is specified to use a program when
invoking toolchain programs like compile or asm, the environment variable
<code>TOOLEXEC_IMPORTPATH</code> is now set to the import path of the package
being built.
</p>
<h3 id="cgo">Cgo</h3>
<p> <!-- CL 252378 -->

View File

@ -2001,6 +2001,13 @@ func (b *Builder) runOut(a *Action, dir string, env []string, cmdargs ...interfa
defer cleanup()
cmd.Dir = dir
cmd.Env = base.AppendPWD(os.Environ(), cmd.Dir)
// Add the TOOLEXEC_IMPORTPATH environment variable for -toolexec tools.
// It doesn't really matter if -toolexec isn't being used.
if a != nil && a.Package != nil {
cmd.Env = append(cmd.Env, "TOOLEXEC_IMPORTPATH="+a.Package.ImportPath)
}
cmd.Env = append(cmd.Env, env...)
start := time.Now()
err := cmd.Run()

83
src/cmd/go/testdata/script/toolexec.txt vendored Normal file
View File

@ -0,0 +1,83 @@
[short] skip
# Build our simple toolexec program.
go build ./cmd/mytool
# Build the main package with our toolexec program. For each action, it will
# print the tool's name and the TOOLEXEC_IMPORTPATH value. We expect to compile
# each package once, and link the main package once.
# Don't check the entire output at once, because the order in which the tools
# are run is irrelevant here.
# Finally, note that asm and cgo are run twice.
go build -toolexec=$PWD/mytool
stderr -count=2 '^asm'${GOEXE}' TOOLEXEC_IMPORTPATH=test/main/withasm$'
stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH=test/main/withasm$'
[cgo] stderr -count=2 '^cgo'${GOEXE}' TOOLEXEC_IMPORTPATH=test/main/withcgo$'
[cgo] stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH=test/main/withcgo$'
stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH=test/main$'
stderr -count=1 '^link'${GOEXE}' TOOLEXEC_IMPORTPATH=test/main$'
-- go.mod --
module test/main
-- foo.go --
// Simple package so we can test a program build with -toolexec.
// With a dummy import, to test different TOOLEXEC_IMPORTPATH values.
// Includes dummy uses of cgo and asm, to cover those tools as well.
package main
import (
_ "test/main/withasm"
_ "test/main/withcgo"
)
func main() {}
-- withcgo/withcgo.go --
package withcgo
// int fortytwo()
// {
// return 42;
// }
import "C"
-- withcgo/stub.go --
package withcgo
// Stub file to ensure we build without cgo too.
-- withasm/withasm.go --
package withasm
-- withasm/withasm.s --
TEXT ·Add(SB),$0-24
MOVQ a+0(FP), AX
ADDQ b+8(FP), AX
MOVQ AX, ret+16(FP)
RET
-- cmd/mytool/main.go --
package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
)
func main() {
tool, args := os.Args[1], os.Args[2:]
toolName := filepath.Base(tool)
if len(args) > 0 && args[0] == "-V=full" {
// We can't alter the version output.
} else {
// Print which tool we're running, and on what package.
fmt.Fprintf(os.Stdout, "%s TOOLEXEC_IMPORTPATH=%s\n", toolName, os.Getenv("TOOLEXEC_IMPORTPATH"))
}
// Simply run the tool.
cmd := exec.Command(tool, args...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Run(); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}