首先,请了解可执行文件不包含单个rpath
条目,而是一个或多个条目的数组。
其次,你可以使用otool
列出图像的rpath
条目。使用otool -l
,您将得到如下输出,其最后是rpath
条目:
Load command 34
cmd LC_LOAD_DYLIB
cmdsize 88
name /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (offset 24)
time stamp 2 Wed Dec 31 19:00:02 1969
current version 1038.32.0
compatibility version 45.0.0
Load command 35
cmd LC_RPATH
cmdsize 40
path @loader_path/../Frameworks (offset 12)
寻找LC_RPATH
命令并记下下面的路径path
entry.
编辑:关于什么@loader_path
是:它是引用想要加载框架的 Mach-O 对象的通用且动态的方式。
虽然这是一个相当人为的例子,但我认为它应该能够表达要点。假设我们有一个应用程序MyApp.app
使用框架MyFramework.framework
。我们还会说,为了正常运行,我要求我的应用程序安装在 /Applications 中,而不是其他地方。因此,所述应用程序和框架的结构如下:
/Applications/MyApp.app/Contents/MacOS/MyApp
(可执行)/Applications/MyApp.app/Contents/Frameworks/MyFramework.framework/MyFramework
(Mach-O dylib)
如果我们要跑otool -L
(注意大写的 L)在可执行文件上它将显示有关 MyFramework 的以下内容:
@rpath/MyFramework.framework/Versions/A/MyFramework
/System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa
/System/Library/Frameworks/Foundation.framework/Versions/C/Foundation
/usr/lib/libobjc.A.dylib
/usr/lib/libSystem.B.dylib
....
请注意,因为 MyFramework.framework 使用@rpath
安装名称/路径,我们需要有运行时搜索路径条目来替换@rpath
在运行时。现在,我可以有一个 rpath 条目:
/Applications/MyApp.app/Contents/Frameworks
这是可行的,并且在运行时这两个部分将被组合在一起:
/Applications/MyApp.app/Contents/Frameworks
+ /MyFramework.framework/Versions/A/MyFramework
==
/Applications/MyApp.app/Contents/Frameworks/MyFramework.framework/Versions/A/MyFramework
显然,硬编码这样的路径并不理想,因为简单地将应用程序移动到不同的文件夹或重命名应用程序本身会导致链接失败。
@loader_path
只是一种动态方式来引用应用程序的可执行文件,无论它存在于文件系统上的任何位置。在这种特殊情况下,在运行时它将填充正在运行的可执行文件的路径:/Applications/MyApp.app/Contents/MacOS/MyApp
。然后我们可以说,要找到 MyFramework.framework,您只需转到一个目录并转到Frameworks
.