【问题标题】:How to use static library(.a file) instead of a group of object files(.o) to create a shared library如何使用静态库(.a 文件)而不是一组目标文件(.o)来创建共享库
【发布时间】:2014-09-05 15:39:36
【问题描述】:

我有一个共享库,我用它来创建一个可执行的二进制文件。我只能控制库和可执行二进制文件的构建过程,而不能控制所涉及的源文件。正如预期的那样,可执行二进制文件中的源文件引用了库中的许多函数。

目前共享库是直接使用 objectfiles(.o) 构建的。

g++ -shared ${OBJECT_FILES} -o ${SHARED_LIBRARY}

我也想通过将目标文件分组到静态库(.a 文件或档案)中来发布目标文件。

为了节省空间,我在创建存档文件时删除了所有 .o 文件。所以现在,构建命令是

g++ -shared ${ACRCHIVE_FILE} -o ${SHARED_LIBRARY}

图书馆建设良好。
但是,当我尝试通过链接到此共享库来构建可执行二进制文件时,二进制文件引用的符号未定义并且无法链接。 (未定义对Context::Get()的引用)

根据我的理解,我们是直接使用 .o 文件还是使用包含所有 .o 文件的存档创建共享库,但这显然是不可能的,或者我可能遗漏了一些东西。

【问题讨论】:

标签: c++ g++ linker-errors


【解决方案1】:

共享库libfoo.so 应该包含PIC 代码,静态库libfoo.a 包含普通的非PIC 代码。因此,您不能从静态库创建共享库。

共享库需要 位置无关代码,因为它们的段是 mmap(2)-ed 在几乎任意和可变的地址 - 没有 MAP_FIXED ... 另见 ASLR .

您原则上可以从 PIC 对象文件构建静态库,但实际上没有人这样做。

你可能(如果你真的坚持的话)用非 PIC 代码制作一个ELF 共享对象,但结果会产生非常糟糕的性能;动态链接器会有很多relocations,所以大部分段都不会共享,动态链接会很慢。

将共享库的foo.cc编译成PIC对象文件foo.pic.o

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

为一个静态库编译一个普通的非PIC对象文件foo.o

g++ -Wall -c -O foo.cc -o foo.o 

foo.pic.obar.pic.o 的共享库转换为libfoobar.so 在某些libdep.so 共享库中的链接:

g++ -shared foo.pic.o bar.pic.o -ldep -o libfoobar.so

在制作上述共享库时,您通常希望添加更多链接选项,例如-Wl,-rpath,... 或 -Wl,-soname,....

顺便说一句,无法将存档 libfoobar.a(即使它是由 PIC 文件组成)链接到 libfoobar.so,因为没有未定义名称并且需要从 libfoobar.a 链接一些目标文件(也许你可以尝试用-u symb 取消定义一些符号symb,但我不建议这样做)。

foo.obar.o 的静态库制作成libfoobar.a

ar cv libfoobar.a foo.o bar.o

请注意,ranlib(创建存档索引)不再需要,因为 GNU ar 完成了它的工作。

另请阅读ld.so(8)ldd(1)ld(1)ar(1)objdump(1)readelf(1)dlopen(3)(通常,如果主程序加载@ 987654363@-ed plugins at runtime,使插件能够在主程序中找到一些符号)。

注意:我只会构建一个共享库,根本不关心静态链接。请注意,在某些系统上,PIC 的成本较低(代码稍大和/或速度较慢)。 AFAIK,x86-64 上的 PIC 开销比 32 位 Linux x86 代码上的成本更低。在某些架构和 ABI 上,PIC 的开销可能可以忽略不计(甚至可能比非位置无关代码更有效)。

参考:Drepper's paper: How to Write Shared Libraries & Levine's book: Linkers and Loaders & Program Library HowTo

【讨论】:

  • 我一直认为 .a 只不过是 .o 文件的存档,原则上与 .tar.gz 或 .zip 甚至目录没有区别。我错了吗?
  • ar 命令也做了ranlib 曾经做的事情:创建一些索引。
  • 那么 .a 库与 PIC 有什么关系?
  • 它(一个静态的libxxx.a库)与PIC无关,它包含非PIC对象
  • 那么如果进入 .a 的 .o 是用 -fPIC 编译的,那么我们应该没问题?
猜你喜欢
  • 2023-03-21
  • 1970-01-01
  • 1970-01-01
  • 2014-01-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 2015-10-11
相关资源
最近更新 更多