在与GCC链接时,如何仅将某些特定库静态链接到我的二进制文件?
gcc ... -static ...
尝试静态链接所有链接库,但我没有其中一些的静态版本(例如:libX11).
我有一个共享库,由我无法控制的另一个应用程序使用,需要*.so对象.我的库使用sqlite3,它需要与它静态链接(我绝对需要一个自包含的二进制文件).
当我尝试编译和链接我的库时:
-fpic -flto -pthread -m64
-flto -static -shared
Run Code Online (Sandbox Code Playgroud)
我最终得到以下错误:
/usr/bin/ld: /usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtbeginT.o: relocation R_X86_64_32 against `__DTOR_END__' can not be used when making a shared object; recompile with -fPIC
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/4.6.1/crtbeginT.o: could not read symbols: Bad value
collect2: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)
什么是与-fPIC相关的重新编译?我的代码还是CRT?
我已经尝试用-fPIC编译我的对象,结果相同.
谢谢.
编辑:
这个问题似乎与SQLite3无关.
我写了一个简单的单行无用库,它编译和链接如下:
g++ -c -fPIC -o bar.o bar.cpp
g++ -shared -o bar.so bar.o
Run Code Online (Sandbox Code Playgroud)
但不是这样的:
g++ -c -fPIC -o bar.o bar.cpp
g++ -static -shared -o bar.so bar.o
Run Code Online (Sandbox Code Playgroud)
问题似乎与CRT(crtbeginT.o)有关.我应该重新编译GCC - 用pic还是其他什么?
以下问题是相关的,但不回答我的问题:
我之前提出了一个非常类似的问题,但是由于我开始的上一个问题在评论部分有些混乱而没有得到完全回答(但我将其标记为已回答,因为这是一项很好的努力并至少部分回答了它)我会问一个新问题.问题是具体如何将libc链接为静态,同时动态链接其他库(例如libm).有人提出在第一个问题中无法做到,是真的吗?如果是这样,知道为什么不是很有趣.
甚至可以这样做吗?有人发表了意见(这是出于某种原因删除,也许这是不正确的?),这是可能的,但那么一定还存在libc中的动态链接的版本,因为它会通过动态库需要(如动态的libm会需要动态libc(?)).
这对我来说很好,但对我来说如何告诉GCC这样做并不明显,即在libc中链接为静态和动态.我该怎么做(我做了几次尝试,有些会在后面的问题中展示)?或者还有其他方法可以做我想要的吗?
我们首先看到,通过简单地运行gcc test.c -lm,一切都是动态链接的,如下所示:
$ gcc test.c -lm
$ ldd a.out
linux-vdso.so.1 (0x00007fffb37d1000)
libm.so.6 => /lib64/libm.so.6 (0x00007f3b0eeb6000)
libc.so.6 => /lib64/libc.so.6 (0x00007f3b0eb10000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3b0f1b0000)
Run Code Online (Sandbox Code Playgroud)
要仅将libm链接为静态,同时允许libc保持动态,我们可以这样做(正如Z boson在前面提到的一个问题中指出的那样):
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libm.a
$ ldd a.out
linux-vdso.so.1 (0x00007fff747ff000)
libc.so.6 => /lib64/libc.so.6 (0x00007f09aaa0c000)
/lib64/ld-linux-x86-64.so.2 (0x00007f09aadb2000)
Run Code Online (Sandbox Code Playgroud)
但是,尝试使用相同的过程来链接libc static和libm dynamic,似乎不起作用:
$ gcc test.c /usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a -lm
/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../x86_64-pc-linux-gnu/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `/usr/lib/gcc/x86_64-pc-linux-gnu/4.7.3/../../../../lib64/libc.a(strcmp.o)' can not be used when making an executable; recompile with -fPIE and relink …
Run Code Online (Sandbox Code Playgroud) 我需要构建一个静态链接 libc 的二进制文件。我在与源代码相同的目录中提供了 libc.a 。为了编译,我尝试了以下操作:
gcc -o foo foo.c libc.a
Run Code Online (Sandbox Code Playgroud)
这导致了以下问题:
/usr/bin/ld: dynamic STT_GNU_IFUNC symbol `strcmp' with pointer equality in `libc.a(strcmp.o)' can not be used when making an executable
Run Code Online (Sandbox Code Playgroud)
在研究这个问题时,我发现了以下问题:Linking Partial static and Partially Dynamic in GCC
按照顶部答案中的解决方案,我创建了自己的字符串比较函数my_strcmp.c
并尝试了以下编译:
gcc -o foo foo.c mystrcmp.c libc.a
Run Code Online (Sandbox Code Playgroud)
它确实有效,但是二进制文件现在很早就出现了段错误。如果没有静态链接 libc,这种情况就不会发生。这是 GDB 跟踪:
(gdb) backtrace
#0 0x00000000004fe48e in generic_start_main ()
#1 0x00000000004fe891 in __libc_start_main ()
#2 0x0000000000406b56 in _start ()
Run Code Online (Sandbox Code Playgroud)
不太确定如何解释这一点。有人有主意吗?