macosdylibdyldotoolinstall-name-tool

How to create an absolute path reference in a dylib?


[Disclaimer: I'm working with someone else's code. I've never created a .dylib, so I turn to S.O.]

I'm working on a distro that creates a .dylib. It looks okay, but when I link against it, the resulting executable crashes with:

dyld: Library not loaded: libstk.dylib.4.4.4
  Referenced from: /Users/r/Projects/Mu/examples/./mune31
  Reason: image not found 
Trace/BPT trap: 5

When I examine the executable with otool, the problem is clear: libstk (the next to last entry) has a relative path, not an absolute path. (As an aside, it doesn't have compatibility or current versions properly set.)

Mu[~/Projects/Mu/examples]$ otool -L ./mune31
        /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
        /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio (compatibility version 1.0.0, current version 1.0.0)
        /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.16.0)
        /System/Library/Frameworks/CoreMIDI.framework/Versions/A/CoreMIDI (compatibility version 1.0.0, current version 73.0.0)
        /Users/r/Projects/Mu/usr/lib/libgsl.0.dylib (compatibility version 18.0.0, current version 18.0.0)
        libstk.dylib.4.4.4 (compatibility version 0.0.0, current version 0.0.0)
        /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)

the question

This distro uses g++ (rather than clang) for its compiler. The current incantation that creates the .dylib is:

g++  -fPIC -dynamiclib -o libstk.dylib.4.4.4 Release/*.o -lpthread -framework CoreAudio -framework CoreFoundation -framework CoreMidi
install -m 644 libstk.dylib.4.4.4 /Users/r/Projects/Mu/usr/lib

What should it read instead to create a .dylib with an absolute path?

update

For backward compatibility reasons, we'd prefer to leave the dylib with a relative name when its build (i.e. we don't want to pass the -install_name argument to g++ -fPIC ... command).

Is there a way to tweak the dylib after it's built to have the absolute pathname? When I run otool -L on the existing file, I see:

$ otool -L libstk.dylib.4.4.4
libstk.dylib.4.4.4:
    libstk.dylib.4.4.4 (compatibility version 0.0.0, current version 0.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
    /System/Library/Frameworks/CoreAudio.framework/Versions/A/CoreAudio (compatibility version 1.0.0, current version 1.0.0)
    /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.16.0)
    /System/Library/Frameworks/CoreMIDI.framework/Versions/A/CoreMIDI (compatibility version 1.0.0, current version 73.0.0)
    /usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 120.0.0)

I'd like that first line to be

    /MySandbox/whatever/libstk.dylib.4.4.4 (compatibility version 0.0.0, current version 0.0.0)

p.s.

If someone is impatient as I am, you can use install_name_tool as a workaround to update the executable like this:

install_name_tool -change libstk.dylib.4.4.4 ../usr/lib/libstk.dylib.4.4.4 mune31

... but it sure would be nice not to have to do that every time I build an executable.


Solution

  • You can use the -id option of install_name_tool to change the dylib's ID before you link your executable. The linker uses the ID as the reference to the library that gets baked into the executable.

    When you expect to use install_name_tool to modify the paths in a binary, you should specify one of these linker options: either -headerpad <size> or -headerpad_max_install_names.