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

时间:2018-11-13 14:51:19

标签: c++ c linux shared-libraries abi

我正在Linux上构建一个共享库,它充当某些软件的“插件”(具体来说,它扩展了Mathematica)。

我发现,如果我基于Ubuntu 16.04构建,则生成的库无法在RHEL 7.6上运行。但是,如果我基于RHEL 7.6,则该库可同时在RHEL和Ubuntu上使用。

通过“不起作用”,我的意思是Mathematica拒绝加载它,但它只给出了通用且无用的“无法加载”错误消息。

我消除了许多可能破坏兼容性的因素,但我找不到更多因素。 这个问题是关于与我在下面列出的内容有关的其他因素可能会影响兼容性。

该库是用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)

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

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

除非我弄错了,否则此函数似乎是libstdc ++的一部分。如果我指定-static-libstdc++并验证ldd未列出libstdc ++,为什么会发生此错误?


更新2:

根据SergeyA和this QA的建议,我在定义_GLIBCXX_USE_CXX11_ABI=0之后进行了编译。 这确实可以解决不兼容问题。

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

虽然我似乎对此特定情况下的不兼容问题有一个切实可行的解决方案,但我希望您能提供一些解释,以便将来我可以自己解决类似的问题。

1 个答案:

答案 0 :(得分:4)

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

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