Skip to content

go/build: Module support is disabled when ReleaseTags don't match the default. #46856

@nevkontakte

Description

@nevkontakte

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.modules

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions