How to handle dual ABI in GCC 5? - c++

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)

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.

Related

How to maintain compatibility between gcc 7 and gcc 9 with -Ofast

I have library which I have compiled on Ubuntu 18.04 using the version of gcc which comes bundled in the build-essential package, gcc 7.5.0.
If I then try to compile an application on Ubuntu 20.04 and link against the that library I previous built using the default gcc version, gcc 9.3.0, then I get a bunch of errors such as undefined reference to __expf_finite. Note, I do compile my original library with -Ofast as I need to take advantage of all optimizations. According to this SO question, it suggests that math-finite.h is no longer supported by the libc update.
So as a possible solution, I tried compiling my library on Ubuntu 20.04 using gcc 9.3.0 to then see if I can link against that library using an application compiled with gcc 7.5.0 on Ubuntu 18.04 (basically the reverse of the first scenario).
However, when I do this, I get ABI compat errors with std::string:
./trueface_sdk/libtf.a(ocl.cpp.o): In function `cv::ocl::Kernel::set(int, cv::ocl::KernelArg const&)':
ocl.cpp:(.text._ZN2cv3ocl6Kernel3setEiRKNS0_9KernelArgE+0x375): undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()'
ocl.cpp:(.text._ZN2cv3ocl6Kernel3setEiRKNS0_9KernelArgE+0x49d): undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()'
../trueface_sdk/libtf.a(ocl.cpp.o): In function `oclCleanupCallback.cold':
ocl.cpp:(.text.unlikely.oclCleanupCallback+0x36): undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()'
ocl.cpp:(.text.unlikely.oclCleanupCallback+0xcf): undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()'
ocl.cpp:(.text.unlikely.oclCleanupCallback+0x184): undefined reference to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()'
../trueface_sdk/libtf.a(ocl.cpp.o):ocl.cpp:(.text._ZN2cv3ocl6Device4ImplC2EPv[_ZN2cv3ocl6Device4ImplC5EPv]+0xb7b): more undefined references to `std::__cxx11::basic_stringstream<char, std::char_traits<char>, std::allocator<char> >::basic_stringstream()' follow
../trueface_sdk/libtf.a(sqlite3.c.o):(.data.rel+0xb0): undefined reference to `fcntl64'
I also get undefined reference to fcntl64.
So what is the solution? How can I compile a library that will be compatible with multiple version of gcc?
Based on the comments, it looks like it is not compatible because of the use of the -Ofast compiler optimization flag.

Undefined reference errors in RTI DDS when using modern c++ API

