GCC not linking against libstdc++? - c++

I'm receiving C++ build errors on Ubuntu 16.04 (g++ 5.4) that I don't understand:
The linker errors are (taken a few of them and run them through c++filt)
undefined reference to symbol 'std::basic_stringbuf<char, std::char_traits<char>, std::allocator<char> >::str() const##GLIBCXX_3.4'
undefined reference to symbol 'std::condition_variable::notify_one()##GLIBCXX_3.4.11'
The command lanks I'm using are: gcc -std=c++11 -m64 -fPIC -std=c++11 ... (the ... has all the libs, etc.)
I assume I'm trying to link against /usr/lib/x86_64-linux-gnu/libstdc++.so.6. When I run strings against it, I see GLIBCXX_3.4 and GLIBCXX_3.4.11 (but I really don't know what this is indicating.)
nm shows me that the symbols (at least the condition_variable one is defined)
$ nm -DA /usr/lib/x86_64-linux-gnu/libstdc++.so.6 | c++filt | grep condition_variable::notify_one
/usr/lib/x86_64-linux-gnu/libstdc++.so.6:00000000000b3930 T std::condition_variable::notify_one()
I've run readelf on all the libraries I'm attempting to link, and they all appear to be built for the same ABI (GCC: (Ubuntu 5.4.0-6ubuntu1~16.04.9) 5.4.0 20160609)
Update
I noticed that the first error is resolved by explicitly linking against libstd++.so (i.e. I added stdc++ to my target_link_libraries in CMake). I was under the impression that I should never have to do this?

