2015-11-20 96 views
3

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

有人能告诉我什么,我做错了什么?

+1

'-fPIC'可能区分大小写。我不知道这是否是问题。 – Simple

+0

@Simple:我试着用'-fPIC',但是我仍然得到相同的错误。 – user10602

+1

试试'-static-libstdC++'。有关链接选项,请参阅https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html。 – Andrew

回答

2

您可以使用-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

您还需要'-static-libgcc'来移除'libgcc_s.so.1'依赖项。 –

+0

@MaximEgorushkin当然,如果你想删除依赖。现在的答案提到了这一点,尽管允许从系统中获取'libc'和'libgcc'通常更好(当然,除非在目标系统上不存在动态'libgcc')。 – Andrew

+0

@Andrew:谢谢!你是否也碰巧知道如何做一个完整的静态链接(包括libc和libm)。我知道这可能不被推荐,但我需要做一个研究原型。 – user10602

2

我需要创建它的共享库包括libc/libstdC++在内的自身依赖关系必须静态链接到它才能生成自包含的二进制文件

要拥有自包含的二进制文件,您不一定需要静态链接。出于不同的原因,某些库不能编译为静态库。

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

$ ORIGIN和rpath的

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

相关问题