Search code examples
c++macoslinkershared-librariesrpath

dyld: Library not loaded despite correct rpath


I am debugging a problem where I am trying to link against a dylib, and set the program's rpath to a directory containing the library.

I have narrowed this to the following MWE:

> ls deps/include/spinnaker/
AVIRecorder.h    Camera.h      CameraPtr.h    Exception.h …bunch of headers
> ls deps/lib/libSpinnaker.dylib*
deps/lib/libSpinnaker.dylib  deps/lib/libSpinnaker.dylib.1.24.0.60
> cat test.cpp
#include <cstddef>
#include <Event.h>          // for CameraList
#include <CameraList.h>          // for CameraList
#include <CameraPtr.h>           // for CameraPtr
#include <ImagePtr.h>            // for ImagePtr
#include <SystemPtr.h>           // for SystemPtr

int main()
{
  const auto system_ptr = Spinnaker::System::GetInstance();

}

I compile this with

clang++ -std=c++14 -o wat -I deps/include/spinnaker/ -L deps/lib/ -lSpinnaker -Wl,-rpath,./deps/lib test.cpp

And thus libSpinnaker gets referenced as shown by

[…]
Load command 9
     cmd LC_UUID
 cmdsize 24
    uuid B4498482-D872-3270-AC47-102914DDBCBE
Load command 10
      cmd LC_BUILD_VERSION
  cmdsize 32
 platform 1
    minos 10.15
      sdk 10.15.6
   ntools 1
     tool 3
  version 609.8
Load command 11
      cmd LC_SOURCE_VERSION
  cmdsize 16
  version 0.0
Load command 12
       cmd LC_MAIN
   cmdsize 24
  entryoff 16224
 stacksize 0
Load command 13
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name libSpinnaker.dylib.1.24.0.60 (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 0.0.0
compatibility version 0.0.0
Load command 14
          cmd LC_LOAD_DYLIB
      cmdsize 48
         name /usr/lib/libc++.1.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 902.1.0
compatibility version 1.0.0
Load command 15
          cmd LC_LOAD_DYLIB
      cmdsize 56
         name /usr/lib/libSystem.B.dylib (offset 24)
   time stamp 2 Thu Jan  1 01:00:02 1970
      current version 1281.100.1
compatibility version 1.0.0
Load command 16
          cmd LC_RPATH
      cmdsize 24
         path ./deps/lib (offset 12)
Load command 17
      cmd LC_FUNCTION_STARTS
  cmdsize 16
  dataoff 49312
 datasize 8
Load command 18
      cmd LC_DATA_IN_CODE
  cmdsize 16
  dataoff 49320
 datasize 0

So the LC_RPATH is included, the library is present at the specified path, but still I get

dyld: Library not loaded: libSpinnaker.dylib.1.24.0.60
  Referenced from: <binary-path>
  Reason: image not found
Abort trap: 6

when running it.

Now my observation is that @rpath is missing before the reference to libSpinnaker in the otool output – for other libraries its always there when I look at my larger cmake-based project. I would expect the line

         name @rpath/libSpinnaker.dylib.1.24.0.60 (offset 24)

instead of what i am seeing. I can set DYLD_LIBRARY_PATH and that'll work, but I want to bake this into the binary with the rpath mechanism.

Question: Is the fact that @rpath is missing here indicative of a problem? And if so, how can I get it added with the compiler or CMake? If this is not the problem, what is it?


Solution

  • install_name_tool -id @rpath/libSpinnaker.dylib.1.24.0.60 deps/lib/libSpinnaker.dylib.1.24.0.60 
    
    install_name_tool -change libSpinnaker.dylib.1.24.0.60 @rpath/libSpinnaker.dylib.1.24.0.60 wat
    

    You noticed that the @rpath was missing from the installed name of the library. install_name_tool is the command which allows you to change the installed pathnames, add or remove @rpaths, etc. Because of the modifications, install_name_tool should be used before codesign. Apple documentation has an example of how to setup this type of relative structure.