6

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?

user10602
  • 83
  • 7
  • 1
    `-fPIC` is probably case sensitive. I don't know if this is the problem. – Simple Nov 20 '15 at 12:13
  • @Simple: I tried with `-fPIC` but I still get the same error. – user10602 Nov 20 '15 at 12:30
  • 2
    Try `-static-libstdc++`. See https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html for relevant linking options. – Andrew Nov 20 '15 at 13:33
  • @Simple, if `-fpic` was not valid there would be an error. It is case-sensitive, but both `-fpic` and `-fPIC` are valid options (with slight differences for some targets, see the manual). – Jonathan Wakely Nov 20 '15 at 16:18

2 Answers2

3

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)
Andrew
  • 5,212
  • 1
  • 22
  • 40
  • 2
    You also need `-static-libgcc` to remove `libgcc_s.so.1` dependency. – Maxim Egorushkin Nov 20 '15 at 15:59
  • @MaximEgorushkin Sure, if you want to remove the dependency. The answer now mentions this, although it's usually better to allow `libc` and `libgcc` to be picked up from the system (unless a dynamic `libgcc` isn't present on the destination system, of course). – Andrew Nov 20 '15 at 16:09
  • @Andrew: Thank you! Do you also happen to know how I can do a full static link (including libc and libm). I know this may not be recommended but I need to do this for a research prototype. – user10602 Nov 20 '15 at 16:21
  • @Andrew `libgcc` implements C++ exceptions, so if one links statically to `libstdc++` that means `libgcc` also need to be linked statically. You are correct about `libc` though. – Maxim Egorushkin Nov 20 '15 at 16:32
  • @MaximEgorushkin you're correct, but if the exceptions are allowed to cross the library boundary, you must make sure the libgcc version is identical on both sides. The easiest way to do this is to allow it to be loaded dynamically on the destination system! If you don't throw exceptions across the library boundary (which is not a great idea anyway!) then you can link statically to `libgcc`. (or if the main application also links statically to identical `libstdc++` and `libgcc`). – Andrew Nov 20 '15 at 16:38
  • @user10602 You may be able to force some static linking by explicitly specifying the `.a` file as an input to the compiler. Instead of using `-lm` to link to the math library, you could specify the path to `libm.a` on your system (if it is available). – Andrew Nov 20 '15 at 16:42
  • @user10602 You might also like to read the answers to [this question](http://stackoverflow.com/questions/4156055/gcc-static-linking-only-some-libraries), which offer a number of ways to mix static and dynamic linking. – Andrew Nov 20 '15 at 16:51
  • @Andrew Often people link statically because the target machine may not have that library installed or have an older version. So, if the target machine has older `libstdc++` that means it has an older `libgcc_s`, hence one needs to bundle both of those. – Maxim Egorushkin Nov 20 '15 at 23:29
3

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 or DT_RUNPATH) to mean the directory containing the application executable. Thus, an application located in somedir/app could be compiled with gcc -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.

Maxim Egorushkin
  • 131,725
  • 17
  • 180
  • 271