Text file src/cmd/go/testdata/script/build_cc_cache_issue64423.txt

     1  # Regression test for https://go.dev/issue/64423:
     2  #
     3  # When we parse the version for a Clang binary, we should accept
     4  # an arbitrary vendor prefix, which (as of 2023) may be injected
     5  # by defining CLANG_VENDOR when building clang itself.
     6  #
     7  # Since we don't want to actually rebuild the Clang toolchain in
     8  # this test, we instead simulate it by injecting a fake "clang"
     9  # binary that runs the real one as a subprocess.
    10  
    11  [!cgo] skip
    12  [short] skip 'builds and links a fake clang binary'
    13  [!cc:clang] skip 'test is specific to clang version parsing'
    14  
    15  # Save the location of the real clang command for our fake one to use.
    16  go run ./which clang
    17  cp stdout $WORK/.realclang
    18  
    19  # Build a fake clang and ensure that it is the one in $PATH.
    20  mkdir $WORK/bin
    21  go build -o $WORK/bin/clang$GOEXE ./fakeclang
    22  [!GOOS:plan9] env PATH=$WORK${/}bin
    23  [GOOS:plan9] env path=$WORK${/}bin
    24  
    25  # Force CGO_ENABLED=1 so that the following commands should error
    26  # out if the fake clang doesn't work.
    27  env CGO_ENABLED=1
    28  
    29  # The bug in https://go.dev/issue/64423 resulted in cache keys that
    30  # didn't contain any information about the C compiler.
    31  # Since the bug was in cache key computation, isolate the cache:
    32  # if we change the way caching works, we want the test to fail
    33  # instead of accidentally reusing the cached information from a
    34  # previous test run.
    35  env GOCACHE=$WORK${/}.cache
    36  mkdir $GOCACHE
    37  
    38  go build -x runtime/cgo
    39  
    40  	# Tell our fake clang to stop working.
    41  	# Previously, 'go build -x runtime/cgo' would continue to
    42  	# succeed because both the broken clang and the non-broken one
    43  	# resulted in a cache key with no clang version information.
    44  env GO_BREAK_CLANG=1
    45  ! go build -x runtime/cgo
    46  stderr '# runtime/cgo\nGO_BREAK_CLANG is set'
    47  
    48  -- go.mod --
    49  module example/issue64423
    50  go 1.20
    51  -- which/main.go --
    52  package main
    53  
    54  import (
    55  	"os"
    56  	"os/exec"
    57  )
    58  
    59  func main() {
    60  	path, err := exec.LookPath(os.Args[1])
    61  	if err != nil {
    62  		panic(err)
    63  	}
    64  	os.Stdout.WriteString(path)
    65  }
    66  -- fakeclang/main.go --
    67  package main
    68  
    69  import (
    70  	"bufio"
    71  	"bytes"
    72  	"log"
    73  	"os"
    74  	"os/exec"
    75  	"path/filepath"
    76  	"strings"
    77  )
    78  
    79  func main() {
    80  	if os.Getenv("GO_BREAK_CLANG") != "" {
    81  		os.Stderr.WriteString("GO_BREAK_CLANG is set\n")
    82  		os.Exit(1)
    83  	}
    84  
    85  	b, err := os.ReadFile(filepath.Join(os.Getenv("WORK"), ".realclang"))
    86  	if err != nil {
    87  		log.Fatal(err)
    88  	}
    89  	clang := string(bytes.TrimSpace(b))
    90  	cmd := exec.Command(clang, os.Args[1:]...)
    91  	cmd.Stdout = os.Stdout
    92  	stderr, err := cmd.StderrPipe()
    93  	if err != nil {
    94  		log.Fatal(err)
    95  	}
    96  
    97  	if err := cmd.Start(); err != nil {
    98  		log.Fatal(err)
    99  	}
   100  
   101  	r := bufio.NewReader(stderr)
   102  	for {
   103  		line, err := r.ReadString('\n')
   104  		if line != "" {
   105  			if strings.Contains(line, "clang version") {
   106  				// Simulate a clang version string with an arbitrary vendor prefix.
   107  				const vendorString = "Gopher Solutions Unlimited "
   108  				os.Stderr.WriteString(vendorString)
   109  			}
   110  			os.Stderr.WriteString(line)
   111  		}
   112  		if err != nil {
   113  			break
   114  		}
   115  	}
   116  	os.Stderr.Close()
   117  
   118  	if err := cmd.Wait(); err != nil {
   119  		os.Exit(1)
   120  	}
   121  }
   122  

View as plain text