What version of Go are you using (go version)?
$ go version
go version go1.16.5 linux/amd64
Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (go env)?
go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/aleks/.cache/go-build"
GOENV="/home/aleks/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/aleks/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/aleks/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.16.5"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/home/aleks/go/src/github.com/gopherjs/gopherjs/go.mod"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2418058575=/tmp/go-build -gno-record-gcc-switches"
Problem description
go/build implements module support by calling out to the go list command, which is very nice. Unfortunately, this functionality is disabled if build.Context has ReleaseTags different from the default build context (determined by the version of Go that built the binary). I assume this restriction comes from the fact that you can't pass ReleaseTags to the go list command.
Unfortunately, this check is not particularly helpful because there's no guarantee that the go tool in PATH will match the version the program was built. A typical example would be a tool that is distributed as a pre-built binary.
In addition, when a go/build user tries to match release tags to the GOROOT they are working with, module support may silently turn off, which is a surprising and tricky to debug behavior.
Possible solution
A better version of that condition could be checking that go version matches ReleaseTags, and let the library user to add GOROOT/bin to PATH if they require so, or maybe even use the go list from GOROOT by default.
In addition, it's worth considering whether a silent fallback is appropriate in case of ReleaseTags specifically. I can see that the fallback allows us to maintain compatibility with earlier behavior, which did not depend on the go tool or its version. But maybe disabling the fallback when GO111MODULE=on is set would be reasonable?
A side note on x/tools/go/packages
go/packages sidesteps this problem by not allowing the user to set ReleaseTags to begin with. #41231 suggests the user to manipulate PATH to achieve the desired effect.
Foressing a suggestion to use the go/packages instead of go/build, it is unfortunately difficult in my case for two reasons:
- There's a lot of per-existing code that already relies on
go/build, updating it is a lot of work.
- At the moment,
go/packages doesn't seem to expose any information about embedded files, but go/build does.
What version of Go are you using (
go version)?Does this issue reproduce with the latest release?
Yes.
What operating system and processor architecture are you using (
go env)?go envOutputProblem description
go/buildimplements module support by calling out to thego listcommand, which is very nice. Unfortunately, this functionality is disabled ifbuild.ContexthasReleaseTagsdifferent from the default build context (determined by the version of Go that built the binary). I assume this restriction comes from the fact that you can't passReleaseTagsto thego listcommand.Unfortunately, this check is not particularly helpful because there's no guarantee that the
gotool in PATH will match the version the program was built. A typical example would be a tool that is distributed as a pre-built binary.In addition, when a
go/builduser tries to match release tags to the GOROOT they are working with, module support may silently turn off, which is a surprising and tricky to debug behavior.Possible solution
A better version of that condition could be checking that
go versionmatchesReleaseTags, and let the library user to addGOROOT/bintoPATHif they require so, or maybe even use thego listfrom GOROOT by default.In addition, it's worth considering whether a silent fallback is appropriate in case of
ReleaseTagsspecifically. I can see that the fallback allows us to maintain compatibility with earlier behavior, which did not depend on thegotool or its version. But maybe disabling the fallback whenGO111MODULE=onis set would be reasonable?A side note on
x/tools/go/packagesgo/packagessidesteps this problem by not allowing the user to setReleaseTagsto begin with. #41231 suggests the user to manipulate PATH to achieve the desired effect.Foressing a suggestion to use the
go/packagesinstead ofgo/build, it is unfortunately difficult in my case for two reasons:go/build, updating it is a lot of work.go/packagesdoesn't seem to expose any information about embedded files, butgo/builddoes.