结束语在动态库不同版本的静态库
-
25-09-2019 - |
题
在我的项目有(从现在起就叫libsomething
)从第三方的静态库的依赖性。近日,libsomething
在另外的版本可用。我的任务是为我的软件与旧的和新版本的支持。仅libsomething
的一个版本被用于在任何给定时间运行时,但是这是哪个版本应该程序运行之间可配置的。
我使用MSVC2005在WinXP,一个次要目的是成为准备切换到Linux和GCC。
由于libsomething
的两个版本都使用相同的符号,连接他们两个在我的可执行文件是出了问题的是两个版本的符号要在链接时在发生冲突的所有。
虽然我可以创建两个可执行文件(一个链接到的老版,另外一个使用新版本),我不能执行的决定上可执行的最终部署环境(遗留原因)来调用。
我想出了创建libsomething
的各个版本动态库包装,并在运行时根据一些配置文件联系起来的想法。随着MSCV,这将意味着走下去使用LoadLibrary()
,GetProcAddress()
等的道路,而在Linux上,我将不得不使用dlopen()
和dlsym()
。
据我所知,使用libtool
(即,libtldl
)被包裹在此平台依赖性用于使用共享库。这是遵循相应的路径?有没有更好的(或者至少是不同的)的方式?做libtldl
存在替代品的开源?
解决方案
这已经好几年了,但我想提的完整性另一种解决方案。代替手工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。
其他提示
我知道你说你不能用两个可执行文件,由于要执行的决定,但不能你exec
来回,这取决于在配置中选择版本的可执行文件之间?
在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归档选项之后在命令行上提及的每个存档,包括在档案中的每个对象文件 链接,而不是搜索存档所需的目标文件。这通常用于打开的存档文件到共享 要被包括在所产生的共享库库,迫使每个对象。这个选项可以多次使用。 点击 有两点需要注意利用gcc的这个选项的时候:首先,GCC不知道这个选项,那么你必须使用-Wl,-whole归档。 其次,不要忘记使用-Wl,你的档案的名单后-no-全存档,因为gcc将添加自己的档案清单到您 链接,你可能不希望这个标志会影响那些为好。
-soname =名,点击 当创建一个ELF共享对象,内部DT_SONAME字段设置为指定的名称。当一个可执行文件与链接 其中有一个DT_SONAME场共享对象,然后当可执行运行动态连接器将尝试加载共享对象 由DT_SONAME字段,而不是使用提供给链接器的文件名指定。