12

如果一个人在自己的构建脚本中构建静态库并且想要使用这些静态库来链接最终的可执行文件,那么提到.a文件的顺序很重要:

g++ main.o hw.a gui.a -o executable

如果gui.a使用hw.a链接中定义的某些内容将失败,因为在hw.a处理时,链接器还不知道稍后需要该定义,并且不会将其包含在being.generated 可执行文件中。手动摆弄链接器行是不切实际的,因此使用一种解决方案--start-group--end-group它使链接器在库中运行两次,直到不再找到未定义的符号。

g++ main.o -Wl,--start-group hw.a gui.a -Wl,--end-group -o executable

但是 GNU ld 手册说

使用此选项会带来很大的性能成本。最好仅在两个或多个档案之间存在不可避免的循环引用时才使用它。

所以我认为最好将所有.a文件放在一个.a文件中,并带有一个索引(-sGNU ar 的选项),该索引说明文件需要以什么顺序链接。然后一个人只将那个.a文件提供给g++.

但我想知道这是否比使用组命令更快或更慢。这种方法有什么问题吗?我也想知道,有没有更好的方法来解决这些相互依赖的问题?


编辑:我编写了一个程序,它采用.a文件列表并生成合并.a文件。使用 GNU 通用ar格式。将 LLVM 的所有静态库打包在一起就像这样

$ ./arcat -o combined.a ~/usr/llvm/lib/libLLVM*.a

我将速度与.a手动解压缩所有文件然后使用重新计算索引将它们放入新.a文件进行了比较。ar使用我的arcat工具,我获得了大约 500 毫秒的一致运行时间。使用手动方式,时间变化很大,大约需要2s左右。所以我认为这是值得的。

代码在这里。我把它放到公共领域:)

4

2 回答 2

3

lorder您可以使用和实用程序确定顺序tsort,例如

libs='/usr/lib/libncurses.a /usr/lib/libedit.a'
libs_ordered=$(lorder $libs | tsort)

导致/usr/lib/libedit.a /usr/lib/libncurses.a因为 libedit 依赖于 libncurses。

--start-group如果您不为每个链接命令再次运行lorder,这可能只是上述好处。tsort此外,它不允许像这样的相互/循环依赖--start-group

于 2011-08-14T10:27:06.457 回答
2

是否有第三种选择,您只需构建一个库开始?我有一个类似的问题,我最终决定使用第三种选择。

以我的经验, group 比仅仅统一 .a 文件要慢。您可以从存档中提取所有文件,然后从较小的文件中创建一个新的 .a 文件

但是,您必须小心两个文件恰好包含相同定义的情况(您可以通过使用nm来明确检查每个库中包含哪些定义)

于 2011-08-13T21:56:07.657 回答