如何正确设置运行路径、搜索路径和安装名称?

15

我有一系列的项目正在编译为动态库。每个 .dylib 都依赖于其他各种 .dylib,我想将这些依赖项放置在不同的目录中(例如可执行路径、加载器路径和固定路径)。

当我在已编译的库上运行 otool -L 时,我会得到一个列表,其中包含这些依赖项的路径,但我不知道这些路径是如何被设置/确定的。它们几乎看起来是伪随机的。我花了数小时在 Xcode 的“构建设置”中尝试更改这些路径(使用 @rpath、@executable_path、@loader_path 等),但似乎无法更改任何内容(通过运行 otool -L 进行检查)。我甚至不确定在哪里添加这些标志,也不真正理解以下差异或如何正确使用它们:

链接 - “动态库名”
链接 - “运行路径搜索路径”
链接 - “其他链接标志”
搜索路径-“库搜索路径”

当我在各种库上运行 install_name_tool -change 时,我能够成功更改运行路径搜索路径(再次通过运行 otool -L 进行验证)。

我正在运行 Xcode 4.2,我非常接近放弃并只使用后构建脚本来运行 install_tool_name 进行更改。但这是一个拙劣的修补程序,我不想这样做。

我在哪里可以看到设置 dylib 依赖项的搜索/运行路径?
有人有任何关于我可能犯了什么错误的想法吗?

2个回答

14
通常来说,在我的动态链接库目标中,我会设置 INSTALL_PATH,也称为“安装目录”,设置成我想要的前缀(例如:@executable_path/../Frameworks)。
我将 LD_DYLIB_INSTALL_NAME,也称为“动态库安装名称”,保留在其默认值,即$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)
Xcode基于您的目标名称来扩展它,因此它可能最终会变成@executable_path/../Frameworks/MyFramework.framework/Versions/A/MyFramework
重要的是要意识到,安装路径作为构建过程的一部分内置于动态链接库中。后来,当您链接引用A.dylib的B.dylib时,A.dylib的安装路径将被复制到B.dylib中。(这就是otool向您显示的内容——那些复制的安装路径)。因此,最好首先将正确的安装路径构建到动态链接库中。
在尝试让所有动态链接库一起工作之前,请逐个检查每个动态链接库。构建它,然后对构建的动态链接库运行otool -L。对于每个体系结构,第一行应该是LD_DYLIB_INSTALL_NAME 显示给你的内容。
一旦您组织好了这些,尝试让动态链接库相互链接。这应该要简单得多。

3
虽然不是我一直在寻找的确切答案,但这让我能够确定我的问题。"otool -L"列出了所有安装名称,第一个所列的“安装名称”是库本身的名称,其他路径是其依赖项的路径。假设您已经从源代码编译了这些依赖项,在Xcode中设置“动态库安装名称”会正确设置这些路径。然而在我的情况下,这些依赖项来自于第三方,因此路径已经被设置好了。由于我无法控制第三方库的编译过程,所以我被迫使用"install_name_tool -change"。 - BigMacAttack
@KurtRevis,假设我正在为软件构建一个插件(基本上是一个DyLib)。我使用编译器自带的libiomp5.dylib进行构建。然而,主程序也有它自己的库。我该如何告诉我的插件在主程序中搜索它(我可以从@executable_path知道路径)?谢谢。 - Royi
我在这里写了一个关于它的问题 - http://stackoverflow.com/questions/40318465/setting-the-search-path-for-plug-in-dylib。谢谢。 - Royi

2

install_name_tool非常有用,可以设置名称和路径。如果程序在构建目录中运行自身测试,然后在make install期间发生更改,则特别有用。在这种情况下,您可以使用install_name_tool而无需单独构建。

install_name_tool也很有用,因为Apple的LD不像Linux/GCC那样支持rpath链接器选项。也就是说,你需要使用一组不同的命令来设置它们。

这是它的man页面。它包含完整的内容,因为它讨论了其他选项,如-headerpad_max_install_names

INSTALL_NAME_TOOL(1)                                      INSTALL_NAME_TOOL(1)

NAME
       install_name_tool - change dynamic shared library install names

SYNOPSIS
       install_name_tool  [-change  old  new  ]  ...  [-rpath  old  new  ] ...
       [-add_rpath new ] ... [-delete_rpath new ] ... [-id name] file

DESCRIPTION
       Install_name_tool changes the dynamic shared library install names  and
       or  adds,  changes  or  deletes the rpaths recorded in a Mach-O binary.
       For this tool to work when the install names or rpaths are  larger  the
       binary  should  be  built  with  the ld(1) -headerpad_max_install_names
       option.

       -change old new
              Changes the dependent shared library install name old to new  in
              the specified Mach-O binary.  More than one of these options can
              be specified.  If the Mach-O binary does  not  contain  the  old
              install  name  in  a  specified  -change  option  the  option is
              ignored.

       -id name
              Changes the shared library  identification  name  of  a  dynamic
              shared  library  to name.  If the Mach-O binary is not a dynamic
              shared library and the -id option is specified it is ignored.

       -rpath old new
              Changes the rpath path name old to new in the  specified  Mach-O
              binary.   More  than  one of these options can be specified.  If
              the Mach-O binary does not contain the old rpath path name in  a
              specified -rpath it is an error.

       -add_rpath new
              Adds  the  rpath  path  name new in the specified Mach-O binary.
              More than one of these options can be specified.  If the  Mach-O
              binary  already  contains  the  new rpath path name specified in
              -add_rpath it is an error.

       -delete_rpath old
              deletes the rpath path name old in the specified Mach-O  binary.
              More  than one of these options can be specified.  If the Mach-O
              binary does not contains the old rpath path  name  specified  in
              -delete_rpath it is an error.

SEE ALSO
       ld(1)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接