我可以强制动态库 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 定向到特定的库实现,有两种一般选择:
通过存储在程序/库二进制文件中的信息。您使用的术语表明 ELF-based 系统,对于 ELF 共享对象,RPATH
和/或 RUNPATH
传达有关在何处查找所需库的信息。没有与个别图书馆要求相关的路径信息;它们仅由 SONAME 标识。但是你说你不想使用 RPATH
*,所以我想也不会 RUNPATH
。
通过动态的静态或动态配置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 脚本以避免出现这种情况。
我正在构建一个动态库 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 定向到特定的库实现,有两种一般选择:
通过存储在程序/库二进制文件中的信息。您使用的术语表明 ELF-based 系统,对于 ELF 共享对象,
RPATH
和/或RUNPATH
传达有关在何处查找所需库的信息。没有与个别图书馆要求相关的路径信息;它们仅由 SONAME 标识。但是你说你不想使用RPATH
*,所以我想也不会RUNPATH
。通过动态的静态或动态配置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 脚本以避免出现这种情况。