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)
The library ABI is mostly of interest for end-users who have unresolved symbols and are linking dynamically to the C++ Standard library, and who thus must be careful to compile their application with a compiler that is compatible with the available C++ Standard library binary.
clang, modulo bugs, is fully C++ ABI compatible with GCC (they both follow the intervendor Itanium ABI) on unix systems. Make sure you use the same standard library for all components because libstdc++ and libc++ are different implementations with completely different object layouts.
Without a stable ABI, all parts of a program must be compiled with the same version of the same compiler. That situation creates a maintenance nightmare for distributed projects, particularly for suppliers of binary libraries. The early rapid evolution of the C++ programming language precluded a stable ABI.
In computer software, an application binary interface (ABI) is an interface between two binary program modules. Often, one of these modules is a library or operating system facility, and the other is a program that is being run by a user.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With