如何在GCC 5中处理双重ABI

How to handle dual ABI in GCC 5?

本文关键字:处理 ABI GCC      更新时间:2023-10-16

我试图了解如何克服GCC 5中引入的双重ABI的问题。然而,我无法做到这一点。这里有一个非常简单的例子来重现错误。GCC I使用的版本是5.2。正如你所看到的,我的主要功能(在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(-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

希望它能有所帮助!

EDIT:正如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

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

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

编写该脚本时,libstdc++的版本与输入GCC发行版的版本相对应。