83

我想使用 更改可执行文件的rpathinstall_name_tool,但我现在无法弄清楚rpath是什么。install_name_tool需要在命令行上同时给出旧的和新的rpath。我可以使用什么命令在 macOS 下打印可执行文件的rpath ?

4

5 回答 5

114

首先,了解可执行文件不包含单个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

编辑:关于什么@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.

于 2012-09-20T22:56:18.450 回答
13

您可以使用otool -l myexecutable,但如果您只对rpath的列表感兴趣,这会打印出很多不必要的信息。

您可以通过以下方式过滤otool -l相关rpath条目的输出

otool -l myexecutable | grep RPATH -A2
于 2018-10-31T13:05:57.230 回答
6

我发现我可以使用 macOS 打印共享库的安装名称

otool -D mylib

此外,我可以直接设置安装名称,而无需通过将-id标志传递给旧的安装名称install_name_tool

install_name_tool -id @rpath/my/path mylib
于 2017-06-28T07:46:55.983 回答
2

我目前正在编写几个用于处理 DYLD 的脚本,这个脚本回答了这个问题,所以我将其发布以供参考:

#!/usr/bin/env ruby
require 'open3'
stdout, stderr, status = Open3.capture3('/usr/bin/otool', '-l', *ARGV)
stdout.scan(/^ +cmd LC_RPATH$.*?^ +path (.*?) \(offset \d+\)$/m) {|(p)| puts p}

例子:

lsrpath /usr/local/microsoft/powershell/7/{pwsh,createdump,unknown.xyz}
@loader_path

'希望能帮助到你 ;-)

于 2015-04-17T23:41:13.603 回答
-1

我只是使用 otool 命令

otool -l <my executable>

它打印出 rpath 字段。不需要任何长脚本。

于 2016-02-26T17:41:28.590 回答