_GLIBCXX_USE_CXX11_ABI,GCC 4.8和ABI兼容性

23

我们收到了一些编译为Linux (.a) 的库(可能是使用GCC 6.x编译的)。

我们正在使用GCC 4.8,但在链接时出现了以下类型的错误:undefined reference to std::__cxx11::basic_string

通常情况下,可以通过确保所有单元都使用相同的_GLIBCXX_USE_CXX11_ABI标志进行编译来解决此问题。但是,如果我理解正确,这是由GCC 5.1及以上版本引入的。

  1. 是否有办法使此方法与GCC 4.8配合使用,或者我们需要要求人们使用不同的_GLIBCXX_USE_CXX11_ABI重新编译库?
  2. 如果我们能够切换到GCC >= 5.1,那么我们就可以解决这个问题了吗?

谢谢!


2
还可以在 Red Hat 博客上查看 GCC5 和 C++11 ABI,GCC 手册中的 Dual ABI 以及 Stack Overflow 上的 由于 abi::cxx11 导致的链接问题?。这给我们带来了很多问题,特别是当 Clang 不支持 GCC5/C++11 时。这看起来像是你的重复问题,但它没有答案:我应该如何处理 gcc-4.9 和 gcc-5 之间的 ABI 不兼容性? - jww
1个回答

17

在gcc 4.8.2中使用C++11 ABI是可能的,但这是一种危险的做法;如果可能的话,最好向您的供应商请求使用以C++03 ABI编译的库(-D_GLIBCXX_USE_CXX11_ABI=0),或者升级到GCC 5或更高版本。

您需要下载并安装GCC 5,以便使用其libstdc++头文件和库,然后指示GCC 4.8优先使用它们。此外,由于GCC 4.8缺少GCC 5附带的一些intrinsics,因此您需要删除其使用。

例如,为了编译一个包含<string>的简单单文件应用程序:

/usr/local/gcc-4.8.2/bin/g++ \
   -std=c++11 \
   -D_GLIBCXX_USE_CXX11_ABI=1 \
   -D'__is_trivially_copyable(...)=0' \
   -D'__is_trivially_constructible(...)=0' \
   -D'__is_trivially_assignable(...)=0' \
   -nostdinc++ \
   -isystem /usr/local/gcc-5.4.0/include/c++/5.4.0/ \
   -isystem /usr/local/gcc-5.4.0/include/c++/5.4.0/x86_64-unknown-linux-gnu \
   -L /usr/local/gcc-5.4.0/lib64
   a.cpp

这是危险的,因为gcc 5.4 libstdc++不是为gcc 4.8设计的,重新定义使用的内部函数(__is_trivially_copyable等)可能会改变结构的布局或以其他方式导致程序与供应商库之间的二进制不兼容。

为了运行生成的可执行文件,您还需要确保动态链接器找到兼容的libstdc++,例如通过将/usr/local/gcc-5.4.0/lib64添加到/etc/ld.so.conf中,或者使用-Wl,-rpath /usr/local/gcc-5.4.0/lib64


可能加上-Wl,-rpath也有意义。 - yugr
哇,这是可怕(而酷)的东西!最好最小化风险,遵循安全路径并请求重新编译。 - Tanasis
升级gcc时,是否意味着我们必须同时更新内核?我看到新的工具链需要更新较新的gcc,这是否意味着我们必须更新内核? - ransh
@ransh 不应该要求更新的内核头文件,GCC 应该能够使用构建时存在的任何内核头文件。我不知道你在哪里看到“新的工具链需要更新的内核头文件”。 - Jonathan Wakely

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接