在我的项目中,第三方依赖于静态库(从现在开始称为libsomething
)。最近,libsomething
已在另一个版本中提供。我的任务是为我的软件提供旧版和新版的支持。在任何给定时间,在运行时只使用一个libsomething
版本,但在程序运行之间应该可以配置哪个版本。
我在WinXP上使用MSVC2005,第二个目标是准备切换到Linux和GCC。
由于libsomething
的两个版本都使用相同的符号,因此将它们都链接到我的可执行文件中是不可能的,因为两个版本的符号将在链接时发生冲突。
虽然我可以创建两个可执行文件(一个链接旧版本,另一个使用新版本),但我无法决定在最终部署环境中调用哪个可执行文件(遗留原因)。
我提出了为libsomething
的每个版本创建动态库包装器的想法,并根据某些配置文件在运行时链接它们。使用MSCV,这意味着要使用LoadLibrary()
,GetProcAddress()
等,而在Linux上,我必须使用dlopen()
和dlsym()
。
我理解使用libtool
(即libtldl
)包含此平台依赖项以使用共享库。这是一条合适的道路吗?是否有更好的(或至少是不同的)方式? libtldl
的替代方案是否作为开源存在?
答案 0 :(得分:2)
我知道你说由于决定执行哪个,你不能使用两个可执行文件,但是根据在配置中选择的版本,你不能在可执行文件之间来回exec
吗?
答案 1 :(得分:2)
在Linux上,您可以更轻松地链接到共享库并使用符号链接来更正版本 - IMO比使用dlopen()
+ dlsym()
更容易。
因此,您将为库的旧版本和新版本创建共享库:
g++ -shared -o libshared.so.1.1 -Wl,-soname=libshared.so.1 -L. -Wl,--whole-archive libstatic.a.old -Wl,-no-whole-archive
和
g++ -shared -o libshared.so.1.2 -Wl,-soname=libshared.so.1 -L. -Wl,--whole-archive libstatic.a.new -Wl,-no-whole-archive
创建符号链接:
ln -s libshared.so.1.1 libshared.so.1
ln -s libshared.so.1 libshared.so
构建应用程序,将其链接到旧版本的库。我想两个版本都是二进制兼容的(ABI没有坏掉),但是新版本可能有一些新的符号。
g++ -o myapp myapp.cpp -L. -lshared
由于共享库SONAME
为libshared.so.1
,您的应用程序将依赖于它,并将在libshared.so.1
或/etc/ld.so.conf
LD_LIBRARY_PATH
在运行应用程序之前,您可以将libshared.so.1
符号链接设置为指向libshared.so.1.2
或libshared.so.1.1
。
<小时/> 关于此处使用的链接器选项的信息很少:
- 全归档
对于--whole-archive选项后命令行中提到的每个存档,包括存档中的每个目标文件 链接,而不是在存档中搜索所需的目标文件。这通常用于将存档文件转换为共享文件 库,强制每个对象都包含在生成的共享库中。此选项可能不止一次使用。
从gcc使用此选项时的两个注意事项:首先,gcc不知道此选项,因此您必须使用-Wl,-whole-archive。 其次,不要忘记在归档列表之后使用-Wl,-no-whole-archive,因为gcc会将自己的归档列表添加到您的归档中 链接,你可能不希望这个标志也影响那些。-soname =名
创建ELF共享对象时,将内部DT_SONAME字段设置为指定的名称。当可执行文件与a链接时 具有DT_SONAME字段的共享对象,然后在运行可执行文件时,动态链接器将尝试加载共享对象 由DT_SONAME字段指定,而不是使用为链接器提供的文件名。
答案 2 :(得分:0)
现在已经有几年了,但我想提一下完整性的另一种解决方案。您可以为所有必需的函数生成简单的存根,而不是手动dlopen
和dlsym
,并且在第一次调用时(或在程序启动时)决定需要哪个库版本,加载它并解析地址。
您可以编写专门为您的项目量身定制的脚本,或使用Implib.so工具:
# This will generate mylib.so.init.c and mylib.so.tramp.S
# which implement stubs. These need to be linked to your
# executable.
$ implib-gen.py mylib.so
Implib.so仅适用于Linux,但应该很容易适应Windows。