[short] skip # Build our simple toolexec program. go build ./cmd/mytool # Use an ephemeral build cache so that our toolexec output is not cached # for any stale standard-library dependencies. # # TODO(#27628): This should not be necessary. env GOCACHE=$WORK/gocache # 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 [GOARCH:amd64] 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"$' # Test packages are a little bit trickier. # We have four variants of test/main, as reported by 'go list -test': # # test/main - the regular non-test package # test/main.test - the generated test program # test/main [test/main.test] - the test package for foo_test.go # test/main_test [test/main.test] - the test package for foo_separate_test.go # # As such, TOOLEXEC_IMPORTPATH must see the same strings, to be able to uniquely # identify each package being built as reported by 'go list -f {{.ImportPath}}'. # Note that these are not really "import paths" anymore, but that naming is # consistent with 'go list -json' at least. go test -toolexec=$PWD/mytool stderr -count=2 '^# test/main\.test$' stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main\.test"$' stderr -count=1 '^link'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main\.test"$' stderr -count=1 '^# test/main \[test/main\.test\]$' stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main \[test/main\.test\]"$' stderr -count=1 '^# test/main_test \[test/main\.test\]$' stderr -count=1 '^compile'${GOEXE}' TOOLEXEC_IMPORTPATH="test/main_test \[test/main\.test\]"$' -- 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() {} -- foo_test.go -- package main import "testing" func TestFoo(t *testing.T) {} -- foo_separate_test.go -- package main_test import "testing" func TestSeparateFoo(t *testing.T) {} -- 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 // Note that we don't need to declare the Add func at all. -- withasm/withasm_amd64.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=%q\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) } }