diff --git a/internal/linker/linker.go b/internal/linker/linker.go index 7e81a6b..1c583ac 100644 --- a/internal/linker/linker.go +++ b/internal/linker/linker.go @@ -16,6 +16,7 @@ import ( "os/exec" "path/filepath" "regexp" + "runtime" "github.com/bluekeyes/go-gitdiff/gitdiff" "github.com/rogpeppe/go-internal/lockedfile" @@ -138,7 +139,7 @@ func applyPatches(srcDir, workingDir string, modFiles map[string]bool, patches [ return mod, nil } -func cachePath(goExe string) (string, error) { +func cachePath() (string, error) { var cacheDir string if val, ok := os.LookupEnv(garbleCacheDir); ok { cacheDir = val @@ -155,6 +156,11 @@ func cachePath(goExe string) (string, error) { return "", err } + goExe := "" + if runtime.GOOS == "windows" { + goExe = ".exe" + } + // Note that we only keep one patched and built linker in the cache. // If the user switches between Go versions or garble versions often, // this may result in rebuilds since we don't keep multiple binaries in the cache. @@ -220,13 +226,13 @@ func buildLinker(workingDir string, overlay map[string]string, outputLinkPath st return nil } -func PatchLinker(goRoot, goVersion, goExe, tempDir string) (string, func(), error) { +func PatchLinker(goRoot, goVersion, tempDir string) (string, func(), error) { patchesVer, modFiles, patches, err := loadLinkerPatches() if err != nil { panic(fmt.Errorf("cannot retrieve linker patches: %v", err)) } - outputLinkPath, err := cachePath(goExe) + outputLinkPath, err := cachePath() if err != nil { return "", nil, err } diff --git a/main.go b/main.go index 20d4c32..b482c90 100644 --- a/main.go +++ b/main.go @@ -441,7 +441,7 @@ func mainErr(args []string) error { executablePath := args[0] if tool == "link" { - modifiedLinkPath, unlock, err := linker.PatchLinker(cache.GoEnv.GOROOT, cache.GoEnv.GOVERSION, cache.GoEnv.GOEXE, sharedTempDir) + modifiedLinkPath, unlock, err := linker.PatchLinker(cache.GoEnv.GOROOT, cache.GoEnv.GOVERSION, sharedTempDir) if err != nil { return fmt.Errorf("cannot get modified linker: %v", err) } @@ -2378,7 +2378,7 @@ func flagSetValue(flags []string, name, value string) []string { func fetchGoEnv() error { out, err := exec.Command("go", "env", "-json", // Keep in sync with sharedCache.GoEnv. - "GOOS", "GOMOD", "GOVERSION", "GOROOT", "GOEXE", + "GOOS", "GOMOD", "GOVERSION", "GOROOT", ).CombinedOutput() if err != nil { // TODO: cover this in the tests. diff --git a/shared.go b/shared.go index bbd8f4f..c75c9d9 100644 --- a/shared.go +++ b/shared.go @@ -54,7 +54,6 @@ type sharedCache struct { GOMOD string GOVERSION string GOROOT string - GOEXE string } } diff --git a/testdata/script/linker.txtar b/testdata/script/linker.txtar index 9c0d7ee..141be66 100644 --- a/testdata/script/linker.txtar +++ b/testdata/script/linker.txtar @@ -14,9 +14,23 @@ exec ./main [short] stop # no need to verify this with -short +# The rebuilt linker should use the executable extension for the host GOOS, +# not the target one. Not doing so might be harmless, but can result in +# building the linker twice, wasting CPU and disk. +[!windows] env GOOS=windows +[windows] env GOOS=linux +garble build +[!windows] [exec:git] exists ${GARBLE_CACHE_DIR}/garble/link +[!windows] [exec:git] ! exists ${GARBLE_CACHE_DIR}/garble/link.exe +[windows] [exec:git] ! exists ${GARBLE_CACHE_DIR}/garble/link +[windows] [exec:git] exists ${GARBLE_CACHE_DIR}/garble/link.exe +env GOOS= + +# Verify a build without garble. go build exec ./main cmp stderr main.stderr + -- go.mod -- module test/main