tl;dr: if the PWD of the current shell is a symlink to a dir in $GOPATH, then linking with -X does not work.
go version)?go version go1.10 freebsd/amd64
yes
go env)?GOARCH="amd64"
GOBIN=""
GOCACHE="/data/home/kena/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="freebsd"
GOOS="freebsd"
GOPATH="/data/home/kena/src/go"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/freebsd_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
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 -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build068611065=/tmp/go-build -gno-record-gcc-switches"
Check the README here: https://github.com/knz/build-x-bug
In short:
go build -ldflags '-X yourpackage/var=val' -> this worksgo build command -> this breaks, -X does not set the var.-X with a package path relative to $GOPATH should work regardless of PWD.
Whether -X works properly or not is dependent on the PWD.
use filepath.Abs on the PWD before trying to make clever comparisons in the linker.
I think that filepath.Abs on the pwd is not sufficient, GOPATH itself must also be normalized with Abs.
I also think this is a regression with 1.10 - wasn't there in 1.9
/cc @ianlancetaylor
It works if you use -ldflags=all='-X ...'.
Perhaps the $PWD referring to a symlink changes the matching of the -ldflags pattern somehow.
Likely could be fixed by calling filepath.EvalSymlinks in getwd before setting base.Cwd in cmd/go/internal/base.
@ianlancetaylor I have verified your version and it turns out to be a working fix. Should we have a proper test for it in go_test.go?
Yes, it ought to have a test.
Change https://golang.org/cl/101256 mentions this issue: cmd/go: fix -X importpath.name=value when building from symlinked wd
I wrote on the CL:
In general, don't use symlinks and expect things to work.
The call to EvalSymlinks will fix this one test case, where evaluating the symlink
makes the path move into GOPATH. But it will break the inverse test case, where
evaluating the symlink makes the path move out of GOPATH.The answer is to not use symlinks.
I think we should leave the current behavior alone. GOPATH is on its way out anyway.
In general, don't use symlinks and expect things to work.
It worked in every Go version prior to 1.10. Why break it until GOPATH is out?
It worked by accident in every prior Go version. I don't feel strongly about this particular issue, but as a general rule we don't want to lock ourselves into behavior that was not documented and that worked by accident.
In general, don't use symlinks and expect things to work.
The call to EvalSymlinks will fix this one test case, where evaluating the symlink
makes the path move into GOPATH. But it will break the inverse test case, where
evaluating the symlink makes the path move out of GOPATH.The answer is to not use symlinks.
It's reasonable to disallow symlinks in the GOPATH itself. But whether the cwd is a symlink or not shouldn't matter. At least that's my expectation as a user (and it's not something I would expect to be specifically documented).