Yet another dyld: Library not loaded dylib problem..
I've got a dylib (libboost_system.dylib) compiled from the Boost sources,
then used install-name-tool to prepare it for inclusion in the Frameworks folder of my app bundle like so:
install_name_tool -id #executable_path
/../Frameworks/
libboost_system.dylib libboost_system.dylib
Verified with otool:
$> otool -L libboost_system.dylib
/Users/TesterCodeSandbox/OgreSDK
/BOOST_DYLIBS/libboost_system.dylib:
#executable_path/../Frameworks
/libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.9.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11)
Now added to the Xcode project, linked against the app and copied to the Frameworks folder.
But when checking the built app with otool -L it's still referring to the original (i.e. 'non-relocated') dylib:
OgreTest-ekeeqmnyciddaxbzyrehtcoijcki/Build
/Products/Debug/OgreTest.app/Contents/MacOS/OgreTest:
#executable_path/../Plugins
/RenderSystem_GL.dylib (compatibility version 0.0.0, current version 1.8.0)
/System/Library/Frameworks/Cocoa.framework/
Versions/A/Cocoa (compatibility version 1.0.0, current version 15.0.0)
#executable_path/../Frameworks/Ogre.framework/
Versions/1.8.0/Ogre (compatibility version 0.0.0, current version 1.8.0)
#executable_path/../Frameworks/Cg.framework
/Cg (compatibility version 0.0.0, current version 0.0.0)
/System/Library/Frameworks/IOKit.framework/Versions/A
/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/Carbon.framework/Versions/A
/Carbon (compatibility version 2.0.0, current version 152.0.0)
libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libstdc++.6.dylib
(compatibility version 7.0.0, current version 7.9.0)
/usr/lib/libSystem.B.dylib
(compatibility version 1.0.0, current version 125.2.11)
/usr/lib/libobjc.A.dylib
(compatibility version 1.0.0, current version 227.0.0)
/System/Library/Frameworks/CoreFoundation.framework
/Versions/A/CoreFoundation
(compatibility version 150.0.0, current version 550.43.0)
/System/Library/Frameworks/AppKit.framework
/Versions/C/AppKit
(compatibility version 45.0.0, current version 1038.36.0)
And the app fails to start with the 'dyld: Library not loaded: libboost_system.dylib' error. Any ideas?
Note 1
Now it does work if I also post-process my app's binary with install_name_tool, i.e.:
install_name_tool -change libboost_system.dylib #executable_path/../Frameworks/libboost_system.dylib TestApp
Am I missing some Xcode option to force the compiler to change the dylib location in my app automatically as part of the build?
Surely invoking install_name_tool manually for the application consuming the dylib (i.e. one of potentially many) can just be a work-around for something I've screwed up when configuring the (application) project....
Related
For a reason I don't understand some of the libraries of my binary are statically linked while others have an rpath.
$ otool -L binary
binary:
/usr/local/lib/libtest-1.2.0.dylib (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)
/opt/homebrew/opt/openblas/lib/libopenblas.0.dylib (compatibility version 0.0.0, current version 0.0.0)
#rpath/libtorch.dylib (compatibility version 0.0.0, current version 0.0.0)
#rpath/libtorch_cpu.dylib (compatibility version 0.0.0, current version 0.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1858.112.0)
/System/Library/Frameworks/OpenCL.framework/Versions/A/OpenCL (compatibility version 1.0.0, current version 1.0.0)
How can I force my libtorch libraries for example to be statically linked without using DYLD_LIBRARY_PATH (which can't be overridden without changing some security settings on Mac)?
Thank you.
I can't find this information anywhere. I have some libraries installed in my system, so it works on my computer, but I want to distribute the libraries with my application. The problem that I see is that otool shows absolute paths to system libraries, so when I copy my binaries to other machine it can't find them even tho I have them in a directory that is added in "runpath search paths". I have one local library (located in project dir) and it is linked with #rpath prefix. Other system libraries are linked the same way but they have absolute paths as otool shows. How do I force them to be linked with #rpath prefix?
Well this partially answers my question: How to set dyld_library_path in Xcode
I tried to automate that, so when any new library is added then it would set things up properly, but I gave up (gosh, why does it have to be so complicated!?)
TL;DR
Using install_name_tool -change will certainly set the #rpath for the referenced frameworks/libraries. However, it doesn't change the names of the libraries themselves.
To do that you need to use install_name_tool -id.
Using a rough example of a project I'm working on currently, where QtGui.framework (amongst others, i.e. QtCore, etc.) is a bundled framework within an application bundle called serialplot.app.
Having first run install_name_tool -change to fix the relative paths for QtGui (and QtCore etc.) being called by serialplot application binary
$ install_name_tool -change /usr/local/opt/qt#5/lib/QtGui.framework/Versions/5/QtGui #rpath/QtGui.framework/Versions/5/QtGui serialplot.app/Contents/MacOS/serialplot
... (omitted commands for clarity)
$ install_name_tool -change /usr/local/opt/qt#5/lib/QtCore.framework/Versions/5/QtCore #rpath/QtCore.framework/Versions/5/QtCore serialplot.app/Contents/MacOS/serialplot
as well as install_name_tool -change to fix the relative path for QtCore which being called by QtGui itself
$ install_name_tool -change /usr/local/Cellar/qt#5/5.15.2/lib/QtCore.framework/Versions/5/QtCore #rpath/QtCore.framework/Versions/5/QtCore serialplot.app/Contents/Frameworks/QtGui.framework/Versions/5/QtGui
Now running otool -L on the application binary gives
serialplot.app/Contents/MacOS/serialplot:
#rpath/qwt.framework/Versions/6/qwt (compatibility version 6.2.0, current version 6.2.0)
#rpath/QtSvg.framework/Versions/5/QtSvg (compatibility version 5.15.0, current version 5.15.2)
#rpath/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.15.0, current version 5.15.2)
#rpath/QtGui.framework/Versions/5/QtGui (compatibility version 5.15.0, current version 5.15.2)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1671.10.106)
/System/Library/Frameworks/Metal.framework/Versions/A/Metal (compatibility version 1.0.0, current version 1.0.0)
#rpath/QtSerialPort.framework/Versions/5/QtSerialPort (compatibility version 5.15.0, current version 5.15.2)
#rpath/QtNetwork.framework/Versions/5/QtNetwork (compatibility version 5.15.0, current version 5.15.2)
#rpath/QtCore.framework/Versions/5/QtCore (compatibility version 5.15.0, current version 5.15.2)
So everything looks fine, with #rpath being used for QtGui (as well as the other Qt frameworks).
However, running otool -L on the bundled QtGui, within the application bundle, shows
serialplot.app/Contents/Frameworks/QtGui.framework/QtGui:
/usr/local/opt/qt#5/lib/QtGui.framework/Versions/5/QtGui (compatibility version 5.15.0, current version 5.15.2)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1671.10.106)
/System/Library/Frameworks/Metal.framework/Versions/A/Metal (compatibility version 1.0.0, current version 1.0.0)
#rpath/QtCore.framework/Versions/5/QtCore (compatibility version 5.15.0, current version 5.15.2)
/System/Library/Frameworks/DiskArbitration.framework/Versions/A/DiskArbitration (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/CoreGraphics.framework/Versions/A/CoreGraphics (compatibility version 64.0.0, current version 1247.4.1)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1560.12.0)
/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/ApplicationServices.framework/Versions/A/ApplicationServices (compatibility version 1.0.0, current version 50.1.0)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.11)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 400.9.4)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.200.5)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1560.12.0)
/System/Library/Frameworks/CoreText.framework/Versions/A/CoreText (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
Note that (as you state) the absolute path (/usr/local/opt/qt#5/lib/), and not #rpath is used
$ otool -L serialplot.app/Contents/Frameworks/QtGui.framework/QtGui
serialplot.app/Contents/Frameworks/QtGui.framework/QtGui:
/usr/local/opt/qt#5/lib/QtGui.framework/Versions/5/QtGui (compatibility version 5.15.0, current version 5.15.2)
...
Now run install_name_tool -id
$ install_name_tool -id #rpath/QtGui.framework/Versions/5/QtGui serialplot.app/Contents/Frameworks/QtGui.framework/Versions/5/QtGui
and the output of otool -L now gives you what you want
$ otool -L serialplot.app/Contents/Frameworks/QtGui.framework/QtGui
serialplot.app/Contents/Frameworks/QtGui.framework/QtGui:
#rpath/QtGui.framework/Versions/5/QtGui (compatibility version 5.15.0, current version 5.15.2)
...
Yes, it is complex, and annoying, but perfectly scriptable with a little patience.
For more details on this particular example, see my blog on this project: Porting serialplot to OS X
I've created a simple mac app that uses the Cocoa wrapper for libspotify.
When I export the project as an Application and try to run it, it crashes immediately.
Crash report:
Application Specific Information:
dyld: launch, loading dependent libraries
Dyld Error Message:
Library not loaded: #rpath/CocoaLibSpotify.framework/Versions/A/CocoaLibSpotify
Referenced from: /Users/USER/Desktop/Wunderkiste.app/Contents/MacOS/Wunderkiste
Reason: image not found
otool output:
$ otool -L ~/Desktop/Wunderkiste.app/Contents/MacOS/Wunderkiste
#rpath/CocoaLibSpotify.framework/Versions/A/CocoaLibSpotify (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 20.0.0)
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 1056.0.0)
/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
/System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1265.0.0)
/System/Library/Frameworks/CoreData.framework/Versions/A/CoreData (compatibility version 1.0.0, current version 481.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 855.11.0)
Project - Build Phases
Any ideas?
The Runtime Search Paths build setting in your project needs to contain #loader_path/../Frameworks to tell the dynamic linker where to find CocoaLibSpotify at runtime.
See Linking and Install Names by Mike Ash for a detailed discussion.
I'm building an application using Qt5.1.1 on a Mac. I'm using packages to create an installer. I have it set up so that the installer installs the .app file and all of the libraries into a folder in /Applications/. The problem is when I install the application it is not looking where I want it to look for the libraries.
An otool -L shows this:
esu:
libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
/Users/ken/Qt5.1.1/5.1.1/clang_64/lib/QtWidgets.framework/Versions/5/QtWidgets (compatibility version 5.1.0, current version 5.1.1)
/Users/ken/Qt5.1.1/5.1.1/clang_64/lib/QtGui.framework/Versions/5/QtGui (compatibility version 5.1.0, current version 5.1.1)
/Users/ken/Qt5.1.1/5.1.1/clang_64/lib/QtCore.framework/Versions/5/QtCore (compatibility version 5.1.0, current version 5.1.1)
/Users/ken/Qt5.1.1/5.1.1/clang_64/lib/QtSerialPort.framework/Versions/5/QtSerialPort (compatibility version 5.1.0, current version 5.1.1)
/System/Library/Frameworks/IOKit.framework/Versions/A/IOKit (compatibility version 1.0.0, current version 275.0.0)
/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 744.1.0)
/Users/ken/Qt5.1.1/5.1.1/clang_64/lib/QtNetwork.framework/Versions/5/QtNetwork (compatibility version 5.1.0, current version 5.1.1)
/System/Library/Frameworks/OpenGL.framework/Versions/A/OpenGL (compatibility version 1.0.0, current version 1.0.0)
/System/Library/Frameworks/AGL.framework/Versions/A/AGL (compatibility version 1.0.0, current version 1.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
How can I change where the application is looking for these libraries?
If you run macdeployqt it will change some of them automaticaly (thoses used by Qt) for the other ones, you can do it with install_name_tool
install_name_tool -change oldpath newpath target
I ended up going to where my release esu.app file was and I just used the macdeployqt. Trying to manually set up lib dependencies with install_name_tool was too much of a pain.
This is the command I used:
macdeployqt esu.app -verbose=2 -dmg
I'm trying to run a binary executable built for 10.7 (ISCAgent in the below example) on Mac OS X 10.6.8.
The problem with the binary is it depends on /usr/lib/libcurl.4.dylib
with compatibility version of 7.0.0, while I only have version 6.0.0 installed:
$ otool -L ISCAgent
ISCAgent:
#executable_path/libsslserver.dylib (compatibility version 0.0.0, current version 0.0.0)
#executable_path/libssl.dylib (compatibility version 1.0.0, current version 1.0.0)
#executable_path/libcrypto.dylib (compatibility version 1.0.0, current version 1.0.0)
#executable_path/libcachecom.dylib (compatibility version 0.0.0, current version 0.0.0)
#executable_path/libxerces-c-3.1.dylib (compatibility version 0.0.0, current version 0.0.0)
#executable_path/libicuuc.40.dylib (compatibility version 40.0.0, current version 40.0.0)
#executable_path/libicudata.40.dylib (compatibility version 40.0.0, current version 40.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 52.0.0)
$ otool -L libxerces-c-3.1.dylib
libxerces-c-3.1.dylib:
#executable_path/libxerces-c-3.1.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libcurl.4.dylib (compatibility version 7.0.0, current version 7.0.0)
#executable_path/libicuuc.40.dylib (compatibility version 40.0.0, current version 40.0.0)
#executable_path/libicudata.40.dylib (compatibility version 40.0.0, current version 40.0.0)
/usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 52.0.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
$ otool -L /usr/lib/libcurl.4.dylib
/usr/lib/libcurl.4.dylib:
/usr/lib/libcurl.4.dylib (compatibility version 6.0.0, current version 6.1.0)
/usr/lib/libssl.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
/usr/lib/libcrypto.0.9.8.dylib (compatibility version 0.9.8, current version 0.9.8)
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.3)
/System/Library/Frameworks/LDAP.framework/Versions/A/LDAP (compatibility version 1.0.0, current version 2.2.0)
/System/Library/Frameworks/Kerberos.framework/Versions/A/Kerberos (compatibility version 5.0.0, current version 5.0.0)
/usr/lib/libresolv.9.dylib (compatibility version 1.0.0, current version 41.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 125.2.11)
Currently, I've just replaced libxerces-c-3.1.dylib shipped with the executable with one I built myself on my Snow Leopard, and everything seems to work.
I would like to know what my other options are, however.
Particularly:
How can I (I'm pretty sure I can't, but still) have different versions of libcurl.4.dylib with different compatibility version values in the same /usr/lib directory? I'm confused a bit here -- if code contract (API) and/or ABI changes, the version number in the library file name should also be increased, shouldn't it? If, on the other hand, we have a compatibility version mechanism, what the original version number present in the file name is good for?
How can I affect the hard-coded library paths in a 3rd-party shared object? I have a libcurl.4.dylib (from MacPorts, compatibility version 8.0.0) residing under /opt/local/lib, but exporting a proper DYLD_LIBRARY_PATH doesn't help -- libxerces-c-3.1.dylib always picks libcurl.4.dylib from /usr/lib.