我可以强制动态库 link 到特定的动态库依赖项吗?

Can I force a dynamic library to link to a specific dynamic library dependency?

我正在构建一个动态库 libfoo.so,它依赖于 libcrypto.so

在我的 autotools Makefile.am 文件中,我有这样一行:

libfoo_la_LIBADD += -L${OPENSSL_DIR}/lib -lcrypto

其中 $OPENSSL_DIR 默认为 /usr 但可以通过传递 --with-openssl-dir=/whatever.

来覆盖

如何确保使用 libfoo.so 的可执行文件使用 ${OPENSSL_DIR}/lib/libcrypto.so(仅)而无需 人员构建或 运行ning 可执行文件必须将 rpath 或 fiddle 与 LD_LIBRARY_PATH 一起使用?

就目前情况而言,我可以构建 libfoo 并通过 --with-openssl-dir=/usr/local/openssl-special,并且构建良好。但是当我运行ldd libfoo.so时,它只是指向/usr/lib中的libcrypto.so

我能想到的唯一解决方案是将 libcrypto.a 静态链接到 libfoo.so。还有其他可行的方法吗?

运行时间动态 linking 的详细信息因平台而异。 Autotools 可以在一定程度上将您与此隔离开来,但是如果您关心细节(显然您很关心),那么让 Autotools 为您选择可能是不够的。

话虽如此,您似乎排除了几乎 所有 种可能性:

  • 确保在 运行 时获得在构建时 link 反对的特定实现的最可靠方法是静态地 link。但是你说你不想那样。

  • 如果您改为使用动态库,那么您将依赖动态 linker 在 运行 时将库实现与您的可执行文件相关联。在这种情况下,对于如何将 DL 定向到特定的库实现,有两种一般选择:

  1. 通过存储在程序/库二进制文件中的信息。您使用的术语表明 ELF-based 系统,对于 ELF 共享对象,RPATH 和/或 RUNPATH 传达有关在何处查找所需库的信息。没有与个别图书馆要求相关的路径信息;它们仅由 SONAME 标识。但是你说你不想使用 RPATH*,所以我想也不会 RUNPATH

  2. 通过动态的静态或动态配置linker。这是 LD_LIBRARY_PATH 的用武之地,但您说您不想使用它。动态 linker 通常还有一个或多个配置文件,例如 /etc/ld.so.conf。在那里您可以指定要搜索的库目录,并稍微注意搜索它们的顺序。

然后,您可以通过更新动态 linker 的配置文件使其首先搜索所需的路径,从而将所需的库实现 linked 到您的应用程序中。但是,这会影响整个系统,而且很脆弱。

或者,根据依赖性质的细节,你可以给你想要的 libcrypto 版本一个不同的 SONAME。实际上,就静态和动态 link 用户而言,这将使它成为一个不同的对象( 例如 libdjcrypto)。但这是有风险的,因为如果你的库对 libcrypto 有直接和间接的依赖,或者如果使用你的库的程序通过另一条路径依赖 libcrypto,那么你将在 运行 时间(动态地)结束 link使用两个库,甚至可能使用两个库中的函数,具体取决于每次调用的来源。

请注意 如果您也link 静态库,则上述问题应该是您关心的问题。如果这在你的库中留下任何对 libcrypto 的间接动态依赖,或者在使用你的库的程序中任何来自其他来源的动态依赖,那么你最终将同时使用多个版本的 libcrypto。

底线

对于 可执行文件,最好的选择是 (1) all-static linkage 或 (2)(对于 ELF)RPATH / LD_LIBRARY_PATH / RUNPATH,确保所有组件都通过相同的 SONAME 需要目标库。我倾向于提供一个设置 LD_LIBRARY_PATH 的包装脚本,这样它的作用范围就很窄了。

对于可重复使用的 ,“不要那样做”可能是最好的选择。同时使用另一个库(在您的情况下为 libcrypto)的两个不同版本来结束程序的可能性很高,这使得所有可用选项都没有吸引力。当然,除非您同意同一个程序使用多个库版本,在这种情况下 static linkage 和 RPATH / RUNPATH (但不是 LD_LIBRARY_PATH ) 是您最好的选择。


*请注意,至少某些版本的 libtool 有添加 RPATH 条目的习惯,无论您是否要求它们——需要注意的事情。您可能需要修补项目中安装的 libtool 脚本以避免出现这种情况。