我们在旧的发布系统上编译了一组给定的遗留C ++库,使用libstdc ++。so.5.0.0编译旧的编译器gcc 3.2。最新的CentOS7将使用兼容性库libstdc ++。so.5.0.7运行在旧操作系统上编译的可执行文件,而具有不同库ABI的当前C ++版本是libstdc ++。so.6。
我们新版本的可执行文件是在新操作系统上构建的,无法再在旧平台上构建。但目前在CentOS7上重新编译遗留库也不是一个选择:数值结果会略有不同。所以我想使用它们与libstdc ++。so.5一样,而我的二进制文件的其余部分使用c ++版本。
this post建议使用与静态版本libstdc ++链接的包装器c接口库.a.5。
this post主要暗示相同。
在我们的例子中,这个方法似乎是可行的,因为接口只是C风格,不使用C ++对象。而且C-ABI似乎是c ++ lib两个版本之间的一种障碍。
但是,我还没有找到提供静态C ++。5库的人。另外我想我曾经在一个应用程序中听说过并行使用libstdc ++的两个共享库版本。那么还有一个保持共享C ++。5库的解决方案吗?我有一些弱的记忆,他们也使用C库作为边界。它也适用于dlopen()吗?
我目前的情况是这样的:
使用旧的gcc-3.2,libstdc ++。so.5,32位模式在旧操作系统上编译:
使用新的gcc-4.8.5在新操作系统上编译:
因此,可执行文件必须使用新的libstdc ++。so.6 for libC,但是会间接调用libA1,libA2,libB,它必须使用旧的libstdc ++。so.5。
我是否必须将包装器lib导出的符号完全限制在我的API中,而不是使用链接器的版本脚本标志来公开1中的pobedims注释中的任何c ++符号?
或许我只是将旧操作系统上的旧版lib链接到-lstdc ++,但使用全名/usr/lib/libstdc++.so.5? libB将继续从libA2中获取正确的符号吗?
我的可执行链接/依赖于......
可执行文件与-rdynamic链接,也许这是一个问题?如何确保使用同名可执行文件中的符号解析libA1,A2,B中的符号?
稍后修改/解决方案:
注1:尝试在旧平台上使用存档版本libstdc ++进行链接.a.5导致错误,该错误仅在更高版本的gcc> = 3.4中修复:
错误:ld:libwrapper.so:未定义的版本化符号名称_ZSt10time_put_w @@ GLIBCPP_3.2
ld:未能设置动态部分大小:错误值
所以这不是一个选择。
注2: LibB是一个问题,因为它是由工作库和可执行文件本身所期望的。如果可执行文件使用新版本的libB,则会引入libstdc ++。so.6,其中的符号将传递给worker libs,这会在启动时崩溃。我已经将用过的libB版本更改为旧系统上编译的版本,只需在运行时系统上进行交换即可。这是可能的,因为简单的C接口是二进制兼容的。因此,我的可执行文件(通过libB)和worker libs libA1和libA2都使用相同的libstdc ++。so.5。我的(C)可执行文件是直接链接libstdc ++。so.5构建的。现在我的可执行文件可以启动并运行。
注3:我发现参考结果和新结果之间存在一些数值差异。使用LD_PRELOAD机制已经解决了这些问题: LD_PRELOAD = libstdc ++。so.5 my_executable
这似乎很好用。我认为通过使用LD_PRELOAD,我确保libstdc ++。so.5在提供从libstdc ++解析的符号方面具有优势。我之前没有提到的:我们在旧平台上使用了英特尔编译器,我使用了数学库libimf.so,如下所示:LD_PRELOAD =" libimf.so libstdc ++。so.5"提供两个库。结果,数值差异消失了,这似乎是由普通数学函数的实现引起的。