Is it OK to use DYLD_LIBRARY_PATH on Mac OS X? And, what's the dynamic library search algorithm with it?

我读过一些不鼓励使用 DYLD _ LIBRARY _ PATH 的文章,因为动态库的路径应该使用-install _ name、@rpath 和@loader _ path 修复。

In terms of making a program that runs both on Linux and Mac OS X, DYLD_LIBRARY_PATH of Mac OS X does exactly what LD_LIBRARY_PATH of Linux. And, we can share (almost) the same make file that doesn't have the -install_name and @rpath.

  • Is this OK to use DYLD_LIBRARY_PATH on Mac OS X?
  • 当二进制文件找不到动态库时,Mac OS X 的动态库搜索算法是什么?工作目录-> DYLD _ librARY _ PATH 目录... ?
110416 次浏览

正如您所注意到的,DYLD_LIBRARY_PATH的行为与其他 * nix 上的 LD_LIBRARY_PATH相似。然而,还有另一个环境变量你应该看看称为 DYLD_FALLBACK_LIBRARY_PATH

一般来说,这些建议(包括在 osx 和 linux 上)仅供开发使用,因为当您使用不具有相同符号表的库进行重写时,它们可能会导致符号查找错误。这方面的一个很好的例子是,尝试用自定义安装覆盖 VecLib 的默认安装(例如 blas lapack)。如果设置了 DYLD_LIBRARY_PATH,这将导致在链接到系统 VecLib 的应用程序中未发现符号错误,如果没有设置 DYLD_LIBRARY_PATH,则导致相反的结果(自定义应用程序中的符号查找错误)。这是由于系统 blas/lapack 不是 ATLAS 库的完整实现。

DYLD_FALLBACK_LIBRARY_PATH不会产生这些问题。

When installing libraries to a non-standard location, DYLD_FALLBACK_LIBRARY_PATH is much more sane. This will look for symbols in libraries provided in the default paths and if the symbol is not found there, fall back to the specified path.

这样做的好处是,在根据默认库编译的应用程序中,此过程不会导致符号查找错误。

In general, when libraries are installed to non-standard locations absolute paths should be specified which negates the ambiguity of the dynamic lookup.

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

DYLD _ Library _ PATH

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

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

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

DYLD_FALLBACK_LIBRARY_PATH

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

DYLD _ version _ Library _ PATH

这是一个冒号分隔的目录列表,其中包含可能的重写库。动态链接器在这些目录中搜索动态库。对于找到的每个库,dyld 查看其 LC _ ID _ DYLIB 并获取 current _ version 和 install name。然后,Dyld 在安装名称路径处查找库。当需要具有该安装名称的 dylib 时,将在流程中使用当前 _ version 值较大的值。这与 DYLD _ LIBRARY _ PATH 类似,只不过它不是总是重写,而是重写提供的库更新。

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 (使用 leaf name from path ), then the supplied path (using current working directory for relative paths), then $DYLD_FALLBACK_LIBRARY_PATH (with leaf name from 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?)