Reputation: 83
I need to create a shared library whose own dependencies including libc/libstdc++ have to be statically linked to it to produce a self-contained binary. I tried to do this
g++ -c -fpic -o foo.o foo.cpp
g++ -static -shared -o foo.so foo.o
which fails with:
/usr/bin/ld.bfd.real: /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/crtbeginT.o: relocation R_X86_64_32 against `__TMC_END__' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/crtbeginT.o: could not read symbols: Bad value
collect2: error: ld returned 1 exit status
Can somebody tell me what I am doing wrong?
Upvotes: 6
Views: 2786
Reputation: 136495
I need to create a shared library whose own dependencies including libc/libstdc++ have to be statically linked to it to produce a self-contained binary
To have a self-contained binary you do not necessarily need to link statically. Some libraries cannot be compiled as static libraries for different reasons.
Many commercial applications use $ORIGIN
linker feature. You can copy all the required shared libraries into a directory along with your executable and link your executable with extra linker flags. See man ld.so
:
$ORIGIN and rpath
ld.so understands the string
$ORIGIN
(or equivalently${ORIGIN}
) in an rpath specification (DT_RPATH
orDT_RUNPATH
) to mean the directory containing the application executable. Thus, an application located in somedir/app could be compiled withgcc -Wl,-rpath,'$ORIGIN/../lib'
so that it finds an associated shared library in somedir/lib no matter where somedir is located in the directory hierarchy. This facilitates the creation of "turn-key" applications that do not need to be installed into special directories, but can instead be unpacked into any directory and still find their own shared libraries.
Upvotes: 3
Reputation: 5352
You can use the -static-libstdc++
option to link libstdc++
statically. You probably shouldn't link statically to libc
(or libgcc
, which you can link statically with -static-libgcc
should you need to) if you're making a dynamic library; you'll want to pick up the libc version of the application that loads your shared library.
Other options controlling static linking can be found in the GCC manual. You may also be able to achieve the desired results by passing arguments to the linker (-Wl,<argument>
, or calling ld
directly). The LD manual lists the permitted options.
Example:
I wrote the following code
#include <iostream>
extern "C" void do_something() {
std::cout << "Doing something!\n";
}
and compiled it to a .o
file as follows:
g++ -fPIC -c -o tmp.o tmp.cpp
I then produced two shared libraries from it. One with -static-libstdc++, and one without:
g++ -shared -o tmp-shared.so tmp.o
g++ -shared -static-libstdc++ -o tmp-static.so tmp.o
For comparison, ldd tmp-shared.so
:
linux-vdso.so.1 => (0x00007fffc6dfd000)
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00002b708cb43000)
libm.so.6 => /lib64/libm.so.6 (0x00002b708ce4c000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002b708d0cf000)
libc.so.6 => /lib64/libc.so.6 (0x00002b708d2dd000)
/lib64/ld-linux-x86-64.so.2 (0x00000035c6c00000)
and ldd tmp-static.so
:
linux-vdso.so.1 => (0x00007fff99bfd000)
libm.so.6 => /lib64/libm.so.6 (0x00002acbec030000)
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002acbec2b3000)
libc.so.6 => /lib64/libc.so.6 (0x00002acbec4c1000)
/lib64/ld-linux-x86-64.so.2 (0x00000035c6c00000)
Upvotes: 3