我们在旧的发布系统上编译了一组给定的遗留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版本6 .

this post建议使用与静态版本libstdc .a.5链接的包装器c接口库 .

this post主要暗示相同 .

在我们的例子中,这种方法似乎是可能的,因为接口只是C风格,不使用C对象 . 而且C-ABI似乎是两个版本的lib之间的一种障碍 .

但是,我还没有找到提供静态C.5库的人 . 另外我想我曾经听说过在一个应用程序中并行使用libstdc的两个共享库版本 . 那么还有一个保持共享C.5库的解决方案吗?我有一些弱的记忆,他们也使用C库作为边界 . 它也适用于dlopen()吗?

我目前的情况是这样的:

使用旧的gcc-3.2,libstdc .so.5,32位模式在旧操作系统上编译:

  • libA1.so使用C

  • libA2.so调用libB.so,两者都使用C,libA2与libstdc明确地链接到链接器选项-lstdc,libB没有,但可能它从libA获取它的符号

  • libwrapper.so只使用C而不是C,与/使用libA1和libA2链接 .

使用新gcc-4.8.5在新操作系统上编译:

  • 可执行文件(32位)通过使用dlopen()系统调用来调用libwrapper.so,因此间接调用C libs libA1.so和libA2 .

  • 可执行文件也使用共享的C lib libC.so(但接口是C风格)

  • 可执行文件还使用共享C lib libB.so(但接口是C样式),libA1和libA2也需要它 .

因此,可执行文件必须为libC使用新的libstdc .so.6,但会间接调用必须使用旧的libstdc .so.5的libA1,libA2,libB .

我是否必须将包装器lib导出的符号严格限制在我的API中,而不是使用链接器的版本脚本标志在1中暴露任何c符号,例如pobedims注释中的符号?

或者我可能只是将旧操作系统上的旧版lib链接到-lstdc,但使用全名/ usr / lib / libstdc .so.5? libB将继续从libA2获取正确的符号?

我的可执行链接/取决于......

  • libB.so(C)

  • libC.so(C)需要libstdc .6

  • libwrapper.so(带有C接口),使用动态加载dlopen()加载,它本身链接到"worker" libA1和libA2(它也提供了一个C接口):

  • libA1.so使用C.5

  • libA2.so使用C.5

  • libB.so使用C.5

可执行文件与-rdynamic链接,也许这是一个问题?如何确保使用同名可执行文件中的符号解析libA1,A2,B中的符号?

Edit later / Resolution :注意1:尝试在旧平台上使用存档版本libstdc .a.5进行链接会导致错误,该错误仅在更高版本的gcc> = 3.4中修复:
错误:ld:libwrapper.so:未定义的版本化符号名称_ZSt10time_put_w @@ GLIBCPP_3.2
ld:未能设置动态部分大小:错误值

所以这不是一个选择 .

注2:LibB是一个问题,因为它是由工作库和可执行文件本身所期望的 . 如果可执行文件使用新版本的libB,则会引入libstdc .so.6,其中的符号将传递给工作者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”来提供两个库 . 结果,数值差异消失了,这似乎是由普通数学函数的实现引起的 .