Undefined reference to `sc_dt::sc_uint_base::to_string[abi:cxx11] - c++

I have some code using the SystemC library which compiles fine when I'm physically at the machine, but throws undefined references when I'm ssh'ing in.
g++ -Wno-deprecated -O0 -g3 -I/path/to/include socex2.cpp -L/path/to/lib -lsystemc
/tmp/ccCNdiMA.o: In function `sc_dt::sc_uint_base::print(std::ostream&) const':
/path/to/include/sysc/datatypes/int/sc_uint_base.h:844: undefined reference to `sc_dt::sc_uint_base::to_string[abi:cxx11](sc_dt::sc_numrep, bool) const'
collect2: error: ld returned 1 exit status
At first I thought it was a problem with LD_LIBRARY_PATH, set in ~/.bashrc to /path/to/lib. I source ~/.bashrc in ~/.bash_profile for non-interactive sessions such as ssh.
To verify, here's the relevant bits of /usr/bin/env:
TERM=xterm
SHELL=/bin/bash
SSH_CLIENT=xx.xx.xx.xx 56176 22
LD_LIBRARY_PATH=/path/to/lib
SSH_CONNECTION=xx.xx.xx.xx 56176 yy.yy.yy.yy 22
_=/usr/bin/env
Why won't my program link? The headers and libraries I'm using are exactly the same and in the exact same places.
P.S.
I don't have admin access on these machines
gcc is 5.4.0
OS is Ubuntu 16.04
Dependent libraries:
$ ldd /path/to/lib/libsystemc.so
linux-vdso.so.1 => (0x00007ffe29d36000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fb9b85f5000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fb9b8273000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fb9b7f69000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fb9b7ba0000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fb9b798a000)
/lib64/ld-linux-x86-64.so.2 (0x000056093a23e000)

...to_string[abi:cxx11] ...
One of two things...
First, GCC and Clang are being mixed and matched. If you were compiling with Clang, this would be a likely suspect because of GCC5 and the C++11 ABI and LLVM Issue 23529: Add support for gcc's attribute abi_tag (needed for compatibility with gcc 5's libstdc++).
Second, to_string is C++11, so you need either -std=c++11 or -std=gnu++11. C++11 is the likely candidate if all other things are equal. It also gets you the new ABI unless you -D_GLIBCXX_USE_CXX11_ABI=0.
You could still have problems with dependent library configurations, and they could be surfacing in your question.

Related

Why linux ld somtime use the symbolic link of libs

I use the jsoncpp lib in my linux cli tool.
The CMakeLists.txt contains
find_library(LIB_JSON jsoncpp)
target_link_libraries(${PROJECT_NAME} ${LIB_JSON})
The result is
/usr/bin/c++ -rdynamic CMakeFiles/cktwagent.dir/agent_main.cpp.o -o cktwagent -ljsoncpp
When i check the binary I found:
$> ldd cktwagent
linux-vdso.so.1 (0x00007ffe4cfd1000)
libjsoncpp.so.24 => /usr/lib/libjsoncpp.so.24 (0x00007f87505bd000)
libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007f87503e0000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f875029a000)
libgcc_s.so.1 => /usr/lib/libgcc_s.so.1 (0x00007f8750280000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f87500b7000)
/lib64/ld-linux-x86-64.so.2 => /usr/lib64/ld-linux-x86-64.so.2 (0x00007f87506ce000)
Why ld use /usr/lib/libjsoncpp.so.24 and not the symbolic link /usr/lib/libjsoncpp.so?
Why the ld sometime resolv the linbrary link to the real library file?
$> ls -l /usr/lib/libjsoncpp.so
lrwxrwxrwx 1 root root 16 26. Sep 17:02 /usr/lib/libjsoncpp.so -> libjsoncpp.so.24
In case of /usr/lib/libstdc++.so.6 the ld use the symbolic link. When i check the path from ldd output, libstdc++.so.6 point to a symbolic link.
$> ls -l /usr/lib/libstdc++.so.6
lrwxrwxrwx 1 root root 19 9. Nov 12:43 /usr/lib/libstdc++.so.6 -> libstdc++.so.6.0.28
I like to understand this behavior. Because when i copy the binary to a different system, the link to libjsoncpp.so available. But it points to some different version.
Many thanks
Thomas
That's a version compatibility feature. By convention, API compatibility is determined by the major version number. So 6.0.28 would be is compatible with 6.1.1, but not with 5.0.1 or 7.0.1.
To allow for compatible upgrades, libstdc++.so.6.0.28 is symlinked as libstdc++.so.6. Then it can be binary-upgraded to e.g. libstdc++.so.6.0.29 without touching applications that rely on API version 6 of libstdc++.
In addition, it allows libraries with different major version numbers to coexist on the same system. Installing libstdc++.so.7.0.0 will not break apps that link against libstdc++.so.6.
Why ld use /usr/lib/libjsoncpp.so.24 and not the symbolic link /usr/lib/libjsoncpp.so?
That's because libjsoncpp has a soname of libjsoncpp.so.24. Apparently it is following the same convention of having the major version number determine compatibility.
You can achieve the same behavior with your shared lib libfoo if you link it like this:
gcc -shared -Wl,-soname,libfoo.so.<major> -o libfoo.so.<major>.<minor>
For more details refer to GCC Howto - Version numbering, sonames and symlinks.

Unable to use libc++ with clang++-5.0

I've installed clang++-5.0 to try out new C++17 features, but to get the full experience I need a new library. After being unable to find newer libstdc++, I decided to try out libc++.
I've checked it out using similar way described here.
After checkout, I've compiled it with clang itself, since it was advised to use clang. Compilation went without problems. Then I installed it, make put them in the /usr/local/include/c++/v1 directory.
When I tried to compile anything, I was getting an error saying the compiler couldn't find <stddef.h>. I solved the problem with "redirecting" the includes: -isystem /usr/local/include/c++/v1.
But then linker throws a lot of errors related to exceptions and virtual tables. I have no idea what to do in this case.
Is it possible to fix it?
My setup: ubuntu 16.04 LTS with all updates, clang++-5.0, cmake-3.6 .
Here are my flags:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v -stdlib=libc++ -Wall -Wextra -pedantic-errors -std=c++1z -isystem /usr/local/include/c++/v1")
Excerpt from error messages:
//usr/local/lib/libc++.so: undefined reference to `__cxa_end_catch'
//usr/local/lib/libc++.so: undefined reference to `__cxa_pure_virtual'
//usr/local/lib/libc++.so: undefined reference to `__cxa_rethrow'
//usr/local/lib/libc++.so: undefined reference to `vtable for __cxxabiv1::__si_class_type_info'
//usr/local/lib/libc++.so: undefined reference to `vtable for __cxxabiv1::__class_type_info'
//usr/local/lib/libc++.so: undefined reference to `vtable for __cxxabiv1::__vmi_class_type_info'
UPDATE:
After building libc++abi it successfully passes build step, though now it crashes with error saying
error while loading shared libraries: libc++abi.so.1: cannot open shared object file: No such file or directory
Current flags:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -isystem /usr/local/include/c++/v1 -stdlib=libc++ -lc++abi -Wall -Wextra -pedantic-errors -std=c++1z")
After having a look, I found that they are absent in /usr/lib/, but are present in /usr/local/lib.
Here is the output of ldd program:
linux-vdso.so.1 => (0x00007ffd1b7da000)
libc++abi.so.1 => /usr/local/lib/libc++abi.so.1 (0x00007f69bd322000)
libc++.so.1 => /usr/local/lib/libc++.so.1 (0x00007f69bcf80000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f69bcc76000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f69bca60000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f69bc697000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f69bc479000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f69bc271000)
/lib64/ld-linux-x86-64.so.2 (0x000055e63a9a9000)
So what lead to problem was actually me leaving the part with libc++abi. Most of the procedure is as specified in the docs, with minor deviation.
The procedure for me was roughly as following:
Checkout llvm
Checkout libc++ and libc++abi. Remember to checkout both!
Configure. I'm not sure if it matters, but I builded it with release configuration, e.g. specified -DCMAKE_BUILD_TYPE=Release. Also, make sure that it will be compiled with clang itself.
Install both. They will probably be somewhere around /usr/local/lib/ folder.
Let compiler know that you want libc++. The flags are -stdlib=libc++ -lc++abi. If it will complain about missing <stddef.h>, add -isystem path/to/includes/ to the compiler flags, which in my case was -isystem /usr/local/include/c++/v1.

