Reputation: 195
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?
Upvotes: 1
Views: 1281
Reputation: 1377
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
Upvotes: 1
Reputation: 195
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!?)
Upvotes: 1