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


我有一组项目,我正在编译为动态库。这些.dylib中的每一个都依赖于我想要放置在各种其他目录中的其他各种.dylib(即一些在可执行路径中,一些在加载器路径上,一些在固定路径上)。

当我跑 otool -L 在编译的库中,我得到了这些依赖项的路径列表,但我知道如何设置/确定这些路径。它们几乎都是伪随机的。我花了几个小时搞乱Xcode中的“Build Settings”来尝试更改这些路径(w / @ apt,@ executable_path,@ center_path等),但我似乎无法改变任何东西(通过运行检查) otool -L)。我甚至不完全确定在哪里添加这些标志,并且不太了解以下内容之间的区别或如何正确使用它们:

链接 - “动态库安装名称”
链接 - “Runpath搜索路径”
链接 - “其他链接标志”
搜索路径 - “图书馆搜索路径”

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

我正在运行Xcode 4.2,我非常接近放弃,只是使用运行install_tool_name的后期构建脚本来进行更改。但它是一个kludge hack修复,我宁愿不这样做。

在哪里可以看到如何设置dylib依赖项的搜索/运行路径?
任何人对我可能做错了什么都有任何想法?


1951
2018-03-21 04:32


起源



答案:


通常,在我的dylib的目标中,我设置 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, 例如。

要意识到的重要一点是安装路径是 内置于 dylib,作为其构建过程的一部分。稍后,当你链接引用A.dylib的B.dylib时,A.dylib的安装路径是 复制到 B.dylib。 (那是什么 otool 向您展示 - 那些复制的安装路径。)因此,最好首先在dylib中获得正确的安装路径。

在尝试让所有dylib一起工作之前,请分别检查每个dylib。然后构建它 otool -L 在建成的dylib上。每个架构的第一行应该是什么 LD_DYLIB_INSTALL_NAME 向你展示

一旦你有条理,尝试让dylib相互链接。它应该更加直截了当。


12
2018-03-21 05:21



虽然不是我想要的确切答案,但这有助于我找出问题所在。 otool -L 列出所有安装名称。列出的第一个“安装名称”是库本身的名称。列出的任何其他路径都是针对其依赖项的。假设您已从源代码编译了依赖项,在Xcode中设置“动态库安装名称”将正确设置这些路径。但是在我的情况下,依赖关系来自第三方,所以路径已经设置好了。由于我无法控制第三方库的编译,我不得不使用它 install_name_tool -change。 - BigMacAttack
很高兴你想出来了。 - Kurt Revis
非常有用的答案.. - Ahmed
@KurtRevis,假设我正在构建一个软件插件(基本上是DyLib本身)。我用libiomp5.dylib构建它,我的编译器。然而,东道主计划本身也有它。如何告诉我的插件在主机中搜索它(我可以知道@executable_path的路径)?谢谢。 - Royi
我在这里写了一个问题 - stackoverflow.com/questions/40318465/...。谢谢。 - Royi


答案:


通常,在我的dylib的目标中,我设置 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, 例如。

要意识到的重要一点是安装路径是 内置于 dylib,作为其构建过程的一部分。稍后,当你链接引用A.dylib的B.dylib时,A.dylib的安装路径是 复制到 B.dylib。 (那是什么 otool 向您展示 - 那些复制的安装路径。)因此,最好首先在dylib中获得正确的安装路径。

在尝试让所有dylib一起工作之前,请分别检查每个dylib。然后构建它 otool -L 在建成的dylib上。每个架构的第一行应该是什么 LD_DYLIB_INSTALL_NAME 向你展示

一旦你有条理,尝试让dylib相互链接。它应该更加直截了当。


12
2018-03-21 05:21



虽然不是我想要的确切答案,但这有助于我找出问题所在。 otool -L 列出所有安装名称。列出的第一个“安装名称”是库本身的名称。列出的任何其他路径都是针对其依赖项的。假设您已从源代码编译了依赖项,在Xcode中设置“动态库安装名称”将正确设置这些路径。但是在我的情况下,依赖关系来自第三方,所以路径已经设置好了。由于我无法控制第三方库的编译,我不得不使用它 install_name_tool -change。 - BigMacAttack
很高兴你想出来了。 - Kurt Revis
非常有用的答案.. - Ahmed
@KurtRevis,假设我正在构建一个软件插件(基本上是DyLib本身)。我用libiomp5.dylib构建它,我的编译器。然而,东道主计划本身也有它。如何告诉我的插件在主机中搜索它(我可以知道@executable_path的路径)?谢谢。 - Royi
我在这里写了一个问题 - stackoverflow.com/questions/40318465/...。谢谢。 - Royi


install_name_tool 对于设置名称和路径非常有用。如果程序在构建目录中运行自检,那么它特别有用,然后在a期间发生变化 make install。在这种情况下,您可以使用 install_name_tool 无需单独构建。

install_name_tool 也很有用,因为Apple的LD不尊重 rpath Linux / GCC之类的链接器选项。也就是说,您需要使用一组不同的命令来设置它们。

这是它的手册页。它包含在内,因为它讨论了其他选项,例如 -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)

2
2017-12-21 02:01