使用共享库#

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

Windows、macOS 和 Linux 都提供了构建包含链接到其依赖的共享库的可执行文件和库的方法,而不是直接链接库本身。

Windows 中的共享库#

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

存在一种称为 并排程序集 的替代配置,它需要在嵌入的清单或与相关二进制文件一起的适当命名的 XML 文件中指定 DLL 版本。Conda 目前不使用并排程序集,但它将来可能会转向这种方式,以解决同一系统上同一库的多个版本引起的复杂情况。

目前,大多数 DLL 都安装在 (install prefix)\\Library\\bin 中。此路径被添加到所有 Python 进程的 os.environ["PATH"] 中,以便无论系统 PATH 环境变量的值如何,都可以找到 DLL。

注意

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

macOS 和 Linux 中的共享库#

在 macOS 和 Linux 中,动态链接的发现方式类似于 Python 模块通过 PYTHONPATH 发现,而可执行文件通过 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 来短路链接解析。

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

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