【问题标题】:How to handle dual ABI in GCC 5?如何在 GCC 5 中处理双 ABI?
【发布时间】:2015-11-03 13:26:28
【问题描述】:

我试图了解如何克服 GCC 5 中引入的双重 ABI 的问题。但是,我无法做到。这是一个重现错误的非常简单的示例。我使用的 GCC 版本是 5.2。如您所见,我的 main 函数(在 main.cpp 文件中)非常简单:

// main.cpp

#include <iostream>
#include <string>

int main()
{
    std::string message = "SUCCESS!";
    std::cout << message << std::endl;
}

当我输入时

/home/aleph/gcc/5.2.0/bin/g++ main.cpp

我收到以下错误消息:

/tmp/ccjsTADd.o: In function `main':
main.cpp:(.text+0x26): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&)'
main.cpp:(.text+0x43): undefined reference to `std::basic_ostream<char, std::char_traits<char> >& std::operator<< <char, std::char_traits<char>, std::allocator<char> >(std::basic_ostream<char, std::char_traits<char> >&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
main.cpp:(.text+0x5c): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
main.cpp:(.text+0x8c): undefined reference to `std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()'
collect2: erreur: ld a retourné 1 code d'état d'exécution

如果我将_GLIBCXX_USE_CXX11_ABI 的值更改为0,问题就消失了。

但是,如何使用默认 ABI 进行操作?

编辑:更简单的问题(删除 cmake 脚本)

【问题讨论】:

  • 在 gcc 5.x 和 gcc 4.x 两种情况下,make VERBOSE=1 是什么意思?实际上在这两种情况下使用不同的 gcc 吗?由于 cmake 缓存 CXX_COMPILER 值和在运行脚本(Cmakelists.txt)的时候你不能改变编译器
  • "如果您收到有关未定义引用符号的链接器错误,这些符号涉及 std::__cxx11 命名空间或标签 [abi:cxx11] 中的类型,则可能表明您正在尝试将目标文件链接在一起使用 _GLIBCXX_USE_CXX11_ABI 宏的不同值编译的“gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html
  • 我删除了构建存储库中的所有内容以避免任何缓存问题
  • 是的,可能存在兼容性问题,但我不知道如何检测,如何解决。
  • 如果我将 _GLIBCXX_USE_CXX11_ABI 宏的值更改为 0,以便使用旧的 ABI,我可以工作。但是,当 _GLIBCXX_USE_CXX11_ABI 设置为 1 时,我不知道如何使事情正常运行。我在 GCC 的目录中找不到任何链接器。

标签: c++ c++11 gcc c++14


【解决方案1】:

我通过向 gcc(-v 标志)添加更多详细信息找到了解决方案。如果您有同样的问题,您需要告诉 gcc 在包含您的发行版的 libstdc++ 版本的存储库中搜索库。换句话说,你应该尝试这样的事情:

/home/aleph/gcc/5.2.0/bin/g++ -L /home/aleph/gcc/5.2.0/lib64 main.cpp

之后应正确执行链接步骤。但是,您可能无法运行您的程序。进入

./a.out

可能会导致以下错误:

./a.out: relocation error: ./a.out: symbol _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcRKS3_, version GLIBCXX_3.4.21 not defined in file libstdc++.so.6 with link time reference

确实,您可以通过键入来检查您的可执行文件是否依赖于错误的 libstdc++ 版本

ldd a.out

这应该会导致这样的事情:

linux-vdso.so.1 =>  (0x00007ffebb722000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x0000003a71400000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x0000003d03a00000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x0000003a71000000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x0000003d02e00000)
/lib64/ld-linux-x86-64.so.2 (0x0000003d02a00000)

将 LD_LIBRARY_PATH 设置为您自己的 libstdc++ 版本的路径将解决问题:

LD_LIBRARY_PATH=/home/aleph/gcc/5.2.0/lib64 ./a.out

希望对你有帮助!

编辑:正如 Marc 所注意到的,可以修改 rpath,而不是修改环境变量 LD_LIBRARY_PATH。这是一个 CMake 配置脚本。

project (example CXX)

add_executable(main main.cpp)

if(GCC_ROOT)
    set(CMAKE_CXX_COMPILER ${GCC_ROOT}/bin/g++)
    target_link_libraries(main ${GCC_ROOT}/lib64/libstdc++.so)
    link_directories(${GCC_ROOT}/lib64)
endif(GCC_ROOT)

这个脚本可以和通常的组合一起使用

cmake ..
make

在“构建”子目录中。但也可以通过提供 GCC 发行版根目录的路径来选择我们自己的编译器:

cmake -D GCC_ROOT=/home/aleph/gcc/5.2.0 ..
make

脚本的编写使得 libstdc++ 的版本对应于输入 GCC 发行版的版本。

【讨论】:

  • -Wl,-rpath,/home/aleph/gcc/5.2.0/lib64 是 LD_LIBRARY_PATH 的替代品。
  • 是的,这是一个更好的选择。我在答案中添加了它的 cmake 版本。
  • 运行时错误(通过 rpaths 或 LD_LIBRARY_PATH 解决)是可以预料的,但不必使用 -L 告诉 g++ 如何找到自己的库。您的 GCC 5.2 安装出现问题。
猜你喜欢
  • 1970-01-01
  • 2016-07-18
  • 1970-01-01
  • 2018-08-03
  • 2021-11-26
  • 2015-12-15
相关资源
最近更新 更多