How can I specify the rpath in a dylib?
Asked Answered
P

2

4

I have a library: libfoo.dylib. The problem is illustrated in the commands:

$ install_name_tool -id "@rpath/libfoo.dylib" libfoo.dylib
$ install_name_tool -add_rpath "@executable_path/" libfoo.dylib
$ gcc -o foo foo.c -lfoo
$ ./foo #<==== I want this to work
dyld: Library not loaded: @rpath/libfoo.dylib
  Referenced from: ~/./foo
  Reason: image not found
$ install_name_tool -add_rpath "@executable_path/" foo #<=== I dont want to have to specify here where to look for the library
$ ./foo
Hello World

How do I achieve the goal of not having to specify at executable compile where the library is?

Prescript answered 19/6, 2013 at 22:14 Comment(1)
I think you need to compile and link libfoo.dylib with -headerpad_max_install_names to ensure there's enough room for the names you are trying to add. Once libfoo.dylib has its install name, then foo will be able to link to it regardless of the location of the program.Leak
J
2

I must confess that I'm a little confused as to what you're trying to achieve. The entire point of using the runpath search path is that the images loading the library define the search path to be used when loading the library. What you're asking for is for the library to define where the executable should find it. That can be accomplished without using the runpath search path by simply setting the install name of the dylib to the appropriate value. Based on your particular example, it sounds like you want to set the install name to something like @loader_path/libfoo.dylib. Consider the following, which is along the same lines of your sample:

$ cat a.c 
int a(void)
{
    return 1;
}
$ cc -install_name "@loader_path/liba.dylib" -dynamiclib -o liba.dylib a.c 
$ cat main.c
#include <stdio.h>

extern int a(void);

int main(int argc, char **argv)
{
    fprintf(stderr, "A: %d\n", a());
    return 0;
}
$ cc -L. -la -o main main.c
$ ./main
A: 1
$ 

The library tells executables that link against it how to find it by setting its install name, and nothing special needs to be done when linking the executable to have it find the library at runtime.

Jez answered 22/6, 2013 at 8:36 Comment(2)
Yes, your example does what I want (having the library set where it should be found and not the executable). The only problem (and reason that I wanted to use rpath) is that I want to specify 3 locations to search: the /usr/lib, ../Framework/, and the executable path like you showed. From my reading that isnt possible using just install_name, right?Prescript
Right, if you want to specify multiple locations then you need to use runpath search paths, and thus the executable is the one that will specify where to find the library. Note that /usr/lib will be searched by default if the library cannot be found at the location referenced by the load command, so it may not be necessary to explicitly reference that location.Jez
B
-1

The only thing you need is to tell the linker to add the rpath in your binary. Actually, you tell gcc to tell the linker in the following way:

$ gcc -o foo foo.c -lfoo -Wl,-rpath=/some/path

Now if you use objdump to see what's in there:

$ objdump -x ./foo | less

You will see under Dynamic Section somthing like RPATH /some/path.

If having to type the same -Wl,-rpath=... is too cumbersome, ld accepts the @file option (I don't know about dyld but I suppose it does too):

$ echo "-rpath=/some/path" > ./ld-options
$ gcc ./foo.c -o foo -Wl,@ld-options
Blackcock answered 20/6, 2013 at 8:36 Comment(3)
i guess i should have explained a bit further, but the thing is that i have a lot of executables compiling and only one library. I want to keep the command to build the executable within the span of 1 line so that it is easy to see warnings. Adding rpath=... to each executable compile command makes the command really long and go past the 1 line mark. Its more a matter of convenience than necessity.Prescript
didt work so i tried it the original way: ld: unknown option: -rpath=@executable_path/Prescript
These instructions appear to be for GCC and the GNU binutils rather than the OS X toolchain. That's why options like -Wl,-rpath=/foo to gcc are throwing an error.Jez

© 2022 - 2024 — McMap. All rights reserved.