Open abemedia opened 4 years ago
What does @executable_path
mean?
Any fix for this will have to be very careful. For the GNU tools, among others, starting a parameter with @
causes it to be replaced with the contents of a file with the string following the @
. So if we do need to handle @executable_path
, we need to be careful to only do it in a context in which we know for sure that it won't be replaced by a file. Otherwise all of this flag vetting no longer works.
@exexutable_path is like the MacOS version of $ORIGIN on Linux i.e. it is the path that the binary is in at runtime to be able to dynamically link to a library using a relative path.
Here's some more info: https://wincent.com/wiki/@executable_path,_@load_path_and_@rpath
While we're at it we should probably add @loader_path
as well as @executable_path
.
It looks like @
is specifically forbidden as a leading character since we started validating cgo flags in 1dcb5836.
A wrinkle in all this is that GNU binutils uniformly accept
@foo on the command line to mean "if the file foo exists,
then substitute its contents for @foo in the command line".
So we must also reject @x.go, flags and flag arguments
beginning with @, and so on.
That would still be an issue here. Perhaps we could support specifically @loader_path
and @executable_path
(nothing else that starts with @
), and only allow those when GOOS=darwin
?
Yes, that sounds like the ideal solution!
If someone can point me to where I need to look I'm happy to have a bash at a PR.
security.go contains regular expressions for allowed flags.
cfg.GOOS
may be used to check the target operating system. I don't think we have any regular expressions that are allowed on one platform but not others, but that would be necessary here.
cgo_bad_directives.txt tests this filtering, so that would need to be expanded. See README.txt in that directory for information on the test format.
Actually I'm evaluating go for a project on mac and i've a poc that needs to load an external *.dylib
from a directory relative to the binary. So I stumbled over @executable_path
and this issue with go, so is there any known workaround to get a go binary working that can load a *.dylib
from a directory relative to the binary?
Any suggestions would be great, I really would like to use go for the project, but we need to load external C libraries that are not installed in any of the OS search paths.
Update: Sorry for the post but I've found at least a workaround for that:
package native
/*
*/ import "C"
// Rest of code omitted for brevity
2. Run `go build -o mybinary`
3. Run the `install_name_tool`
```bash
# You can check the correct name for change with otool -L mybinary
install_name_tool -change @rpath/libgreeter.dylib @executable_path/libs/x64/libgreeter.dylib mybinary
I'm not sure if this would break anything else, but so far everything is working as expected. I still hope that the go tooling will allow the @executable_path
and @loader_path
flags in the future.
@snmed I'm glad you found a way. You can also set set the CGO_LDFLAGS_ALLOW
environment variable. https://golang.org/cmd/go/#hdr-Environment_variables
@ianlancetaylor Thanks for your advice, that worked very well with CGO_LDFLAGS_ALLOW="-Wl,-rpath,@executable_path/.*" go build
, now only the vscode extensions still shows the invalid flag in #cgo LDFLAGS:-Wl,-rpath,@executable_path/libs
maybe there is some setting for that. A workaround for that is to set the variable for the whole development environment.
What version of Go are you using (
go version
)?Does this issue reproduce with the latest release?
Yes
What operating system and processor architecture are you using (
go env
)?go env
OutputWhat did you do?
I tried to build a MacOS bundle using dynamically linked libraries. As per convention these are stored in
MyApp.app/Contents/Frameworks
which requiresLC_RPATH
to point there.I added the following flag:
What did you expect to see?
go build
builds binary withLC_RPATH
set to@executable_path/../Frameworks
What did you see instead?
I got an
invalid flag
error upon runninggo build
.I also tried replacing
@executable_path
for$ORIGIN
as I would in Linux but then I got animage not found
error when running the resulting binary (I assume this isn't supported on MacOS).