2

I'm struggling with the right options in XCode to include a dylib in my app. I do have a dylib in /usr/local/lib which I do need for my app. As long as I set this path in Lib Search Paths

enter image description here

everything works fine. But of course I want to distribute the dylib with my app which is why I added it to a copy phase:

enter image description here

This indeed copies the dylib into the Frameworks folder in the app. But running on the target system, the app does not find the dylib. It even does not find it in /usr/local/lib. Rather it croaks:

Dyld Error Message:

Library not loaded: @rpath/libopencv_imgproc.3.2.dylib

So, which option needs to be set?

Edit I put together a sample project here. It contains 3 zips: one project, one with the headers to be placed in /usr/local/include and one with the dylibs to be placed in /usr/local/lib. Once the app is compiled it should be able to run anywhere. The dylib is copied into the app, but when run on a clean machine it still looks in /usr/local/lib for the dylib.

I tried (too) many ways to get this to work, so I'm currently completely mixed up.

qwerty_so
  • 35,448
  • 8
  • 62
  • 86
  • Do you have the `dylib` included under `Link Binary with Libraries` in Build Phases? I would also recommend making a copy of the `dylib` and adding it to your project in the `Frameworks` folder, that way it is setup properly when you build your project. – l'L'l Jan 21 '17 at 18:28
  • @l'L'l Yes, sure. Else the compile would already fail. Copy to project does make no difference. The dylib needs to be inside the app which is done with the above copy phase. – qwerty_so Jan 21 '17 at 18:40
  • Try adding `@executable_path/Frameworks` to Build Settings > Linking > Runpath Search Paths. – l'L'l Jan 21 '17 at 18:48
  • @l'L'l It had been `@executable_path/../Frameworks` but changing it did not help. – qwerty_so Jan 21 '17 at 18:55
  • Another question, have you cleaned your project? It should've worked otherwise. The path showing for your `dylib` does not look correct in the `Copy Files` image you have either. It should look like this: `...in Frameworks`. – l'L'l Jan 21 '17 at 18:56
  • 1
    One more observation: Look at the error message `Library not loaded: @rpath/libopencv_imgproc.3.2.dylib`, now look at the name of your dylib `libopencv_imgproc.3.2.0.dylib`, notice the missing `0`. – l'L'l Jan 21 '17 at 19:06
  • @l'L'l Looks promising. Been away for a moment and now it's time to sleep. I'll check that tomorrow :) – qwerty_so Jan 21 '17 at 22:02
  • @l'L'l Couldn't wait... Had cleaned (also derived data), no change. I created a copy of the culprit in the app with the right name. Verified that they are correct libs with `nm`. Still it croaks the it does not find it. Now - time for some sleep! (Found also this to try: http://stackoverflow.com/questions/7117128/xcode-dylib-looking-in-usr-lib?rq=1 – qwerty_so Jan 21 '17 at 22:24
  • @l'L'l I gave up. There does not seem to be a way to add a search path that finds dylibs in the app package. It expects them in a fixed system location :-( I'll create an extra distro to place the needed libs. Can't believe that I'm the only one needing that :-/ – qwerty_so Jan 22 '17 at 18:00
  • If you put a small Xcode project together with the dylib behavior I can probably take a look when time permits. – l'L'l Jan 22 '17 at 19:01
  • @l'L'l That's very kind of you. I have added a sample project. – qwerty_so Jan 22 '17 at 20:51
  • I found the issue with the dylib; I'll write up an answer shortly. – l'L'l Jan 23 '17 at 07:55
  • @l'L'l Great, thanks ! – qwerty_so Jan 23 '17 at 08:04

1 Answers1

3

In my earlier comment as mentioned the name of the dylib in the error message differs (3.2 vs. 3.2.0) from that of the one you are actually using. Since the dylib is already built and you are including it this way in your project that's an indicator an existing rpath or id already exists.

Using otool:

$ otool -l libopencv_core.3.2.0.dylib
...
 Load command 3
          cmd LC_ID_DYLIB
      cmdsize 56
         name @rpath/libopencv_core.3.2.dylib (offset 24)
   time stamp 1 Wed Dec 31 17:00:01 1969
      current version 3.2.0
compatibility version 3.2.0
...
 Load command 16
          cmd LC_RPATH
      cmdsize 32
         path /usr/local/lib (offset 12)

Two things can be observed here; the first being the LC_ID_DYLIB which confirms the discrepancy, and secondly, the LC_RPATH (rpath) which is present is set to indicate the library location is /usr/local/lib. Since you are including the lib with your app it should be updated.

Update the library (the one included in your app):

$ install_name_tool -id @rpath/libopencv_core.3.2.0.dylib libopencv_core.3.2.0.dylib

Updates the LC_ID_DYLIB.

$ install_name_tool -add_rpath "@executable/../Frameworks" libopencv_core.3.2.0.dylib

Adds the correct LC_RPATH.

$ install_name_tool -delete_rpath "/usr/local/lib" libopencv_core.3.2.0.dylib

Removes the rpath /usr/local/lib from the library. To verify run otool -l again:

...
 Load command 3
          cmd LC_ID_DYLIB
      cmdsize 64
         name @rpath/libopencv_core.3.2.0.dylib (offset 24)
   time stamp 1 Wed Dec 31 17:00:01 1969
      current version 3.2.0
compatibility version 3.2.0
...
 Load command 17
          cmd LC_RPATH
      cmdsize 40
         path @executable/../Frameworks (offset 12)

Now you should be able to include the dylib in a standalone app and it's path should be set correctly; the updated dylib is here. After updating the library the app opens without issue.

Notes: In your question you are importing libopencv_core3.2.0.dylib, although the error states libopencv_imgproc.3.2.dylib, but I assume it's another dylib which suffers a similar issue, so this can certainly be applied to others. The rpath you had originally set in Xcode was correct

enter image description here

although since libraries allow multiple rpaths to exist and /usr/local/bin already is present it's using that location first, in addition to the wrong name.

qwerty_so
  • 35,448
  • 8
  • 62
  • 86
l'L'l
  • 44,951
  • 10
  • 95
  • 146