如何将静态库链接到共享库

How do you link a static library to a shared library

本文关键字:链接 共享 静态      更新时间:2023-10-16

我正在尝试通过类似命令将静态库链接到共享库

g++ -shared obj.o archive.a -o libLib.so

但是在运行时,我不断得到未解析的系统,该系统应该在编译时从 archive.a 链接。 我试过了

 g++ -shared obj.o -Wl,-Bstatic archive.a -Wl,-Bdynamic -o libLib.so

g++ -shared obj.o -Wl,-whole-archive archive.a -Wl,-no-whole-archive -o libLib.so

没有成功。 我觉得我在这里错过了一些基本的东西......

你实际上不能(即永远不应该)这样做。共享库应该是与位置无关的代码,但静态库不是。

如果要将libaa链接到libfoo.so构建或获取共享(PIC)库libaa.so,而不是静态(非PIC)库libaa.a

因此,进入共享库foo1.cc的文件libfoo.so应编译为

g++ -c -fPIC -Wall -O foo1.cc -o foo1.pic.o

并且库将链接为

g++ -shared foo1.pic.o foo2.pic.o -o libfoo.so 

您可以将另一个共享库libsmiling.so链接到libfoo.so例如,通过将-lsmiling附加到上述命令中。但是,您不能将库链接到静态库,只能复制其成员。

但是进入静态libfoo.a的文件只是编译为

g++ -Wall -O foo1.cc -o foo1.o

因此,当您从libfoo.a中提取该foo1.o成员时,它不是PIC(这是非常低效的)

原则上,您可以将非 PIC 目标代码放在共享库中。实际上,您永远不应该这样做,因为重定位量太大,以至于违背了共享库的目的。如果这样做,文本内存将无法共享,动态链接器将有大量重定位工作。

共享对象内部.so代码应该是 PIC,以允许ld.so在不同进程的不同地址段mmap它。

因此,您可以找到一系列命令将静态库链接到共享库,例如ar x使用libbar.a的所有成员进行提取,然后将所有这些提取的bar*.ofoo*.pic.o链接,但这将是一个错误。不要将静态非 PIC 库或对象文件链接到 PIC 共享库。

有关详细信息(重点是Linux),请阅读 ld.so(8),ld(1),ELF维基页面,Levine的书:链接器和加载器,Drepper的论文:如何编写共享库

附言。一些非常少的静态库包含 PIC 代码,因为它们可用于创建共享库。例如,我的 Debian 提供了libc6-pic软件包,特别是提供了/usr/lib/x86_64-linux-gnu/libc_pic.a静态 PIC 库 - 可用于构建libc.so的某种变体 - 例如,如果我想将自己的malloc放在libc.so中!- 无需重新编译每个 glibc 源文件。