I generated RTI code using:
/opt/rti_connext_dds-6.0.0/bin/rtiddsgen -d GENERATED_CODE_DIR -language C++11 -replace IDL_DIR
My CMake file:
link_libraries(gsl gslcblas nnz12 occi clntsh dl nddsc nddscpp2 pthread)
add_definitions(-DRTI -DRTI_64BIT -DRTI_LINUX -DRTI_UNIX -D_GLIBCXX_DEBUG)
include_directories(-isystem /opt/rti_connext_dds-6.0.0/include/ndds)
include_directories(-isystem /opt/rti_connext_dds-6.0.0/include/ndds/hpp)
include_directories(-isystem /opt/rti_connext_dds-6.0.0/include/ndds/hpp/rti)
include_directories(-isystem /opt/rti_connext_dds-6.0.0/include/ndds/hpp/dds)
Now when compiling, I am getting following errors:
undefined reference to `rti::domain::register_type_plugin(dds::domain::TDomainParticipant<rti::domain::DomainParticipantImpl>&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, PRESTypePlugin* (*)(), void (*)(PRESTypePlugin*))'
undefined reference to `dds::core::PreconditionNotMetError::PreconditionNotMetError(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
collect2: error: ld returned 1 exit status
Is there anything I am missing ?
The problem was due to ABI. I am using gcc10.2.
I solved the problem by adding definition:
_GLIBCXX_USE_CXX11_ABI 0
The problem was due to the difference in ABIs of RTI libraries and the occi.so.
Solved the problem by using occi_gcc53.so instead of occi.so library.

Connecting c++ to mysql using mysql-c++-connector 8

I want to connect to mysql 8 using mysql-c++-connector8 (xdevapi) and I use .so file for linking but I get errors
here is my main.cpp file
#include <iostream>
#include <mysqlx/xdevapi.h>
using namespace ::mysqlx;
using std::cout;
using std::cin;
using std::endl;
int main(){
Session sess("localhost",3306,"root","mypass");
Schema db = sess.getSchema("university");
Collection myColl = db.getCollection("student");
DocResult myDocs = myColl.find("name like :param").execute();
cout<<myDocs.fetchOne();
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(1)
set(CMAKE_CXX_STANDARD 17)
include_directories(~/mysql-connector-c++/include)
link_directories(~/mysql-connector-c++/lib64)
set(PROJECT_LINK_LIBS libmysqlcppconn8.so)
add_executable(myExe main.cpp)
target_link_libraries(myExe ${PROJECT_LINK_LIBS})
Errors:
[ 50%] Linking CXX executable myExe
/usr/bin/ld: CMakeFiles/myExe.dir/main.cpp.o: in function `mysqlx::string::string(char const*)':
/home/amir/mysql-connector-c++/include/mysqlx/devapi/common.h:100: undefined reference to `mysqlx::string::Impl::from_utf8(mysqlx::string&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: CMakeFiles/myExe.dir/main.cpp.o: in function `mysqlx::string::string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)':
/home/amir/mysql-connector-c++/include/mysqlx/devapi/common.h:105: undefined reference to `mysqlx::string::Impl::from_utf8(mysqlx::string&, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)'
/usr/bin/ld: CMakeFiles/myExe.dir/main.cpp.o: in function `mysqlx::string::operator std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >() const':
/home/amir/mysql-connector-c++/include/mysqlx/devapi/common.h:115: undefined reference to `mysqlx::string::Impl::to_utf8[abi:cxx11](mysqlx::string const&)'
/usr/bin/ld: CMakeFiles/myExe.dir/main.cpp.o: in function `void mysqlx::internal::Settings_detail<mysqlx::internal::Settings_traits>::set<true, mysqlx::SessionOption, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, mysqlx::SessionOption, unsigned int&, mysqlx::SessionOption, mysqlx::string const&>(mysqlx::SessionOption, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, mysqlx::SessionOption&&, unsigned int&, mysqlx::SessionOption&&, mysqlx::string const&)':
/home/amir/mysql-connector-c++/include/mysqlx/devapi/detail/settings.h:67: undefined reference to `mysqlx::internal::Settings_detail<mysqlx::internal::Settings_traits>::do_set(std::__cxx11::list<std::pair<int, mysqlx::common::Value>, std::allocator<std::pair<int, mysqlx::common::Value> > >&&)'
/usr/bin/ld: CMakeFiles/myExe.dir/main.cpp.o: in function `void mysqlx::internal::Settings_detail<mysqlx::internal::Settings_traits>::set<true, mysqlx::SessionOption, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >(mysqlx::SessionOption, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >&&)':
/home/amir/mysql-connector-c++/include/mysqlx/devapi/detail/settings.h:67: undefined reference to `mysqlx::internal::Settings_detail<mysqlx::internal::Settings_traits>::do_set(std::__cxx11::list<std::pair<int, mysqlx::common::Value>, std::allocator<std::pair<int, mysqlx::common::Value> > >&&)'
/usr/bin/ld: CMakeFiles/myExe.dir/main.cpp.o: in function `void mysqlx::internal::Settings_detail<mysqlx::internal::Settings_traits>::set<true, mysqlx::SessionOption, mysqlx::string const&>(mysqlx::SessionOption, mysqlx::string const&)':
/home/amir/mysql-connector-c++/include/mysqlx/devapi/detail/settings.h:67: undefined reference to `mysqlx::internal::Settings_detail<mysqlx::internal::Settings_traits>::do_set(std::__cxx11::list<std::pair<int, mysqlx::common::Value>, std::allocator<std::pair<int, mysqlx::common::Value> > >&&)'
collect2: error: ld returned 1 exit status
make[3]: *** [CMakeFiles/myExe.dir/build.make:95: myExe] Error 1
make[2]: *** [CMakeFiles/Makefile2:68: CMakeFiles/myExe.dir/all] Error 2
make[1]: *** [CMakeFiles/Makefile2:80: CMakeFiles/myExe.dir/rule] Error 2
make: *** [Makefile:118: myExe] Error 2
I don't want to use legacy connectors as it is not recommended .
TL;DR; You need to use the old GCC ABI by setting the _GLIBCXX_USE_CXX11_ABI to 0. This can be done with cmake by adding the following to your CMakeLists.txt:
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
The issue comes from the "Linux - Generic" of the MySQL connector which have likely been built without the new CXX11 ABI of GCC (introduced in gcc 5.1).
Since your compiler is recent, the default is to use the new ABI, so when you include <mysqlx/xdevapi.h>, you create declarations such as:
mysqlx::string::Impl::from_utf8(
mysqlx::string&,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
...that use the new ABI (see the __cxx11 namespace).
But since the connectors have been built with the old ABI, the libmysqlcppconn8.so contains symbols for functions matching this kind of declaration:
mysqlx::string::Impl::from_utf8(
mysqlx::string&,
std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
You can check this by running readelf -Ws libmysqlcppconn8.so, for the "Linux - Generic" version I get (with a grep from_utf8)1:
1428: 00000000000a0a86 193 FUNC GLOBAL DEFAULT 12 _ZN6mysqlx6string4Impl9from_utf8ERS0_RKSs
9437: 00000000000a0a86 193 FUNC GLOBAL DEFAULT 12 _ZN6mysqlx6string4Impl9from_utf8ERS0_RKSs
But for the Ubuntu 18.10 version I get:
725: 00000000000a23e0 183 FUNC GLOBAL DEFAULT 12 _ZN6mysqlx6string4Impl9from_utf8ERS0_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
10141: 00000000000a23e0 183 FUNC GLOBAL DEFAULT 12 _ZN6mysqlx6string4Impl9from_utf8ERS0_RKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
The easiest fix is to tell your compiler to use the old ABI, so that the symbol will match. This can be done by setting the _GLIBCXX_USE_CXX11_ABI macro to 0 when compiling:
g++ -D_GLIBCXX_USE_CXX11_ABI=0 main.cpp
...or by adding the following to CMakeLists.txt:
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
If you use multiple external libraries, you have to be careful that those also use the old ABI, otherwise you will likely face the opposite issue, i.e., a library built with the new ABI cannot be used directly to build a program with the old ABI.
1 The "Linux - Generic" version contains reference to the CXX11 ABI, so I do not really know what is going on here. It looks like some parts of the library has been compile with the new ABI.
You may need to download the specific version for current OS instead generic-linux version.
for example rhel8 x86_64 platform, the mysql-connector-c++-8.0.23-1.el8.x86_64.rpm and mysql-connector-c++-devel-8.0.23-1.el8.x86_64.rpm should be downloaded. (https://dev.mysql.com/downloads/connector/cpp/)
Then unarchive that into same folder. (note if you have windows system, please unarchive it in linux since there's some soft link in it)
Then just using it without old CXX11ABI (need NOT to define _GLIBCXX_USE_CXX11_ABI=0)

undefined reference to boost::filesystem::path_traits::convert

I am trying to compile a program using cmake, and am seeing the following linker error:
/home/quant/bin/boost_1_61_0/stage/lib/libboost_log_setup.so:
undefined reference to
boost::filesystem::path_traits::convert(wchar_t const*, wchar_t
const*, std::__cxx11::basic_string<char, std::char_traits<char>,
std::allocator<char> >&, std::codecvt<wchar_t, char, __mbstate_t>
const&)' /home/quant/bin/boost_1_61_0/stage/lib/libboost_log.so:
undefined reference to
boost::filesystem::path_traits::dispatch(boost::filesystem::directory_entry
const&, std::__cxx11::basic_string,
std::allocator >&)'
The linker command that ninja generated looks like this:
g++ -pthread -DBOOST_ALL_DYN_LINK
utility/test/CMakeFiles/utilityTest.dir/loadCSVTests.cpp.o
utility/test/CMakeFiles/utilityTest.dir/main.cpp.o
utility/test/CMakeFiles/utilityTest.dir/randomDeviceTests.cpp.o -o
utility/test/utilityTest -rdynamic
/home/quant/bin/boost_1_61_0/stage/lib/libboost_thread.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_program_options.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_serialization.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_unit_test_framework.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_system.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_log.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_log_setup.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_filesystem.so
utility/lib/libutilityLib.a utility/testLib/libutilityTestLib.a
utility/lib/libutilityLib.a
/home/quant/bin/boost_1_61_0/stage/lib/libboost_thread.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_program_options.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_serialization.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_unit_test_framework.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_system.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_log.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_log_setup.so
/home/quant/bin/boost_1_61_0/stage/lib/libboost_filesystem.so
-Wl,-rpath,/home/quant/bin/boost_1_61_0/stage/lib
As you can see, I am linking against boost_filesystem and boost_system, so it's not the same problem as referenced on this SO post (and the many others like it).
I am using boost 1.61, which I compiled with gcc 5.3 (the same compiler as the one I'm compiling my program with).
What am I doing wrong?
I had a similar issue, this could be because of a new ABI which is introduced from gcc 5.1.
https://github.com/openframeworks/openFrameworks/issues/4203
I fixed mine by adding "add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)" to CMakeLists.txt

undefined reference to `__stack_chk_fail'

Getting this error while compiling C++ code:
undefined reference to `__stack_chk_fail'
Options already tried:
added -fno-stack-protector while compiling - did not work, error persists
added a dummy implementation of void __stack_chk_fail(void) in my code. Still getting the same error.
Detailed Error:
/u/ac/alanger/gurobi/gurobi400/linux64/lib/libgurobi_c++.a(Env.o)(.text+0x1034): In function `GRBEnv::getPar/u/ac/alanger/gurobi/gurobi400/linux64/lib/libgurobi_c++.a(Env.o)(.text+0x1034): In function `GRBEnv::getParamInfo(GRB_StringParam, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)':
: undefined reference to `__stack_chk_fail'
amInfo(GRB_StringParam, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&, std::basic_string<char, std::char_traits<char>, std::allocator<char> >&)':
: **undefined reference to `__stack_chk_fail'**
Earlier, I was getting 10's of such errors. Found out that there was a version mismatch between the gcc of the pre-compiled libraries I am using and the gcc version I was using to compile the code. Updated gcc and now I am getting only 2 of these errors.
Any help, please?
libgurobi_c++.a was compiled with -fno-stack-protector (obviously).
A few things come to mind:
add -fstack-protector when linking. This will make sure that libssp gets linked.
Manually link -lssp
Make your dummy version of __stack_chk_fail(void) in it's own object file and and add this .o file to your linker command AFTER libgurobi_c++.a. GCC/G++ resolves symbols from left to right during linking so despite your code having the function defined, a copy of an object containing the __stack_chk_fail symbol needs to be on the linker line to the right of libgurobi_c++.a.
In gentoo I had the same problem and i resolved creating 2 files. The first contain the option to be parsed by emerge and passed to gcc:
/etc/portage/env/nostackprotector.conf
CFLAGS="-fno-stack-protector -O2"
And the second tells which package should use this settings:
/etc/portage/package.env/nostackprotector
x11-libs/vte nostackprotector.conf
sys-libs/glibc nostackprotector.conf
www-client/chromium nostackprotector.conf
app-admin/sudo nostackprotector.conf
Just had the same issue: c++ code with an implementation of void __stack_chk_fail(void) showing several undefined reference to __stack_chk_fail errors when compiling.
My solution was to define __stack_chk_fail(void) as extern "C":
extern "C" {
__stack_chk_fail(void)
{
...
}
}
This suppressed the compilation error :)
Hope it helps!
https://wiki.ubuntu.com/ToolChain/CompilerFlags
says:
"Usually this is a result of calling ld instead of gcc during a build to perform linking"
This is what I encountered when modified the Makefile of libjpeg manually. Use gcc instead of ld solved the problem.