我正在Linux上构建一个共享库,它作为某些软件(具体而言,扩展Mathematica)的“插件”使用。
我发现如果我在Ubuntu 16.04上构建,生成的库在RHEL 7.6上不起作用。但是,如果我在RHEL 7.6上构建,该库在RHEL和Ubuntu上都可以工作。
所谓“不起作用”,是指Mathematica拒绝加载它,但它只给出了一个通用且无用的“加载失败”的错误消息。
我已经排除了许多可能会破坏兼容性的因素,但我找不到更多的原因。这个问题是关于还有哪些因素可能影响兼容性,除了我下面列出的以外。
该库是用C和C++混合编写的,但导出了一个C接口。它使用“-static-libstdc++”和“-static-libgcc”进行构建。如果我在“.so”文件上使用“ldd”,它列出的唯一依赖关系是:
我发现如果我在Ubuntu 16.04上构建,生成的库在RHEL 7.6上不起作用。但是,如果我在RHEL 7.6上构建,该库在RHEL和Ubuntu上都可以工作。
所谓“不起作用”,是指Mathematica拒绝加载它,但它只给出了一个通用且无用的“加载失败”的错误消息。
我已经排除了许多可能会破坏兼容性的因素,但我找不到更多的原因。这个问题是关于还有哪些因素可能影响兼容性,除了我下面列出的以外。
该库是用C和C++混合编写的,但导出了一个C接口。它使用“-static-libstdc++”和“-static-libgcc”进行构建。如果我在“.so”文件上使用“ldd”,它列出的唯一依赖关系是:
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 和 这个 QA 的建议,我在定义 _GLIBCXX_USE_CXX11_ABI=0
后进行了编译。这确实解决了不兼容性问题。
但我仍然不理解为什么。错误消息抱怨缺少一个符号。这个符号通常从哪里加载?我以为如果我使用 -static-libstdc++
,那么它应该包含在我的库中。但这似乎是错误的。
虽然我似乎已经针对这个特定情况找到了实用的解决方案,但我希望能得到一些解释,以便将来可以自己解决类似的问题。
export LD_DEBUG=all
。也许它会产生一些调试输出,有助于解决问题。 - Ctxvtable for std::__cxx11::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >
,这个链接 https://dev59.com/E1wX5IYBdhLWcg3wyB_T 可能会有一些线索。 - SergeyA