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?

bdash
  • 18,110
  • 1
  • 59
  • 91
chacham15
  • 13,719
  • 26
  • 104
  • 207
  • 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. – jww Sep 06 '16 at 18:35

2 Answers2

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.

bdash
  • 18,110
  • 1
  • 59
  • 91
  • 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? – chacham15 Jun 22 '13 at 15:33
  • 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. – bdash Jun 22 '13 at 19:19
-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
rectummelancolique
  • 2,247
  • 17
  • 13
  • 1
    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. – chacham15 Jun 20 '13 at 15:18
  • didt work so i tried it the original way: `ld: unknown option: -rpath=@executable_path/` – chacham15 Jun 20 '13 at 17:00
  • 3
    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. – bdash Jun 22 '13 at 08:27