tl;dr: Invoke g++ rather than gcc to avoid this problem
(based on #SergeyA's comment)
GCC behaves differently depending on whether you run it as the gcc or the g++ binary. Specifically, it apparently won't automatically link against its bundled C++ standard library, libstdc++. I'm guessing it will link against its C standard library - which doesn't help you much.
So just use the appropriate binary for your language; specifying --std=c++whatever isn't enough.

Related

Which part of GCC is still involved when building with Clang++ and LLD?

I built a very simple program using Clang++/LLD:
clang++ -fuse-ld=lld -o test test.cpp
I than ran readelf to confirm that LLD was indeed used as the linker, as mentioned on https://releases.llvm.org/11.0.0/tools/lld/docs/index.html:
$ readelf --string-dump .comment test
String dump of section '.comment':
[ 0] Linker: LLD 7.0.1
[ 12] clang version 7.0.1-8+deb10u2 (tags/RELEASE_701/final)
[ 49] GCC: (Debian 8.3.0-6) 8.3.0
Very good, the linker used was indeed LDD. But it makes me wonder why GCC is still mentioned there. Maybe because the standard libraries were (presumably) build with GCC? Just wondering.
Depending on how you built libc++, you may still be using libgcc and libsupc++ to provide some routines otherwise provided by libc++abi and libcxxrt (and even then, there may still be some parts of libgcc required to make everything work).
Depending on the platform, there may still be some startup files or libc bits linked in which may or may not contain a string reference to GCC.
On Mac or BSD, for example nothing GCC should be involved anymore.
The Clang driver also (used to) use(s) GCC to infer e.g. library and header search paths, but I think it only does that as a fallback on unknown platforms.

Undefined symbols when using user operator in tensorflow-gpu>=1.15

everybody. I wrote some user operators to extend tensorflow and tried to use CMake to compile the code to different shared libraries to fit different versions of tensorflow.
It works fine with tensorflow-gpu<=1.14 but not with 1.15 and 2.0. I got the following error when loading the library.
tensorflow.python.framework.errors_impl.NotFoundError: build/lib/libtensorflow_ctext.so: undefined symbol: _ZN10tensorflow12OpDefBuilder4AttrENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
I tried nm build/lib/libtensorflow_ctext.so on 1.14 version and 2.0 version, both shared libraries have this undefined symbol in the middle.
U _ZN10tensorflow12OpDefBuilder4AttrENSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
It seems that the program is going to find this symbol in the linked Tensorflow framework library libtensorflow_framework.so. I searched libtensorflow_framework.so.2 for similar symbols and found several of them.
0000000000cacc50 T _ZN10tensorflow12OpDefBuilder10DeprecatedEiSs
0000000000cace00 T _ZN10tensorflow12OpDefBuilder10SetShapeFnESt8functionIFNS_6StatusEPNS_15shape_inference16InferenceContextEEE
0000000000cacb20 T _ZN10tensorflow12OpDefBuilder13ControlOutputESs
0000000000cac980 T _ZN10tensorflow12OpDefBuilder13SetIsStatefulEv
0000000000cac970 T _ZN10tensorflow12OpDefBuilder14SetIsAggregateEv
0000000000cac960 T _ZN10tensorflow12OpDefBuilder16SetIsCommutativeEv
0000000000cac990 T _ZN10tensorflow12OpDefBuilder27SetAllowsUninitializedInputEv
0000000000cacb50 T _ZN10tensorflow12OpDefBuilder3DocESs
0000000000caca90 T _ZN10tensorflow12OpDefBuilder4AttrESs
0000000000cacac0 T _ZN10tensorflow12OpDefBuilder5InputESs
0000000000cacaf0 T _ZN10tensorflow12OpDefBuilder6OutputESs
0000000000cac830 T _ZN10tensorflow12OpDefBuilderC1ESs
0000000000cac830 T _ZN10tensorflow12OpDefBuilderC2ESs
0000000000c702d0 W _ZN10tensorflow12OpDefBuilderD1Ev
0000000000c702d0 W _ZN10tensorflow12OpDefBuilderD2Ev
The symbol _ZN10tensorflow12OpDefBuilder4AttrESs looks very similar but different in the last several letters. I don't really know what those "ESs"s and "ENSt7"s stand for.
Hints on how I could debug it are very appreciated. Here is the command to build my shared library (generated by cmake)
g++ -fPIC -shared -Wl,-soname,libtensorflow_ctext.so -o lib/libtensorflow_ctext.so src/CMakeFiles/bp_par_2d.dir/bp_par_2d.cc.o src/CMakeFiles/bp_par_2d_sv.dir/bp_par_2d_sv.cc.o src/CMakeFiles/fp_par_2d.dir/fp_par_2d.cc.o src/CMakeFiles/filter.dir/filter.cc.o cuda/CMakeFiles/bp_par_2d_cu.dir/bp_par_2d.cu.o cuda/CMakeFiles/bp_par_2d_sv_cu.dir/bp_par_2d_sv.cu.o cuda/CMakeFiles/fp_par_2d_cu.dir/fp_par_2d.cu.o cuda/CMakeFiles/filter_cu.dir/filter.cu.o tensorflow/CMakeFiles/bp_par_2d_ops.dir/bp_par_2d_ops.cu.o tensorflow/CMakeFiles/bp_par_2d_sv_ops.dir/bp_par_2d_sv_ops.cu.o tensorflow/CMakeFiles/fp_par_2d_ops.dir/fp_par_2d_ops.cu.o tensorflow/CMakeFiles/ramp_filter_ops.dir/ramp_filter_ops.cu.o CMakeFiles/tensorflow_ctext.dir/cmake_device_link.o -L/usr/lib/x86_64-linux-gnu/stubs -Wl,-rpath,/home/ltl/anaconda3/envs/tf_test/lib/python3.7/site-packages/tensorflow_core /home/ltl/anaconda3/envs/tf_test/lib/python3.7/site-packages/tensorflow_core/libtensorflow_framework.so.2 -lcudadevrt -lcudart_static -lrt -lpthread -ldl
Well, this problem is solved.
I used nm -C instruction to look inside the .so files and found that in Tensorflow>=1.15.0, the function is defined as
0000000000caca90 T tensorflow::OpDefBuilder::Attr(std::string)
while in Tensorflow<=1.14.0, the function is defined as
0000000000c96ed0 T tensorflow::OpDefBuilder::Attr(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)
So, they use different settings on _GLIBCXX_USE_CXX11_ABI when compiling the shared library.
In order to be consistant and avoid those undefined symbol problems, I need to define -D_GLIBCXX_USE_CXX11_ABI=1 for early versions of Tensorflow and define -D_GLIBCXX_USE_CXX11_ABI=0 for later versions.

g++ undefined reference error when linking to third party shared libraries

I'm trying to link a c++ program that uses several shared libraries from 3rd parties. Mainly, these libraries come from a github project called MBSim and I downloaded the latest daily build with all its binaries, libraries and headers, which I installed on /usr/local/mbsim-env.
The most important libraries called are libmbsim, libopenmbvcppinterface, libfmatvec and libboost_filesystem (the last one comes with the MBSim distro).
I set up a simple code to test it and it compiles like a charm using
g++ main.cpp -m64 -g3 -std=c++11 -Wall
-Wfatal-errors -Werror -Wno-unknown-pragmas -fopenmp
`pkg-config --cflags mbsim` -I. -c -o main.o
The pkg-config part calls, as you can wonder, the include directories and flags:
-DHAVE_ANSICSIGNAL -DHAVE_OPENMBVCPPINTERFACE -DHAVE_BOOST_FILE_LOCK
-I/usr/local/mbsim-env/include
-I/usr/include/x86_64-linux-gnu
-I/usr/include/x86_64-linux-gnu/c++/5
-I/usr/local/include
My problems appear when I try to link the objects with the pre-compiled libraries with:
g++ system.o main.o -o teste -L/usr/local/mbsim-env/lib
-lmbsim -lopenmbvcppinterface -lboost_system
-lfmatvec -lm
-Wl,-rpath,/usr/local/mbsim-env/lib
Edit: On the above command, I've tried to use pkg-config --libs as well. The results remain the same.
First of all, the linker issues a warning that I'm linking against an older boost library:
/usr/bin/ld: warning: libboost_system.so.1.53.0,
needed by /usr/local/mbsim-env/lib/libmbsim.so,
may conflict with libboost_system.so.1.61.0
I'm aware of that, but I intentionally want to link against the old one because that's the one that was used to compile the MBSim libraries.
After that, I got several undefined reference warnings for almost every method that I call from MBSim:
system.cpp:59: undefined reference to
MBSim::RigidBody::RigidBody(std::__cxx11::basic_string<char,
std::char_traits<char>, std::allocator<char> > const&)'
It seems to me that this error means that the target libraries don't have the RigidBody method implemented. Well, I know they do.
My first guess was that maybe the linker was looking at the wrong library path, so I set LD_LIBRARY_PATH=/usr/local/mbsim-env/lib and added the -rpath to the same folder. That didn't help at all.
Some googling showed me that the problem could be compiling in 64bits and linking it against 32bits libs. I believe that's not the case: I've done everything in Ubuntu 16.04 64bits and the MBSim libraries are also 64bits.
Could somebody point me out of this dead end?
Could it be that your 3rd party shared libraries are compiled using an older version of GCC? There was a new ABI introduced in GCC 5. It's probably enabled by default on your platform. See https://gcc.gnu.org/onlinedocs/libstdc++/manual/using_dual_abi.html.
You could try switching to the older ABI, but that might require your other libraries to have been compiled with the old ABI also. You might also be able to switch ABIs for the 3rd party libraries explicitly.
undefined reference to MBSim::RigidBody::RigidBody(std::__cxx11::basic_string<std::char_traits<char>, std::allocator<char> > const&)
This is a reference to MBSim::RigidBody::RigidBody(const string&), compiled with g++ -std=c++11 and g++ version 5 or later.
As any1 probably correctly guessed, the binary for libmbsim.so that you downloaded was built with g++ 4.x, and defines the same function with this signature:
MBSim::RigidBody::RigidBody(std::basic_string<char, std::char_traits<char>,
std::allocator<char> > const&)
Note lack of __cxx11 namespace. You can easily confirm or disprove this:
nm -C libmbsim.so | grep 'MBSim::RigidBody::RigidBody'
If this mismatch is indeed the cause, simply rebuild this project from source with your compiler. That's what open source is for.

Undefined reference when combining C++ and Fortran [duplicate]

I am trying to link a .o file generated using g++ and another .o file generated using gfortran.
g++ -c mycppcode.cpp
produces the file mycppcode.o and the command
gfortran -c myfortrancode.f
produces the file myfortrancode.o
When I link these two files to get an output file
g++ -O mycppcode.o myfortrancode.o
I get the following error
Undefined symbols for architecture x86_64:
"__gfortran_pow_c8_i4", referenced from:
Could some one help me with this? Should I use another compiler? Also, I would like to know what functions or subroutines call "__gfortran_pow_c8_i4", so that I can try to avoid these functions or subroutines in fortran in future.
The following assumes you are using the GNU compiler tools. Things may be slightly different if you are using other compilers.
You can use either compiler to link the two together, but you need to provide the appropriate libraries.
Typically, you can use either
gfortran fortobj.o cppobj.o -lstdc++
or
g++ fortobj.o cppobj.o -lgfortran
This assumes that you are using a setup where both compilers know about each other's libraries (like if you installed through a linux repository).
In the case of the OP the C compilers came from XCode and gfortran is from homebrew. In that case, gfortran knows about the g++ libraries (since they were used to compile the compiler), but g++ doesn't know about the gfortran libraries. This is why using gfortran to link worked as advertised above. However, to link with g++ you need to add the path to libgfortran.* when you call the linker using the -L flag, like
g++ fortobj.o cppobj.o -L/path/to/fortran/libs -lgfortran
If for some reason your gfortran compiler is unaware of your g++ libs, you would do
gfortran fortobj.o cppobj.o -L/path/to/c++/libs -lstdc++
Note that there shouldn't be any difference in the final executable. I'm no compiler expert, but my understanding is that using the compiler to link your objects together is a convenience for calling the linker (ld on UNIX-like OS's) with the appropriate libraries associated with the language you are using. Therefore, using one compiler or the other to link shouldn't matter, as long as the right libraries are included.

ICC complains about missing __builtin_ia32_ldmxcsr

When compiling a project with Intel Composer 15 Update 3 on Linux, I get the following unresolved symbols on linking:
undefined reference to `__builtin_ia32_ldmxcsr'
undefined reference to `__builtin_ia32_stmxcsr'
Upon doing a Google search, I found that these functions are built in the 32-bit version of g++ which is why Intel can't find them. Firstly, I am compiling on a 64-bit OS with a 64-bit compiler; why is the linker looking for a function found only in 32-bit? Secondly, why is object code generated by Intel looking for a g++ built-in function?
Firstly, I am compiling on a 64-bit OS with a 64-bit compiler; why is the linker looking for a function found only in 32-bit?
Likely because some of your source code inappropriately references them.
First step: figure out which object(s) are referencing these builtins:
nm -A *.o *.a | egrep '__builtin_ia32_ldmxcsr|__builtin_ia32_stmxcsr'
Second step: preprocess the corresponding source to figure out where the references are coming from:
icpc -E -I ... bad_source.cpp