go: cmd/go: dylib on macos with rpath fails to run with go run/test
What version of Go are you using (go version
)?
$ go version go version go1.13.6 darwin/amd64
What version of macOS are you using (go version
)?
$ sw_vers -productVersion 10.15.2
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="auto" GOARCH="amd64" GOBIN="" GOCACHE="/Users/eric/Library/Caches/go-build" GOENV="/Users/eric/Library/Application Support/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="darwin" GONOPROXY="" GONOSUMDB="" GOOS="darwin" GOPATH="/Users/eric/go" GOPRIVATE="" GOPROXY="https://proxy.golang.org,direct" GOROOT="/usr/local/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64" GCCGO="gccgo" AR="ar" CC="clang" CXX="clang++" CGO_ENABLED="1" GOMOD="" 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=/var/folders/v4/m6f6w8h54j58bp8q4h_138180000gn/T/go-build216040480=/tmp/go-build -gno-record-gcc-switches -fno-common"
What did you do?
When trying to run a simple go source file that links against an rpath based dylib, it fails to run with either go run
or go test
on 1.13.6. However, doing go build
followed by running the executable works fine. It also works fine when I build go and test it from the go1.13.6
tag. It also works in go 1.13.5 but from looking at the commits between the two, I cannot find an issue. This leads me to believe that however the 1.13.6 was built on google servers introduced some kind of issue.
A repro with a makefile is located at https://github.com/edaniels/go1136dylibissue.
What did you expect to see?
I expected to see a log output of 2
from:
LD_LIBRARY_PATH=`pwd`/dylib/lib go run github.com/edaniels/go1136dylibissue/cmd
What did you see instead?
dyld: Library not loaded: @rpath/libfoo.dylib
Referenced from: /var/folders/v4/m6f6w8h54j58bp8q4h_138180000gn/T/go-build330381377/b001/exe/cmd
Reason: image not found
signal: abort trap
About this issue
- Original URL
- State: open
- Created 4 years ago
- Reactions: 6
- Comments: 20 (16 by maintainers)
Commits related to this issue
- revert osx ci to go1.13 due to https://github.com/golang/go/issues/36572 — committed to iost-official/go-iost by lispc 4 years ago
- use -exec for macos to run go test refers to https://github.com/golang/go/issues/36572 — committed to itomsawyer/tongsuo-go-sdk by deleted user a year ago
That first one might possibly fix this issue. I don’t think we would want the second one. We don’t want to actually allow unvalidated libraries to be run by the
go
tool. This entitlement is one that Go-generated binaries would need (assuming they were hardened, which they aren’t at the moment) to use LD_LIBRARY_PATH successfully.I don’t think that’s really the right way to go though. It’s kind of an accident that the
go
tool passes environment variables unmolested through to temporary executables. It’s asking for issues related to the same environment variable meaning different things in thego
binary and the user’s binary. (e.g. what if you wanted a differentCC
value for thego
tool and the user’s binary? Can’t do that withCC=gcc go run
.)I think it is reasonable to ask that if you want to pass environment variables to a program written in Go, you have to build and run as separate steps.
You might be able to use the
-exec
flag togo run
to introduce an environment variable at the right time. Something likeInstead of finding a way to pass
LD_LIBRARY_PATH
through, another workaround appears to be hardcoding the rpath of the resultant binary using the-rpath
linker option. This also avoids having to build test binaries and run them ourselves. For instance:where
/path/to/library
is the value ofLD_LIBRARY_PATH
. I haven’t tried, but this should also work well with the GoLand IDE.Edit: Unfortunately, this only works if the external linker is used… i.e., if
./pkg
itself uses cgo. If./pkg
itself doesn’t use cgo but one of its dependencies does, you may need to add-ldflags=-linkmode=external
– or you could use the-exec
trick as mentioned before.Yep
-exec
does work. I think in this case, it makes sense to build up a whitelist of environment variables and haveLD_LIBRARY_PATH
be in it via entitlement.