独立的共享库

时间:2015-11-20 12:09:01

标签: c++ shared-libraries static-linking

我需要创建一个共享库,其自身的依赖项(包括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

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

2 个答案:

答案 0 :(得分:3)

您可以使用-static-libstdc++选项静态链接libstdc++。如果您正在创建动态库,则可能不应静态链接到libc(或libgcc,您可以根据需要静态链接-static-libgcc;您将需要选择加载共享库的应用程序的libc版本。

可以在GCC manual中找到控制静态链接的其他选项。您也可以通过将参数传递给链接器(-Wl,<argument>或直接调用ld)来实现所需的结果。 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)

答案 1 :(得分:3)

  

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

要拥有自包含二进制文件,您不一定需要静态链接。由于各种原因,某些库无法编译为静态库。

许多商业应用程序使用$ORIGIN链接器功能。您可以将所有必需的共享库与可执行文件一起复制到目录中,并使用额外的链接器标志链接可执行文件。见man ld.so

  

$ ORIGIN和rpath

     

ld.so理解字符串$ORIGIN(或等效${ORIGIN})      rpath规范(DT_RPATHDT_RUNPATH)表示包含应用程序可执行文件的目录。因此,位于的应用程序      somedir / app可以使用gcc -Wl,-rpath,'$ORIGIN/../lib'进行编译      它在somedir / lib中找到了一个关联的共享库,无论如何      其中somedir位于目录层次结构中。这有利于      创建不需要的“交钥匙”应用程序      安装到特殊目录中,但可以解压缩到      任何目录,仍然可以找到自己的共享库。