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
gotool. 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
gotool passes environment variables unmolested through to temporary executables. It’s asking for issues related to the same environment variable meaning different things in thegobinary and the user’s binary. (e.g. what if you wanted a differentCCvalue for thegotool 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
-execflag togo runto introduce an environment variable at the right time. Something likeInstead of finding a way to pass
LD_LIBRARY_PATHthrough, another workaround appears to be hardcoding the rpath of the resultant binary using the-rpathlinker option. This also avoids having to build test binaries and run them ourselves. For instance:where
/path/to/libraryis 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
./pkgitself uses cgo. If./pkgitself doesn’t use cgo but one of its dependencies does, you may need to add-ldflags=-linkmode=external– or you could use the-exectrick as mentioned before.Yep
-execdoes work. I think in this case, it makes sense to build up a whitelist of environment variables and haveLD_LIBRARY_PATHbe in it via entitlement.