是什么决定了Linux上共享库的二进制兼容性?

Sza*_*lcs 8 c c++ linux shared-libraries abi

我正在Linux上构建一个共享库,它作为某些软件的"插件"(具体来说,它扩展了Mathematica).

我发现如果我构建在Ubuntu 16.04上,生成的库在RHEL 7.6上不起作用.但是,如果我在RHEL 7.6上构建,那么该库可以在RHEL和Ubuntu上运行.

通过"不工作",我指的是数学拒绝加载它,但它只是给出了一个通用的,无用的"加载失败"错误消息.

我已经消除了许多可能破坏兼容性的因素,我找不到了.这个问题是关于其他可能影响兼容性的问题,而不是我在下面列出

该库是用C和C++混合编写的,但它导出了一个C接口.它是用-static-libstdc++和建造的-static-libgcc.如果我ldd.so文件上使用它,它列出的唯一依赖项是:

linux-vdso.so.1 =>  (0x00007ffc757b9000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa286e62000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa287854000)
Run Code Online (Sandbox Code Playgroud)

不兼容的一个潜在来源是glibc版本.我查看了库中的符号,nm -gC我在Ubuntu上构建的最高GLIBC版本参考是2.14.RHEL 7.6有glibc 2.17,比2.14更新.因此,我不认为不相容是由于glibc.

还有什么可以导致在Ubuntu 16.04上编译的共享对象不能在RHEL 7.6上加载?


更新:我设法哄Mathematica给出一个更具描述性的错误(这是一个记录不完整的功能),所以我有一个具体的错误信息.在@ Ctx提出的建议中也可以看到同样的情况LD_DEBUG=all.

错误是:

IGraphM.so: undefined symbol: _ZTVNSt7__cxx1115basic_stringbufIcSt11char_traitsIcESaIcEEE
Run Code Online (Sandbox Code Playgroud)

(IGraphM.so是我的图书馆.)

除非我弄错了,否则这个函数似乎是libstdc ++的一部分.如果我指定-static-libstdc++并验证了ldd没有列出libstdc ++ ,为什么会出现此错误?


更新2:

根据SergeyA和本QA的建议,我在定义后编译_GLIBCXX_USE_CXX11_ABI=0. 这确实解决了不兼容问题.

但我仍然不明白为什么.错误消息抱怨缺少符号.这个符号通常从哪里加载?我的印象是,如果我使用-static-libstdc++,那么它应该包含在我的库中.这似乎是错误的.

虽然我似乎有一个实用的解决方案来解决这个特定情况的不兼容性,但我会感谢一些解释,所以将来我可以自己解决类似的问题.

Ser*_*eyA 4

我无法解释为什么您的 .so 库没有静态链接所有使用的符号(而是将它们保留为未定义),但我可以提供有关如何解决当前问题的实用建议。

您可以停止libstdc++静态链接到您的插件,而是使用可用于托管系统的插件。由于构建平台和目标平台之间的 ABI 不兼容,这对您不起作用。您可以通过指定宏来降级插件使用的 ABI _GLIBCXX_USE_CXX11_ABI=0