# Regression test for https://go.dev/issue/64589: # This test is very similar to build_cc_cache_issue64423. Issue #64423 # was that we weren't properly parsing the versions output by the compiler. # That test checked that we could parse the version and incorporate the # version into the hash for the action id. This issue #64589 is that # we treat all errors getting the version of the compiler the same, so # we'd get the same action id for a missing compiler vs one whose # version is unparseable. So the test now first does a run with a compiler # that produces unparseable version output, and then runs it again with a missing # compiler and ensures the command doesn't return the cached output for the # first run when running the second run. [!cgo] skip [short] skip 'builds and links a fake clang binary' [!cc:clang] skip 'test is specific to clang version parsing' # Save the location of the real clang command for our fake one to use. go run ./which clang cp stdout $WORK/.realclang # Build a fake clang and ensure that it is the one in $PATH. mkdir $WORK/bin go build -o $WORK/bin/clang$GOEXE ./fakeclang [!GOOS:plan9] env PATH=$WORK${/}bin [GOOS:plan9] env path=$WORK${/}bin # Force CGO_ENABLED=1 so that the following commands should error # out if the fake clang doesn't work. env CGO_ENABLED=1 # The bug in https://go.dev/issue/64589 resulted in cache keys that # didn't contain any information about the error getting the compiler version. # Since the bug was in cache key computation, isolate the cache: # if we change the way caching works, we want the test to fail # instead of accidentally reusing the cached information from a # previous test run. env GOCACHE=$WORK${/}.cache mkdir $GOCACHE go build -x runtime/cgo # Tell our fake clang to stop working. # Previously, 'go build -x runtime/cgo' would continue to # succeed because both the broken clang and the non-broken one # resulted in a cache key with no clang version information. env GO_BREAK_CLANG=1 ! go build -x runtime/cgo stderr '# runtime/cgo\nGO_BREAK_CLANG is set' -- go.mod -- module example/issue64589 go 1.20 -- which/main.go -- package main import ( "os" "os/exec" ) func main() { path, err := exec.LookPath(os.Args[1]) if err != nil { panic(err) } os.Stdout.WriteString(path) } -- fakeclang/main.go -- package main import ( "bytes" "log" "os" "os/exec" "path/filepath" "slices" ) func main() { if os.Getenv("GO_BREAK_CLANG") != "" { os.Stderr.WriteString("GO_BREAK_CLANG is set\n") os.Exit(1) } b, err := os.ReadFile(filepath.Join(os.Getenv("WORK"), ".realclang")) if err != nil { log.Fatal(err) } if slices.Contains(os.Args, "-###") { // We are being run by gccToolID to determine the tool id used in the action id. return // The important thing is that we don't print the string "version"! } clang := string(bytes.TrimSpace(b)) cmd := exec.Command(clang, os.Args[1:]...) cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr if err := cmd.Run(); err != nil { log.Fatal(err) } }