Is there a way to statically link the glib2 library? - c++

Since the production device does not have a glib2 runtime environment, I need to statically link to glib2. I tried to compile and link in the following ways, but it still links libglib-2.0.so.0. I am sure that libglib-2.0.a exists on my device.
#include <glib.h>
int main(void)
{
char *test;
test = g_new0(char,1);
g_free(test);
return 0;
}
i tried build it by
gcc `pkg-config --static --libs --cflags glib-2.0` main.c -o test
ldd test
linux-vdso.so.1 (0x00007ffe9dbc8000)
libglib-2.0.so.0 => /lib64/libglib-2.0.so.0 (0x00007f2ee333f000)
libm.so.6 => /lib64/libm.so.6 (0x00007f2ee31fb000)
libpcre.so.1 => /lib64/libpcre.so.1 (0x00007f2ee3183000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f2ee3162000)
libc.so.6 => /lib64/libc.so.6 (0x00007f2ee2f93000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2ee3492000)

The flags that pkg-config --static gives you are library flags suited for a program that will ultimately be statically linked. Now, it's not pkg-config's job to configure your build, just to give you the flags your libraries need.
So, you need to add -s to your gcc command yourself.

Related

Building library on Ubuntu, using it in a project on Arch - doesn't build

I'm building a dynamic library on Ubuntu 14.04.5, that depends on some static libraries (Boost and OpenSSL).
If I use this library in a project on another Ubuntu machine, it works perfectly. However, if I build it and use it in a project on an Arch machine (Antergos), it says the following during the build process:
main.cpp.o: In function `init()':
main.cpp:(.text+0xf8): undefined reference to `Util::generateString[abi:cxx11](int)'
I'm building my project with the following:
g++ -Ldeps -Ideps/include main.cpp -lmylib
deps contains libmylib.so and the required header files in deps/include.
If I run ldd on my mylib.so on Ubuntu, I get the following:
linux-vdso.so.1 => (0x00007ffdd24cf000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f10b2f97000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f10b2c91000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f10b2a73000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f10b26ab000)
/lib64/ld-linux-x86-64.so.2 (0x00007f10b3ff3000)
If I run ldd on mylib.so on Antergos, I get the following:
linux-vdso.so.1 (0x00007ffcce115000)
libdl.so.2 => /usr/lib/libdl.so.2 (0x00007f5a42fef000)
libm.so.6 => /usr/lib/libm.so.6 (0x00007f5a42cdc000)
libpthread.so.0 => /usr/lib/libpthread.so.0 (0x00007f5a42abe000)
libc.so.6 => /usr/lib/libc.so.6 (0x00007f5a4271a000)
/usr/lib64/ld-linux-x86-64.so.2 (0x000055ced49a7000)
I'm probably missing something easy, but I can't seem to get it to work. What am I doing wrong?
I'm assuming that Util::generateString[abi:cxx11](int) is a function exported by your libmylib.so library? If so, you may want to recompile that library first and then reattempt the compilation/linking of main.cpp.
I suggest this to ensure that the c++ standard library that each component is linked against is the same version. It looks like libmylib.so was compiled against the c++11 standard library, you'll want to ensure main.cpp matches that. You can always specify which one you're linking against using --std= option (e.g. --std=c++11, --std=c++0x, --std=c++17).

How to configure shared library search path after building GCC on my own?

I just built GCC 5.1 on Ubuntu 14.04, which has gcc 4.8 as default. When I try to build things with it, I find that ld will use the default libstdc++ instead of the newly build one.
Here is the output:
drizzlex#dx ~/test
$ g++ hello.cpp
drizzlex#dx ~/test
$ ldd a.out
linux-vdso.so.1 => (0x00007ffde0d25000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007fa181ad2000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa1817cc000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa1815b5000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa1811f0000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa181dfd000)
And if I use $ export LD_LIBRARY_PATH=/usr/local/lib64/, it will find the right one.
drizzlex#dx ~/test
$ ldd a.out
linux-vdso.so.1 => (0x00007fffeeaf5000)
libstdc++.so.6 => /usr/local/lib64/libstdc++.so.6 (0x00007f4583d92000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4583a67000)
libgcc_s.so.1 => /usr/local/lib64/libgcc_s.so.1 (0x00007f4583850000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f458348b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f458410e000)
I would like to know what should I do to make it correct? Since I know set LD_LIBRARY_PATH is not the best choice.
For building with g++ 5.1 use this:
$ g++5.1 hello.cpp -Wl,-rpath,/usr/local/lib64
And you will not need set LD_LIBRARY_PATH.
This is from https://en.wikipedia.org/wiki/Rpath
rpath is a term in programming which refers to a run-time search path
hard-coded in an executable file or library, used during dynamic
linking to find the libraries the executable or library requires.

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.

Shared library, makefile. Library path

Im trying to link my program to the shared library. Im using a makefile to compile. It looks like this: `
make: sms_out.cpp SMSDispatch.cpp SMSDispatch.h
g++ -c -fPIC SMSDispatch.cpp -o SMSDispatch.o
g++ -shared SMSDispatch.o -o libSMSDispatch.so
` g++ sms_out.cpp -L. -lSMSDispatch -o sms_out
It works fine if I run the program in the command window with:
LD_LIBRARY_PATH="." ./sms_out
But I want to run it with just ./sms_out, can someone help me?
Tried to add export LD_LIBRARY_PATH=. to the makefile, but that didnt work, just got the error " error while loading shared libraries: libSMSDispatch.so: cannot open shared object file: No such file or directory" when I try to run the program.
Another option - provide -rpath options to linker to inform your binary where else search for dynamic objects.
g++ -Wl,-rpath=<path to .so> -o <your binary here> <cpp file name>.cpp
Add the directory where the .so file exists to LD_LIBRARY_PATH:
$ export LD_LIBRARY_PATH=/dir/containing/sharedobject
A utility you may find useful is ldd, which prints the shared library dependencies. For example:
$ ldd /bin/ls
linux-vdso.so.1 => (0x00007fff819ff000)
librt.so.1 => /lib64/librt.so.1 (0x00007fc0d3f67000)
libselinux.so.1 => /lib64/libselinux.so.1 (0x00007fc0d3d4a000)
libacl.so.1 => /lib64/libacl.so.1 (0x00007fc0d3b42000)
libc.so.6 => /lib64/libc.so.6 (0x00007fc0d37e9000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00007fc0d35cd000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc0d4170000)
libdl.so.2 => /lib64/libdl.so.2 (0x00007fc0d33c9000)
libattr.so.1 => /lib64/libattr.so.1 (0x00007fc0d31c4000)
If shared objects are not locatable a string not found, or similar, is displayed instead of the path to the shared object being used.