Prior to Go 1.21, setting the GOROOT_FINAL variable during the make scripts changed the GOROOT value embedded in the tools installed in $GOROOT/bin and $GOROOT/pkg/tool. That allowed those tools (primarily cmd/go) to locate GOROOT even if it (or just its binaries) was symlinked or copied to a different install location.
In Go 1.9 (#18678), to reduce confusion and boilerplate from explicit GOROOT settings, cmd/go was changed to use os.Executable to locate its own binary and then derive GOROOT from the fact that cmd/go is normally installed in $GOROOT/bin. cmd/go then passes that path to other tools explicitly as needed. As long as the go command invoked by the user is actually resolved in $GOROOT/bin (possibly via a symlink), it will infer the correct GOROOT regardless of what value may happen to be baked in.
As of Go 1.21, in order to provide reproducible builds of the Go toolchain (#57120), cmd/dist started building releases with the -trimpath flag set, which incidentally caused GOROOT_FINAL to have no effect (#61921). (Development versions of toolchains are still built without -trimpath by default, so GOROOT_FINAL may affect those builds somewhat.)
So GOROOT_FINAL is only really helpful if all of the following occur:
- The toolchain is being built only for a non-release version,
GOROOT is moved after the make script is run,
- the
cmd/go binary is copied or hard-linked (not symlinked!) to some location outside of GOROOT/bin, and
- the copied
cmd/go binary is invoked without setting GOROOT explicitly.
I believe that the intersection of those conditions is “basically never”:
- Third-party distributions of the Go toolchain aren't likely to build non-release versions.
- Go contributors aren't likely to move
GOROOT.
- Distributions that resolve
cmd/go from some other location (like /usr/bin/go) are likely to use symlinks or wrapper scripts instead of hard-links or copies.
- Third-party build tools like Bazel are likely to set
GOROOT explicitly.
On the other hand, GOROOT_FINAL has long been a source of bugs and complexity in the Go project (see https://github.com/golang/go/issues?q=is%3Aissue+GOROOT_FINAL+in%3Atitle). In particular, tests of the toolchain itself may need to take GOROOT_FINAL into account when they inspect or run artifacts built during the test.
I propose that we:
- Drop support for custom
GOROOT_FINAL settings in cmd/dist, cmd/go, and the make scripts.
- Either replace the use of
GOROOT_FINAL in cmd/link with an explict flag (--trimgoroot?), or change cmd/go to always set GOROOT_FINAL to be equal to either GOROOT (if -trimpath is off) or the literal string "$GOROOT" (if -trimpath is on).
- Remove public-facing documentation that refers to
GOROOT_FINAL.
- (Note that the documentation for
cmd/link already does not mention its use of GOROOT_FINAL.)
Prior to Go 1.21, setting the
GOROOT_FINALvariable during themakescripts changed theGOROOTvalue embedded in the tools installed in$GOROOT/binand$GOROOT/pkg/tool. That allowed those tools (primarilycmd/go) to locateGOROOTeven if it (or just its binaries) was symlinked or copied to a different install location.In Go 1.9 (#18678), to reduce confusion and boilerplate from explicit
GOROOTsettings,cmd/gowas changed to useos.Executableto locate its own binary and then deriveGOROOTfrom the fact thatcmd/gois normally installed in$GOROOT/bin.cmd/gothen passes that path to other tools explicitly as needed. As long as thegocommand invoked by the user is actually resolved in$GOROOT/bin(possibly via a symlink), it will infer the correctGOROOTregardless of what value may happen to be baked in.As of Go 1.21, in order to provide reproducible builds of the Go toolchain (#57120),
cmd/diststarted building releases with the-trimpathflag set, which incidentally causedGOROOT_FINALto have no effect (#61921). (Development versions of toolchains are still built without-trimpathby default, soGOROOT_FINALmay affect those builds somewhat.)So
GOROOT_FINALis only really helpful if all of the following occur:GOROOTis moved after themakescript is run,cmd/gobinary is copied or hard-linked (not symlinked!) to some location outside ofGOROOT/bin, andcmd/gobinary is invoked without settingGOROOTexplicitly.I believe that the intersection of those conditions is “basically never”:
GOROOT.cmd/gofrom some other location (like/usr/bin/go) are likely to use symlinks or wrapper scripts instead of hard-links or copies.GOROOT_FINALcannot locate it when copied to another location #61921) are Void Linux and Guix, which were both using copies, but it appears that they are likely to switch to symlinks instead:GOROOT_FINALcannot locate it when copied to another location #61921 (comment)GOROOTexplicitly.On the other hand,
GOROOT_FINALhas long been a source of bugs and complexity in the Go project (see https://github.com/golang/go/issues?q=is%3Aissue+GOROOT_FINAL+in%3Atitle). In particular, tests of the toolchain itself may need to takeGOROOT_FINALinto account when they inspect or run artifacts built during the test.I propose that we:
GOROOT_FINALsettings incmd/dist,cmd/go, and themakescripts.GOROOT_FINALincmd/linkwith an explict flag (--trimgoroot?), or changecmd/goto always setGOROOT_FINALto be equal to eitherGOROOT(if-trimpathis off) or the literal string"$GOROOT"(if-trimpathis on).GOROOT_FINAL.cmd/linkalready does not mention its use ofGOROOT_FINAL.)