gcc中共享库函数的静态链接


138

如何在gcc中静态链接共享库函数?


13
静态链接是什么意思?您是否希望在不使用.so的情况下分发可执行文件?
Emiliano

Answers:


108

参考:

http://www.linuxquestions.org/questions/linux-newbie-8/forcing-static-linking-of-shared-libraries-696714/

http://linux.derkeiler.com/Newsgroups/comp.os.linux.development.apps/2004-05/0436.html

您需要库的静态版本才能链接它。

共享库实际上是具有指定入口点的特殊格式的可执行文件(包括一些粘性地址问题)。它没有静态链接所需的所有信息。

您不能静态链接共享库(或动态链接静态库)。

该标志-static将强制链接器使用静态库(.a)而不是共享库(.so)。但是默认情况下并不总是安装静态库,因此您可能必须自己安装静态库。

另一种可能的方法是使用statifierErmine。两种工具均将动态链接的可执行文件作为输入,并以输出形式创建包含所有共享库的自包含可执行文件。


11
静态库具有什么信息,以便可以将其静态链接,而动态库则没有?
kbolino '18 -10-17

75

如果要静态链接libapplejuice,但不想静态链接liborangejuice,则可以这样链接:

gcc object1.o object2.o -Wl,-Bstatic -lapplejuice -Wl,-Bdynamic -lorangejuice -o binary

需要注意的是-如果liborangejuice使用libapplejuice,那么libapplejuice也会动态链接。

你必须链接liborangejuice静态与一起libapplejuice拿到libapplejuice静态的。

并且不要忘记保留-Wl,-Bdynamic其他内容,最终将所有内容静态链接,包括libc(这不是一件好事)。


2
难道没有办法直接告诉gcc静态链接什么,而不是绕开他并与链接器交谈吗?
Elazar Leibovich,

1
@ElazarLeibovich,您无法通过这种方式将静态与动态结合起来。
郝准

@EugeneBujak:警告不适用于我的系统。示例:gcc -o main main.cc -Wl,-rpath=. -Wl,-Bdynamic -lB -Wl,-Bstatic -lA -Wl,-Bdynamic -L. libB使用libA,它链接并且ldd没有显示对libA的引用。可执行文件工作正常。已通过g ++ 4.7.3测试。

直接(动态)相关性的间接(嵌套)静态相关性本身不会动态链接。
Vinny

考虑以下内容:binA依赖于libB.so,后者依赖于libC.a正如其他人已经指出的那样,.so本身就是可执行文件,因此当链接共享库时,链接器对任何静态库依赖项的处理方式与链接了一个可执行文件:从.a静态库中提取的唯一符号是.so引用(但未解析)的符号。这意味着,如果binA在libC.a中引用了一个符号,而在libB.so中未引用任何符号,则即使binA链接到libB.so,该符号​​也将是未定义的(除非-Wl,-whole-archive在链接时使用libB.so)。
Vinny

18

如果您拥有共享库(.so)的.a文件,则可以将其完整路径包括在内,就好像它是一个目标文件一样,如下所示:

只需编译即可生成main.o:

gcc -c main.c

这会将目标文件与相应的静态库链接在一起,并创建可执行文件(名为“ main”):

gcc main.o mylibrary.a -o main

或在单个命令中:

gcc main.c mylibrary.a -o main

也可以是绝对路径或相对路径:

gcc main.c /usr/local/mylibs/mylibrary.a -o main

12

是的,我知道这是一个已有8年历史的问题了,但是有人告诉我可以静态链接到共享库,这在我搜索有关它的更多信息时实际上是最热门的。

要实际演示使用ldgcc的链接器)无法静态链接共享库,而不是一堆坚持这一点的人,请使用以下gcc命令:

gcc -o executablename objectname.o -Wl,-Bstatic -l:libnamespec.so

(当然你必须编译objectname.osourcename.c,你可能要弥补自己的共享对象库也是如此。如果你这样做,使用-Wl,--library-path,.使LD可以找到你的本地目录库)。

您收到的实际错误是:

/usr/bin/ld: attempted static link of dynamic object `libnamespec.so'
collect2: error: ld returned 1 exit status

希望有帮助。


10

有点晚了,但是...我发现了几年前保存的链接,我认为这可能对你们有用:

CDE:自动创建可移植的Linux应用程序

http://www.pgbovine.net/cde.html

  • 只需下载程序
  • 执行要传递的二进制文件名称作为参数,使其成为可移植的二进制文件名称,例如:nmap

    ./cde_2011-08-15_64bit nmap

该程序将读取链接到nmap及其依赖项的所有库,并将所有库保存在名为cde-package /的文件夹中(与您所在的目录相同)。

  • 最后,您可以压缩文件夹并在任何系统中部署可移植二进制文件。

记住,要启动可移植程序,您必须执行cde-package / nmap.cde中的二进制文件。

最好的祝福


2
虽然不能完全提供问题的答案,但它是解决问题的有效方法。
razong 2015年

该链接现在似乎已失效。
sinan

0

在gcc中,不支持此功能。实际上,我所知道的任何现有编译器/链接器均不支持此功能。


4
您能解释一下现有编译器不支持静态链接吗?
2012年

5
@noloader,动态库的静态链接?
nothrow 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.