5

I try to understand how to overcome problems with the dual ABI introduced in GCC 5. However, I don't manage to do it. Here is a very simple example to reproduce errors. The version of GCC I use is 5.2. As you can see, my main function (in main.cpp file) is quite simple:

// main.cpp

#include <iostream>
#include <string>

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

When I type

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

I get the following error message:

/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

If I change the value of _GLIBCXX_USE_CXX11_ABI to 0, the problem disappears.

But, how to make things work with the default ABI?

EDIT: simpler question (removed cmake script)

m0nhawk
  • 22,980
  • 9
  • 45
  • 73
Aleph
  • 1,343
  • 1
  • 12
  • 27
  • What tell `make VERBOSE=1` in both cases gcc 5.x and gcc 4.x? does actually different gcc uses in both cases? Because of cmake cache CXX_COMPILER value and in running script (Cmakelists.txt) time you can not change compiler – fghj Nov 03 '15 at 13:36
  • "If you get linker errors about undefined references to symbols that involve types in the std::__cxx11 namespace or the tag [abi:cxx11] then it probably indicates that you are trying to link together object files that were compiled with different values for the _GLIBCXX_USE_CXX11_ABI macro" https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html – Ben Nov 03 '15 at 13:43
  • I remove evrything in build repository in order avoid any cache problem – Aleph Nov 03 '15 at 13:57
  • Yes, there may be a compatibility problem but I don't know how to detect it, and how to solve it. – Aleph Nov 03 '15 at 13:58
  • I works if I change the value of _GLIBCXX_USE_CXX11_ABI macro to 0, in order to use the old ABI. However, I don't know how to make things work well when _GLIBCXX_USE_CXX11_ABI is set to 1. I can't find any linker in GCC's directory. – Aleph Nov 03 '15 at 14:49
  • Indeed, moving to a higher gcc version doesn't update the libstdc++ if your OS uses the old ABI version. (centos 7 for example, with apps such as VSCode that don't run anymore) – Alexis May 05 '21 at 02:46

1 Answers1

8

I found the solution by adding more verbosity to gcc (-v flag). If you have the same problem, you need to tell gcc to search for libraries in the repository containing the libstdc++ version of your distribution. In other words, you should try something like this:

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

The linking step should be correctly performed after that. However, you may not be able to run your program. Entering

./a.out

may lead to the following error:

./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

Indeed, you can check that your executable depends on the wrong version of libstdc++ by typing

ldd a.out

which should lead to something like that:

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)

Set LD_LIBRARY_PATH to the path to your own version of libstdc++ will solve the problem:

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

Hope it helps!

EDIT: as noticed by Marc, it is possible to modify the rpath, instead of modifying the environment variable LD_LIBRARY_PATH. Here is a CMake configuration script to do it.

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)

This script can be used with the usual combo

cmake ..
make

in a 'build' subdirectory. But it is also possible to choose our own compilers by providing the path to the root of our GCC distribution:

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

The script is written so that the version of libstdc++ corresponds to the version of the input GCC distribution.

m0nhawk
  • 22,980
  • 9
  • 45
  • 73
Aleph
  • 1,343
  • 1
  • 12
  • 27
  • 2
    `-Wl,-rpath,/home/aleph/gcc/5.2.0/lib64` is an alternative to LD_LIBRARY_PATH. – Marc Glisse Nov 04 '15 at 13:26
  • Yes, and it's a better alternative. I add a cmake version of it in answer. – Aleph Nov 04 '15 at 16:29
  • 1
    The runtime errors (solved with rpaths or `LD_LIBRARY_PATH`) are to be expected, but it should not be necessary to use `-L` to tell g++ how to find its own libraries. Something is broken in your GCC 5.2 installation. – Jonathan Wakely Jun 06 '16 at 15:09