Skip to content

Commit

Permalink
Break reliance on GOROOT_FINAL (#3984)
Browse files Browse the repository at this point in the history
* Clear GOROOT when linking

Due to golang/go#62047, Go 1.23 won't support `GOROOT_FINAL`.
This means that #971 will no longer fix #969,
meaning linked binaries will contain full GOROOT paths, making them non-reproducible.

Instead of using `GOROOT_FINAL`, this change sets `GOROOT` when invoking the linker,
which will cause the linker to continue to write `GOROOT` into the binary,
keeping builds consistent.

This works on Go 1.23rc1 as well.

I'm not a rules_go expert and I'm not married to this particular solution,
I just wanted to bring attention to the issue.
If there's a clever way we can set `-trimpath` when invoking the compiler,
that might be better - but we already use that flag to trim off the bazel sandbox I believe.

* switch based on runtime.Version
  • Loading branch information
JacobOaks authored Jul 16, 2024
1 parent a23892e commit 1a32e03
Showing 1 changed file with 31 additions and 0 deletions.
31 changes: 31 additions & 0 deletions go/tools/builders/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"path/filepath"
"regexp"
"runtime"
"strconv"
"strings"
)

Expand Down Expand Up @@ -149,6 +150,19 @@ func link(args []string) error {
// add in the unprocess pass through options
goargs = append(goargs, toolArgs...)
goargs = append(goargs, *main)

clearGoRoot, err := onVersion(23)
if err != nil {
return err
}
if clearGoRoot {
// Explicitly set GOROOT to a dummy value when running linker.
// This ensures that the GOROOT written into the binary
// is constant and thus builds are reproducible.
oldroot := os.Getenv("GOROOT")
os.Setenv("GOROOT", "GOROOT")
defer os.Setenv("GOROOT", oldroot)
}
if err := goenv.runCommand(goargs); err != nil {
return err
}
Expand All @@ -161,3 +175,20 @@ func link(args []string) error {

return nil
}

var versionExp = regexp.MustCompile(`.*go1\.(\d+).*$`)

func onVersion(version int) (bool, error) {
v := runtime.Version()
m := versionExp.FindStringSubmatch(v)
if len(m) != 2 {
return false, fmt.Errorf("failed to match against Go version %q", v)
}
mvStr := m[1]
mv, err := strconv.Atoi(mvStr)
if err != nil {
return false, fmt.Errorf("convert minor version %q to int: %w", mvStr, err)
}

return mv >= version, nil
}

0 comments on commit 1a32e03

Please sign in to comment.