install_name_tool to update a executable to search for dylib in Mac OS X

MacosPathLdDylibDyld

Macos Problem Overview


I have a dynamic libray libtest.dylib that is installed in /PATH/lib, and an execution binary, myapp, that uses the dylib installed in /PATH/bin.

I can run myapp to find the dylib as follows (https://stackoverflow.com/questions/3146274/is-it-ok-to-use-dyld-library-path-on-mac-os-x-and-whats-the-dynamic-library-s):

DYLD_LIBRARY_PATH="/PATH/lib" myapp 

I think I can use install_name_tool to update the library and executable so that the library can be found with rpath. I used the hints in this post - https://stackoverflow.com/questions/17202313/how-can-i-specify-the-rpath-in-a-dylib.

In lib, I executed this command to add rpath.

install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
install_name_tool -add_rpath "@executable_path/../lib/" libtest.dylib

In bin, I executed install_name_tool -add_rpath "@executable_path/../lib/" myapp.

However, when I executed myapp in bin directory, I have the error messages.

dyld: Library not loaded: libtest.dylib
  Referenced from: /PATH/bin/./myapp
  Reason: image not found
Trace/BPT trap: 5

otool -l myapp shows the rpath is correctly updated in myapp.

Load command 16
          cmd LC_RPATH
      cmdsize 40
         path @executable_path/../lib/ (offset 12)

The same is true with libtest.dylib

Load command 13
          cmd LC_RPATH
      cmdsize 40
         path @executable_path/../lib/ (offset 12)

What might be wrong?

ADDED

Of course, I can use cc -install_name when compile and link time, but I wanted to know how to do the same thing my modifying the generatd dylib and execution binary.

From the lib:

cc -install_name "@loader_path/../lib/libtest.dylib" -dynamiclib -o libtest.dylib test.c

Or, the install_name can use @rpath:

cc -install_name "@rpath/libtest.dylib" -dynamiclib -o libtest.dylib test.c

From the bin:

cc -I../lib -c main.c
cc -o main main.o ../lib/libtest.dylib -Wl,-rpath -Wl,@loader_path/../lib

Or just one line:

cc -I../lib -L../lib -o main main.c -ltest -Wl,-rpath -Wl,@loader_path/../lib

Macos Solutions


Solution 1 - Macos

From otool -l, I analyzed what should be added or modified from the original library and binary.

Dylib

The change is in id:

Load command 2 <-- OLD
          cmd LC_ID_DYLIB
      cmdsize 40
         name libtest.dylib (offset 24)
   time stamp 1 Wed Dec 31 18:00:01 1969

Load command 2 <-- NEW
          cmd LC_ID_DYLIB
      cmdsize 64
         name @loader_path/../lib/libtest.dylib (offset 24)
         

This is the command to accomplish the change:

install_name_tool -id "@loader_path/../lib/libtest.dylib" libtest.dylib 

Or use rpath:

install_name_tool -id "@rpath/libtest.dylib" libtest.dylib
The executable

There are two changes: rpath and load_dylib

Load command 12 <-- OLD
          cmd LC_LOAD_DYLIB
      cmdsize 40
         name libtest.dylib (offset 24)

Load command 12 <-- NEW
          cmd LC_LOAD_DYLIB
      cmdsize 64
         name @loader_path/../lib/libtest.dylib (offset 24)

This is the command to accomplish the change

install_name_tool -change libtest.dylib @loader_path/../lib/libtest.dylib myapp 

Also I needed to add the rpath

Load command 14
          cmd LC_RPATH
      cmdsize 32
         path @loader_path/../lib (offset 12)

This is the command to accomplish the addition:

 install_name_tool -add_rpath "@loader_path/../lib" myapp
The idea

The binary tries to find the library, it knows where it is located from install_name_tool -add_rpath "@loader_path/../lib" myapp. It loads the library, and the library's id is @rpath/libtest.dylib where @rpath is set to @loader_path/../lib in the executable binary to make the match.

Reference
Cmake

When using CMake, we can automatize the process with the following addition in CMakeLists.txt file.

Library

The id should be added.

# https://cmake.org/pipermail/cmake/2006-October/011530.html
SET_TARGET_PROPERTIES (test
  PROPERTIES BUILD_WITH_INSTALL_RPATH 1
             INSTALL_NAME_DIR "@rpath"
  )
Executable

The rpath should be specified:

SET(CMAKE_INSTALL_RPATH "@loader_path/../lib/libtest.dylib")

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionprosseekView Question on Stackoverflow
Solution 1 - MacosprosseekView Answer on Stackoverflow