【问题标题】:Removing linker dependencies删除链接器依赖项
【发布时间】:2012-07-09 18:14:54
【问题描述】:
我正在使用 g++ 在 Linux 上开发一个 c++ 应用程序。我的应用程序链接在一个共享库中,该库公开了我需要的简单 API。这个库在内部引用了大量额外的共享库。我必须找到每一个并将它们添加到我的 Makefile 中才能将它们链接起来。
我假设我的应用程序必须链接到主库所依赖的任何库。解决此链接要求的唯一方法是在其所有依赖项的静态库中编译主库吗?这是否适用于通过 dlopen/dlsym 使用插件模型?
ty
【问题讨论】:
标签:
c++
c
linux
linker
g++
【解决方案1】:
解决这个链接要求的唯一方法是让主库在其所有依赖项的静态库中编译吗?
没有。共享库本身可以链接到它所依赖的共享库。大多数链接器也会选择这些库,并将您的可执行文件链接到这些库,而无需您在链接器阶段提及它们。
在您的情况下,听起来共享库没有链接到它所需的库。 ldd 工具在这方面很有用。
例如,假设您生成了这个共享库:
gcc -shared foo.o -o libfoo.so -lm
现在libfoo.so 已链接到数学库 (libm)。任何链接到 libfoo.so 的应用程序
也将链接到 libm,即您只需要这样做
gcc -o prog main.o -lfoo
另一方面,如果共享库没有链接到 lib,而是仅使用生成的
gcc -shared foo.o -o libfoo.so
在链接您的应用程序时,您必须明确链接到 libm:
gcc -o prog main.o -lfoo -lm
当您 dlopen() 共享库时,运行时链接器将加载共享库也链接到的所有库 - 除非它们已经加载。所以 - 如果你 dlopen() 的库没有链接到它所依赖的库,并且你的可执行文件也没有链接到这些库,dlopen() 将失败(除非你指定 RTLD_LAZY,在这种情况下事情稍后会失败)
【解决方案2】:
我假设我的应用必须链接到主库所依赖的任何库。
听起来好像您的应用直接使用了这些符号(不仅仅是通过 API 共享库间接使用)或共享库没有正确链接,所以它没有链接到它依赖的库。如果在创建该共享库时,它的依赖项是通过 -l 链接到的,那么在将您的应用链接到 API 库时,它会导致它们自动链接到。
是否是解决此链接要求的唯一方法,让主库在其所有依赖项的静态库中编译?
这是一种方式,但不是唯一的方式。
这是否适用于通过 dlopen/dlsym 使用插件模型?
只要插件正确链接到它们所依赖的库...不,在这种情况下,链接器不可能知道您将在运行时dlopen 的库,所以不知道它们的依赖关系是什么,所以你不需要在链接时命名它们。如果事先不知道所有可能被加载的插件,这是不可能的。
如果插件库未正确链接,您在尝试dlopen 它们时会遇到同样的问题。
【解决方案3】:
我假设我的应用程序必须链接到主库所依赖的任何库。解决此链接要求的唯一方法是让主库在其所有依赖项的静态库中编译吗?
偏离路线。没有办法解决:静态链接,或者在库运行时搜索路径中有库(正确的版本,如果不兼容 ABI)。
这是否适用于通过 dlopen/dlsym 使用插件模型?
没有。为此,您需要在要从中加载它的路径中拥有共享库。