71

我读过一些不鼓励使用 DYLD_LIBRARY_PATH 的文章,因为动态库的路径应该使用 -install_name、@rpath 和 @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 目录...?
4

3 回答 3

85

正如您所指出的,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更加理智。这将在默认路径中提供的库中查找符号,如果在那里找不到符号,则回退到指定路径。

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

通常,当库安装到非标准位置时,应指定绝对路径,这可以消除动态查找的歧义。

于 2010-07-03T18:55:30.127 回答
11

DYLD_LIBRARY_PATH不像LD_LIBRARY_PATH. OS Xdlopen文档 ( 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 (叶名称来自 path ) ,然后是提供的路径(使用当前工作目录作为相对路径),然后是 $DYLD_FALLBACK_LIBRARY_PATH (叶子名称来自 path )。

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

dlopen("/Hello/libfoo.so", RTLD_NOW);
dlopen("/World/libfoo.so", RTLD_NOW);

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

于 2016-12-10T04:09:45.300 回答
8

有关动态链接编辑器的环境变量以及它们如何影响动态库搜索的文档,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 ,除了它不是总是覆盖,它只覆盖提供的库是更新的。

于 2016-01-20T16:16:08.320 回答