Shipping libstdc++.so.6 with application

I want to use gcc 4.8.1 for my application (requires libstdc++.so.6.0.18), however customers only have libstdc++.so.6.0.13. I have been using -static-libgcc -static-stdlibc++ for a while now, but my application consists of several dynamically linked libraries and one main application. This means that when compiling each dynamic library, they must statically compile the standard library, which is redundant and wasteful. I want to just ship the standard library of my choice with my product, however every time I run my application in an environment like theirs, it always loads the wrong standard library. It prefers the /usr/lib64/ version no matter what I seem to do (it seems to take precedence over LD_LIBRARY_PATH).
Constraints:
I'm not allowed to force them to upgrade to a new standard library.
I don't want to make the dynamic libraries static. (I'd be able to statically compile everything into the main app once, but there are some logistical barriers that prevent me from recompiling some libraries into static ones).
-Wl,-rpath=$(path_to_directory) is a bit dangerous, however it is legal because the customers do source some settings that allow me to set path variables. However, setting the rpath of my new stdlibc++ doesn't seem to be overriding the default /usr/lib64 version. I still get GLIBCXX errors because it won't use the right library.
Surely there is an elegant solution for this?
Perhaps there is just an error in my procedure. Here's an example (sorry about the censor, but it's just username stuff):
~/example$ pwd
/home/username/example
~/example$ echo $LD_LIBRARY_PATH
~/example$ ls
Makefile libstdc++.so.6.0.18 test.cpp
~/example$ make
g++ -std=c++11 -Wall -Werror test.cpp -o test
~/example$ ldd test
./test: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ./test)
linux-vdso.so.1 => (0x00007fffe5919000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x000000390b800000)
libm.so.6 => /lib64/libm.so.6 (0x0000003904800000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000390b400000)
libc.so.6 => /lib64/libc.so.6 (0x0000003904400000)
/lib64/ld-linux-x86-64.so.2 (0x0000003904000000)
~/example$ setenv LD_LIBRARY_PATH /home/username/example
~/example$ echo $LD_LIBRARY_PATH
/home/username/example
~/example$ ldd test
./test: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found (required by ./test)
linux-vdso.so.1 => (0x00007fff2d3ff000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x000000390b800000)
libm.so.6 => /lib64/libm.so.6 (0x0000003904800000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x000000390b400000)
libc.so.6 => /lib64/libc.so.6 (0x0000003904400000)
/lib64/ld-linux-x86-64.so.2 (0x0000003904000000)
Sorry guys, I made a rather dumb mistake...
~/example$ file libstdc++.so.6.0.18
libstdc++.so.6.0.18: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped
Some dweeb built the wrong version of the library, and another dweeb (namely myself) tried using it on a 64-bit machine. Using LD_LIBRARY_PATH was working all along...
Your problem is that the executable is linked to the soname libstdc++.so.6 not to the full library filename libstdc++.so.6.0.16. The dynamic linker will look for libstdc++.so.6 in the usual places (i.e. LD_LIBRARY_PATH, DT_RPATH, ldconfig dirs etc.) so to ensure the 6.0.18 version is found you need a symlink called libstdc++.so.6 pointing to it.
Instead of using LD_LIBRARY_PATH (which is fragile on machines you don't control, because users might alter their environment) I prefer linking with '-Wl,-rpath,$ORIGIN' (N.B. the quotes are necessary to stop the shell expanding $ORIGIN)
An RPATH of $ORIGIN tells the dynamic linker to start looking for shared libraries in the same directory as the executable, so if you ship libstdc++.so alongside your executable it will be found. If you want to ship the executable in a bin directory and have the library in a lib directory you can use '-Wl,-rpath,$ORIGIN/../lib' or other paths relative to the location of the executable.

Cross compile c++ for raspberry pi std error

I need to cross compile C/C++ code for the Raspberry Pi (armV6). I followed the instructions on http://hertaville.com/2012/09/28/development-environment-raspberry-pi-cross-compiler/ and I got the building on my host machine (Ubuntu 14.04) working.
So my project builds on my host machine after some irritation with the needed libraries, I was happy enough. But when I transferred the program to my Raspberry Pi, I got the following error:
{ProjectName}: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.18' not found (required by {ProjectName})
{ProjectName}: /usr/lib/arm-linux-gnueabihf/libstdc++.so.6: version `GLIBCXX_3.4.19' not found (required by {ProjectName})
So I suspect the crosscompiler is using the libstd++.so of my host machine instead of the one that is part of the crosscompiler, but I have no idea how to fix it.
I'm using the gcc-linaro-arm-linux-gnueabihf-raspbian/arm-linux-gnueabihf-g++ crosscompiler.
The program that I try to get working is written by someone else directly on the pi, there it builds, compiles and runs perfectly.
My makefile looks like this:
CC=arm-linux-gnueabihf-g++
IFLAGS=-pthread -I./headers -lwiringPi -lortp -llinphone
LIBB = -I/home/david/rpi/rootfs/usr/lib/arm-linux-gnueabihf/
CFLAGS=-Wall -std=c++0x
LDFLAGS=-Wall
SOURCES=$(wildcard src/*cpp)
OBJECTS=$(addprefix obj/,$(notdir $(SOURCES:.cpp=.o)))
EXECUTABLE=bin/wackytalky
all: $(SOURCES) LINK_EXEC
debug: CFLAGS += -g
debug: $(SOURCES) LINK_EXEC
LINK_EXEC: $(OBJECTS)
$(CC) $(LDFLAGS) -o $(EXECUTABLE) $^ $(LIBB) $(IFLAGS)
obj/%.o: src/%.cpp
$(CC) $(CFLAGS) -o $# -c $< $(IFLAGS)
clean:
rm $(EXECUTABLE) obj/*.o
I had the same problem (exactly) as you yesterday. I don't have time to follow up on the Pi side yet, so I just modified modified my cross compile options (I use eclipse) and added -static-libstdc++ to the linker command. This statically links in the code on the Ubuntu side, so the problem with the .so on the Pi side never arises.
Obviously it makes for a much larger executable file.
You have to copy the libstdc++ and others to your respary pi. If you use an newer compiler which generate executables which needs a newer lib this lib must be present on the target. Static linking is not a useful option. Simply copy the new libs to the appropriate path on your target.
So I suspect the crosscompiler is using the libstd++.so of my host machine instead of the one that is part of the crosscompiler, but I have no idea how to fix it.
No, I don't believe this. If your compiler was configured correctly, it uses the correct libs. And if it tries to use you x86 libs, you don't get an message of wrong version because the dynamic linker can not work with x86 libs at all.
For the downvoters :-):
You can have more then one version on the target, so it is no problem to do this, see ldconfig for details. Also you can have the lib in the local or any other path without a problem, for this you can use LD_LIBRARY_PATH. And yes, I have not written that you should remove older versions. Linux is not windows so a added library will not break the system. Linux have no problems like the dll hell of win...
Of your special request I build one program with two different compilers and get from ldd:
gcc 4.9:
linux-vdso.so.1 => (0x00007fff4b7fe000)
librt.so.1 => /lib64/librt.so.1 (0x00000030f2200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000030f1200000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00000030f0e00000)
libstdc++.so.6 => /opt/linux-gnu_4.9-20140105/lib64/libstdc++.so.6 (0x00007fa4aadc4000)
libm.so.6 => /lib64/libm.so.6 (0x00000030f1600000)
libgcc_s.so.1 => /opt/linux-gnu_4.9-20140105/lib64/libgcc_s.so.1 (0x00007fa4aabad000)
libc.so.6 => /lib64/libc.so.6 (0x00000030f0a00000)
gcc 4.8.2:
linux-vdso.so.1 => (0x00007fff4b7fe000)
librt.so.1 => /lib64/librt.so.1 (0x00000030f2200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000030f1200000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00000030f0e00000)
libstdc++.so.6 => /opt/linux-gnu_4.8.2/lib64/libstdc++.so.6 (0x00007fa4aadc4000)
libm.so.6 => /lib64/libm.so.6 (0x00000030f1600000)
libgcc_s.so.1 => /opt/linux-gnu_4.8.2/lib64/libgcc_s.so.1 (0x00007fa4aabad000)
libc.so.6 => /lib64/libc.so.6 (0x00000030f0a00000)
As you can see: Two versions of one library one one system and no problems at all.
Some more infos on different of libs on the os look here at:
How do applications resolve to different versions of shared libraries at run time?
If it will not work on your system, feel free to ask again.

Linking 'libstdc++' library is broken in embedded linux

I have been working on a project which will be loaded on an embedded system, has not enough memory/disk space to install a C++ compiler and compile the code, natively.
So, I need to “cross-compile” the code on my development (Host) machine to be used on the target machine (Embedded Linux).
The happening problem related to using strings and iostreams which are a feature of the C++ standard template library (STL). However, because memory is so critical in an embedded system, the standard template library (libstdc++), can not be available on target side.
I need to statistically link the standard libraries on host machine, rather than dynamically link on target side. So, in my Makefile I need to have a slightly complex modification in both compiling and linking steps in order to build my project.
I have used some parameters such as -nodefaultlibs, -static-libstdc++, and -lstdc++ in the linking step and also added -nostdinc++ to the compiler flags. Still, there exist the problem on target side; " can not load library libstdc++.so.6 "
Most of these settings I have tried did not work. Is there any solution?
-lstdc++ overrides -static-libstdc++, try linking with just -static-libstdc++.
See this for example:
$ g++ -o foo foo.cpp -static-libstdc++ -lstdc++
$ ldd foo
linux-gate.so.1 => (0x0056b000)
libstdc++.so.6 => /usr/lib/i386-linux-gnu/libstdc++.so.6 (0x007ae000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000)
libm.so.6 => /lib/i386-linux-gnu/libm.so.6 (0x005dd000)
/lib/ld-linux.so.2 (0x002bc000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0x0095e000)
libstdc++ is linked dynamically!
$ g++ -o foo foo.cpp -static-libstdc++
$ ldd foo
linux-gate.so.1 => (0x0097b000)
libgcc_s.so.1 => /lib/i386-linux-gnu/libgcc_s.so.1 (0x001f9000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x0037f000)
/lib/ld-linux.so.2 (0x00199000)
now it is not.