简体   繁体   English

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

[英]Can I force a dynamic library to link to a specific dynamic library dependency?

I'm building an dynamic library, libfoo.so , which depends on libcrypto.so . 我正在构建一个动态库libfoo.so ,它依赖于libcrypto.so

Within my autotools Makefile.am file, I have a line like this: 在我的自动工具Makefile.am文件中,我有这样一行:

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

where $OPENSSL_DIR defaults to /usr but can be overridden by passing --with-openssl-dir=/whatever . 其中$OPENSSL_DIR默认为/usr但可以通过传递--with-openssl-dir=/whatever来覆盖。

How can I ensure that an executable using libfoo.so uses ${OPENSSL_DIR}/lib/libcrypto.so (only) without the person building or running the executable having to use rpath or fiddle with LD_LIBRARY_PATH ? 如何确保使用libfoo.so的可执行文件使用${OPENSSL_DIR}/lib/libcrypto.so (仅), 而无需构建或运行该可执行文件的人必须使用rpathLD_LIBRARY_PATH来摆弄?

As things stand, I can build libfoo and pass --with-openssl-dir=/usr/local/openssl-special and it builds fine. 就目前情况而言,我可以构建libfoo并通过--with-openssl-dir=/usr/local/openssl-special ,它可以正常运行。 But when I run ldd libfoo.so , it just points to the libcrypto.so in /usr/lib . 但是,当我运行ldd libfoo.so ,它仅指向/usr/liblibcrypto.so

The only solution I can think of is statically linking libcrypto.a into libfoo.so . 我能想到的唯一解决方案是将libcrypto.a静态链接到libfoo.so Is there any other approach possible? 还有其他可能的方法吗?

Details of runtime dynamic linking vary from platform to platform. 运行时动态链接的详细信息因平台而异。 The Autotools can insulate you from that to an extent, but if you care about the details, which apparently you do, then it probably is not adequate to allow the Autotools to choose for you. 自动工具可以在某种程度上使您与之隔离,但如果您关心细节(显然是您这样做的),则可能不足以让自动工具为您选择。

With that said, however, you seem to be ruling out just about all possibilities: 话虽如此,但您似乎在排除所有可能性:

  • The most reliable way to ensure that at runtime you get the specific implementation you linked against at build time is to link statically. 确保在运行时获得在构建时链接的特定实现的最可靠方法是静态链接。 But you say you don't want that. 但是你说你不想那样。

  • If you instead use dynamic libraries then you rely on the dynamic linker to associate a library implementation with your executable at run time. 如果改用动态库,则在运行时依靠动态链接器将库实现与可执行文件相关联。 In that case, there are two general choices for how you can direct the DL to a specific library implementation: 在这种情况下,对于如何将DL定向到特定的库实现,有两种常规选择:

    1. Via information stored in the program / library binary . 通过信息存储在程序/库的二进制文件中 You are using terminology that suggests an ELF-based system, and for ELF shared objects, it is the RPATH and / or RUNPATH that convey information about where to look for required libraries. 您使用的术语暗示了基于ELF的系统,对于ELF共享对象,正是RPATH和/或RUNPATH传达了有关在哪里寻找所需库的信息。 There is no path information associated with individual library requirements; 没有与单个库要求相关联的路径信息; they are identified by SONAME only. 它们仅由SONAME标识。 But you say you don't want to use RPATH * , and so I suppose not RUNPATH either. 但是你说你不想使用RPATH *,所以我想不RUNPATH无论是。

    2. Via static or dynamic configuration of the dynamic linker . 通过静态或动态配置的动态链接器 This is where LD_LIBRARY_PATH comes in, but you say you don't want to use that. 这就是LD_LIBRARY_PATH来源,但是您说您不想使用它。 The dynamic linker typically also has a configuration file or files, such as /etc/ld.so.conf . 动态链接器通常还具有一个或多个配置文件,例如/etc/ld.so.conf There you can specify library directories to search, and, with a bit of care, the order to search them. 您可以在此处指定要搜索的库目录,并稍加注意,以搜索它们的顺序。

Possibly, then, you can cause your desired library implementation to be linked to your application by updating the dynamic linker's configuration files to cause it to search the wanted path first. 然后,可以通过更新动态链接程序的配置文件,使它首先搜索所需的路径,来使所需的库实现链接到应用程序。 This will affect the whole system, however, and it's brittle. 但是,这会影响整个系统,而且很脆弱。

Alternatively, depending on details of the nature of the dependency, you could give your wanted version of libcrypto a distinct SONAME. 或者,根据依赖项的性质的详细信息,您可以为所需的libcrypto版本提供不同的SONAME。 Effectively, that would make it a different object ( eg libdjcrypto) as far as the static and dynamic linkers are concerned. 实际上,就静态和动态链接器而言,这将使其成为一个不同的对象( 例如 libdjcrypto)。 But that is risky, because if your library has both direct and indirect dependencies on libcrypto, or if a program using your library depends on libcrypto via another path, then you'll end up at run time (dynamically) linking both libraries, and possibly even using functions from both, depending on the origin of each call. 但这是有风险的,因为如果您的库同时具有对libcrypto的直接和间接依赖关系,或者如果使用您的库的程序通过另一路径依赖于libcrypto,那么您将在运行时(动态地)链接两个库,并且可能甚至使用两个函数,具体取决于每个调用的来源。

Note well that the above issue should be a concern for you if you link your library statically, too. 请注意 ,如果您也静态链接库,则上述问题也应该引起您的注意 If that leaves any indirect dynamic dependencies on libcrypto in your library, or any dynamic dependencies from other sources in programs using your library, then you will end up with multiple versions of libcrypto in use at the same time. 如果这在您的库中对libcrypto留下了任何间接动态依赖关系,或者在使用该库的程序中来自其他源的任何动态依赖关系,那么您最终将同时使用多个版本的libcrypto。

Bottom line 底线

For an executable , the best options are either (1) all-static linkage or (2) (for ELF) RPATH / LD_LIBRARY_PATH / RUNPATH , ensuring that all components require the target library via the same SONAME . 对于可执行文件 ,最佳选择是(1)全静态链接或(2)(对于ELF) RPATH / LD_LIBRARY_PATH / RUNPATH ,以确保所有组件都需要通过同一SONAME进行目标库。 I tend to like providing a wrapper script that sets LD_LIBRARY_PATH , so that that its effect is narrowly scoped. 我倾向于提供一个设置LD_LIBRARY_PATH的包装器脚本,以便使其作用范围狭窄。

For a reusable library , "don't do that" is probably the best alternative. 对于可重用的 ,“不要这样做”可能是最好的选择。 The high potential for ending up with programs simultaneously using two different versions of the other library (libcrypto in your case) makes all available options unattractive. 使用另一个库的两个不同版本(在本例中为libcrypto)同时结束程序的可能性很高,这使得所有可用选项都没有吸引力。 Unless, of course, you're ok with multiple library versions being used by the same program, in which case static linkage and RPATH / RUNPATH (but not LD_LIBRARY_PATH ) are your best available alternatives. 当然,除非您RPATH同一程序使用多个库版本,否则静态链接和RPATH / RUNPATH (但不是LD_LIBRARY_PATH )是您最佳的选择。


* Note that at least some versions of libtool have a habit of adding RPATH entries whether you ask for them or not -- something to watch out for. *请注意,至少某些版本的libtool习惯于添加RPATH条目,无论您是否要求它们-都需要提防。 You may need to patch the libtool scripts installed in your project to avoid that. 您可能需要修补安装在项目中的libtool脚本,以避免这种情况。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM