Go: cmd/go: -ldflags pattern matching broken when building from symlinked pwd

Created on 12 Mar 2018  路  12Comments  路  Source: golang/go

tl;dr: if the PWD of the current shell is a symlink to a dir in $GOPATH, then linking with -X does not work.

What version of Go are you using (go version)?

go version go1.10 freebsd/amd64

Does this issue reproduce with the latest release?

yes

What operating system and processor architecture are you using (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"

What did you do?

Check the README here: https://github.com/knz/build-x-bug

In short:

  • make package in $GOPATH. Use go build -ldflags '-X yourpackage/var=val' -> this works
  • create symlink to package in $GOPATH, in another dir, set that as PWD. Then use same go build command -> this breaks, -X does not set the var.

What did you expect to see?

-X with a package path relative to $GOPATH should work regardless of PWD.

What did you see instead?

Whether -X works properly or not is dependent on the PWD.

Suggested fix.

use filepath.Abs on the PWD before trying to make clever comparisons in the linker.

FrozenDueToAge NeedsFix help wanted

All 12 comments

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).

Was this page helpful?
0 / 5 - 0 ratings