Description
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 themake
script is run,- the
cmd/go
binary is copied or hard-linked (not symlinked!) to some location outside ofGOROOT/bin
, and - the copied
cmd/go
binary is invoked without settingGOROOT
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.- Copying binaries results in a significantly larger install footprint.
- Using hard-links is more likely to confuse users, and less likely to be supported by packaging systems.
- Exceptions we are aware of (from cmd/dist: tools built with
GOROOT_FINAL
cannot 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:
- 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 incmd/dist
,cmd/go
, and themake
scripts. - Either replace the use of
GOROOT_FINAL
incmd/link
with an explict flag (--trimgoroot
?), or changecmd/go
to always setGOROOT_FINAL
to be equal to eitherGOROOT
(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 ofGOROOT_FINAL
.)
- (Note that the documentation for