独立的共享库

Self-contained shared library

我需要创建一个共享库,其自身的依赖项(包括 libc/libstdc++)必须静态链接到它以生成独立的二进制文件。我试过这样做

g++ -c -fpic -o foo.o foo.cpp
g++ -static -shared -o foo.so foo.o

失败:

/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

有人可以告诉我我做错了什么吗?

您可以使用 -static-libstdc++ 选项静态地 link libstdc++。你可能不应该 link 静态地 libc (或 libgcc,你可以 link 静态地 -static-libgcc 如果你需要的话)一个动态库;您需要选择加载共享库的应用程序的 libc 版本。

其他控制静态 linking 的选项可以在 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 列出的允许选项中找到。


示例:

我写了下面的代码

#include <iostream>

extern "C" void do_something() {
    std::cout << "Doing something!\n";
}

并将其编译为 .o 文件,如下所示:

g++ -fPIC -c -o tmp.o tmp.cpp

然后我从中生成了两个共享库。一种带有 -static-libstdc++,一种没有:

g++ -shared -o tmp-shared.so tmp.o
g++ -shared -static-libstdc++ -o tmp-static.so tmp.o

为了比较,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)

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)

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

要拥有独立的二进制文件,您不一定需要 link 静态。由于各种原因,某些库无法编译为静态库。

许多商业应用程序使用 $ORIGIN linker 功能。您可以将所有必需的共享库与您的可执行文件和 link 带有额外 linker 标志的可执行文件一起复制到一个目录中。见 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.