【发布时间】:2020-02-27 02:51:10
【问题描述】:
我正在使用 gcc 7.3 在 Ubuntu 16.04 和 Red Hat 7 上构建一个小型 .so 库。当我使用 nm 命令检查导出符号名称时,我发现在 Ubuntu 上编译的库使用 cxx11 ABI,但在 RedHat 上编译的库没有。
例如,在 Ubuntu 上编译的函数的导出符号如下所示。
_Z12customLoad3DPKN8nlohmann10basic_jsonISt3mapSt6vectorNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEEblmdSaNS_14adl_serializerEEEPP11IVolumeDataPSA_
但相同的导出符号在 RedHat 上编译时看起来像这样。
_Z12customLoad3DPKN8nlohmann10basic_jsonISt3mapSt6vectorSsblmdSaNS_14adl_serializerEEEPP11IVolumeDataPS4_
两个库都使用相同的 makefile。该代码使用#define _GLIBCXX_USECXX11_ABI 1 和命令行选项-std=c++11。我还尝试使用具有不同值的 -fabi-version 选项,但均无效。我无法用#ifdef __cplusplus extern "C" 方法解决这个问题,因为这些函数使用模板类参数。
如何强制 RedHat 上的 gcc 使用 cxx11 ABI?我不能使用双 ABI 链接,因为 .so 库用作应用程序的插件,该应用程序在运行时使用硬编码的重编码列表链接到库中的函数。该插件无法在 Red Hat 上运行,因为损坏的名称与程序的预期不符。我该如何解决这个问题?
谢谢!
【问题讨论】:
-
你确定在red hat中使用gcc 7吗?
-
在我看来,这个“插件”是被设计破坏的。 Fedora/Red Hat 和我认为 Ubuntu 都在其发行版各自的编译器和 C++ 库中包含小补丁。无论如何,不能保证 C++ 编译器即使具有相同的基本版本,但在不同的 Linux 发行版上,也会产生相同的名称修饰。您不能依赖损坏的符号。
-
@oblivion 和 devtoolset-7 它是。您还可以使用 devtoolset-8 获得 GCC 8。在我工作的地方,我们通过 devtoolset-8 在 RHEL7 上使用 GCC 8 和 C++17 - 完全支持。
-
@JesperJuhl 确定,但默认情况下未启用。
-
我很肯定我正在使用 gcc 7.3。我自己安装了它,gcc -v 命令报告 7.3。我注意到当我调用 gcc -v 时,它会报告选项 --with-default-libstdcxx-abi=gcc4-compatable。这是否会导致使用旧的 ABI?
标签: c++ linux gcc name-mangling