在Mac OS X上使用DYLD_LIBRARY_PATH是否可以?而且,它的动态库搜索算法是什么?

pro*_*eek 51 language-agnostic macos dll dynamic-linking

我读了一些不鼓励使用DYLD_LIBRARY_PATH的文章,因为动态库的路径应该使用-install_name,@ aptath和@loader_path来修复.

在制作在Linux和Mac OS X上运行的程序方面,Mac OS X的DYLD_LIBRARY_PATH正好与Linux的LD_LIBRARY_PATH完全相同.而且,我们可以(几乎)共享同一个没有-install_name和@rpath的make文件.

  • 在Mac OS X上使用DYLD_LIBRARY_PATH可以吗?
  • 当二进制文件找不到动态库时,Mac OS X的动态库搜索算法是什么?当前目录 - > DYLD_LIBRARY_PATH目录......?

jky*_*yle 67

正如您所指出的,DYLD_LIBRARY_PATH行为与LD_LIBRARY_PATH其他*nix 相似.但是,您应该查看另一个环境变量DYLD_FALLBACK_LIBRARY_PATH.

通常,这些(在osx和linux上)仅建议用于开发用途,因为当您使用不具有相同符号表的库覆盖时,它们可能导致符号查找错误.一个很好的例子是当您尝试使用自定义安装覆盖VecLib的默认安装(例如blas lapack)时.这将导致链接到系统VecLib的应用程序中的符号未找到错误(如果DYLD_LIBRARY_PATH已设置)和反向(自定义应用程序中的符号查找错误)(如果不是).这是因为系统blas/lapack不是ATLAS库的完整实现.

DYLD_FALLBACK_LIBRARY_PATH 不会产生这些问题.

将库安装到非标准位置时,DYLD_FALLBACK_LIBRARY_PATH更加理智.这将在默认路径中提供的库中查找符号,如果在那里找不到符号,则返回到指定的路径.

好处是此过程不会在针对默认库编译的应用程序中导致符号查找错误.

通常,当库安装到非标准位置时,应指定绝对路径,这会消除动态查找的模糊性.

  • 这里看起来很奇怪:根据文档,如果`DYLD_FALLBACK_LIBRARY_PATH`是*not*set,则使用默认的库搜索路径.设置它将导致忽略默认路径,从而导致许多问题.(至少这是我在山狮中发现的情况.)如果你修改`DYLD_FALLBACK_LIBRARY_PATH`,那么你似乎必须小心手动添加默认值.(参见`man dlopen`.)我错过了什么吗? (5认同)
  • 出于安全原因,在El Capitan中似乎无法使用DYLD_FALLBACK_LIBRARY_PATH.有任何想法吗? (4认同)
  • 另一个好处 - 如果你设置`DYLD_LIBRARY_PATH`,X11将拒绝运行.但是如果设置`DYLD_FALLBACK_LIBRARY_PATH`,则可以同时拥有自定义库和X11.很棒的答案! (3认同)
  • Homebrew的人不喜欢`DYLD_FALLBACK_LIBRARY_PATH`:https://github.com/mxcl/homebrew/issues/13463 (3认同)

San*_*ens 6

DYLD_LIBRARY_PATH表现得不像LD_LIBRARY_PATH.OS X dlopen文档(https://developer.apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man3/dlopen.3.html)指定在提供绝对路径时,它将首先查看指定的位置通过DYLD_LIBRARY_PATH:

当path包含斜杠但不是框架路径(即完整路径或dylib的部分路径)时,dlopen()搜索以下内容,直到找到兼容的Mach-O文件:$ DYLD_LIBRARY_PATH(带路径的叶子名称) ,然后是提供的路径(使用相对路径的当前工作目录),然后是$ DYLD_FALLBACK_LIBRARY_PATH(来自路径的叶子名称).

换句话说,如果设置DYLD_LIBRARY_PATH/Hello,则以下两个dlopen调用:

dlopen("/Hello/libfoo.so", RTLD_NOW);
dlopen("/World/libfoo.so", RTLD_NOW);
Run Code Online (Sandbox Code Playgroud)

将解决/Hello/libfoo.so.这非常违反直觉,并且代表了一个安全漏洞.软件使用dlopen无法保证它正在加载正确的库(可能DYLD_LIBRARY_PATH在自己的环境中覆盖?)


Dou*_*son 5

有关动态链接编辑器的环境变量以及它们如何影响动态库搜索的文档,man dyld.

DYLD_LIBRARY_PATH

这是包含库的目录的冒号分隔列表。动态链接器在搜索库的默认位置之前先搜索这些目录。它允许您测试现有库的新版本。

对于程序使用的每个库,动态链接器依次在 DYLD_LIBRARY_PATH 中的每个目录中查找它。如果仍然找不到库,则依次搜索 DYLD_FALLBACK_FRAMEWORK_PATH 和 DYLD_FALLBACK_LIBRARY_PATH。

对 otool(1) 使用 -L 选项。发现可执行文件链接的框架和共享库。

DYLD_FALLBACK_LIBRARY_PATH

这是包含库的目录的冒号分隔列表。它用作安装路径中未找到的库的默认位置。默认情况下,它设置为 $(HOME)/lib:/usr/local/lib:/lib:/usr/lib。

DYLD_VERSIONED_LIBRARY_PATH

这是包含潜在覆盖库的目录的冒号分隔列表。动态链接器在这些目录中搜索动态库。对于找到的每个库,dyld 查看其 LC_ID_DYLIB 并获取 current_version 和安装名称。Dyld 然后在安装名称路径中查找库。每当需要具有该安装名称的 dylib 时,将在进程中使用具有较大 current_version 值的那个。这与 DYLD_LIBRARY_PATH 类似,除了不是总是覆盖,它只覆盖提供的库是更新的。

  • 请注意,`otool -L` 告诉您可执行文件是 _linked_ 的库,不一定是运行时实际加载的库。您可以通过设置`DYLD_LIBRARY_PATH` 并运行`otool`(显示的库路径不考虑`DYLD_LIBRARY_PATH`)来查看这一点。 (3认同)