使用共享库#

共享库是与依赖于它们的程序和扩展松散耦合的库。当将可执行文件加载到内存中时,操作系统会找到所有依赖的共享库并将它们链接到可执行文件,以便它可以运行。

Windows、macOS 和 Linux 都提供了一种构建可执行文件和库的方法,这些文件和库包含指向它们所依赖的共享库的链接,而不是直接链接库本身。

Windows 中的共享库#

与 macOS 和 Linux 不同,Windows 没有将链接嵌入到二进制文件中的概念。相反,Windows 主要依赖于在目录中搜索匹配的文件名,如 Windows 用来定位 DLL 的搜索路径 中所述。

还有另一种配置,称为 并行程序集,它要求在嵌入的清单或与相关二进制文件放在一起的适当命名的 XML 文件中指定 DLL 版本。Conda 目前不使用并行程序集,但未来可能会转向它,以解决同一系统上同一库的多个版本带来的复杂问题。

目前,大多数 DLL 都安装到 (安装前缀)\\Library\\bin 中。此路径被添加到所有 Python 进程的 os.environ["PATH"] 中,以便可以定位 DLL,而无需考虑系统 PATH 环境变量的值。

注意

PATH 从左到右搜索,在没有清单另行指定的情况下,将选择第一个匹配的 DLL 名称。这意味着安装具有其他匹配 DLL 的软件可能会使您的系统以不可预测的方式崩溃。在 Windows 上进行故障排除或寻求支持时,始终将 PATH 视为潜在的问题来源。

macOS 和 Linux 中的共享库#

在 macOS 和 Linux 中,动态链接的发现方式类似于通过 PYTHONPATH 发现 Python 模块以及通过 PATH 发现可执行文件的方式。创建一个搜索位置列表,然后在搜索位置中搜索库对象。默认情况下,并且按设计,系统动态链接器对 conda 环境 lib 目录没有任何特殊偏好。

您可以指定绝对链接和相对链接。如果链接是绝对路径,例如 /Users/UserName/my_build_env,则该库仅在存在该确切路径的系统上有效。因此,conda 软件包中首选相对链接。

相对链接需要在链接本身中使用一个特殊变量

  • 在 Linux 上,$ORIGIN 变量允许您指定“相对于正在执行的此文件”。

  • 在 macOS 上,变量是

    • @rpath---允许您从系统加载路径设置相对链接。

    • @loader_path---等效于 $ORIGIN。

    • @executable_path---支持 Apple .app 目录方法,其中库知道它们相对于其调用应用程序的位置。

Conda-build 在 macOS 上使用 @loader_path,在 Linux 上使用 $ORIGIN,因为我们安装到公共根目录中,并且可以假定其他库也安装到该根目录中。变量的使用允许您构建可在一个系统上构建并发送到任何地方的可重定位二进制文件。

在 Linux 上,conda-build 通过调用 patchelf 工具来修改任何共享库或生成的可执行文件,以使用相对动态链接。在 macOS 上,使用 install_name_tool 工具。

警告

在 Linux 上设置 LD_LIBRARY_PATH 或在 macOS 上设置 DYLD_LIBRARY_PATH 可能会干扰这一点,因为动态链接器通过首先查看 LD_LIBRARY_PATH 来短路链接解析。

示例:您由于代码的某些兼容性问题而在 conda 环境中安装了旧版本的 libcurl。然后,您设置 export LD_LIBRARY_PATH=/home/UserName/envs/curl_env/lib。从那时起,您在该会话中执行的每个程序都将优先使用此 libcurl 而不是您的系统 libcurl,因为它现在有效地位于动态加载路径的“前面”。

不建议在 LD_LIBRARY_PATH 或 DYLD_LIBRARY_PATH 中包含 conda 环境路径。