在链接比创建静态库时更快地使用--start-group和--end-group吗?

时间:2011-08-13 20:31:12

标签: linker static-libraries ar .a

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

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

如果gui.a使用hw.a中定义的内容,则链接将失败,因为在处理hw.a时,链接器尚不知道稍后需要定义,并且不包含在生成的可执行文件中。手动摆弄链接器行是不切实际的,因此解决方案是使用--start-group--end-group,这使得链接器在库中运行两次,直到找不到未定义的符号。

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

然而,GNU ld手册说

  

使用此选项会产生显着的性能损失。最好只在两个或多个档案之间存在不可避免的循环引用时使用它。

所以我认为最好采用所有.a文件并将它们放在一个带有索引(GNU ar的.a选项)的-s文件中,该文件说明了什么命令文件需要链接。然后,只有一个.a文件给g++

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


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

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

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

Code is here。我把它放到公共领域:)

2 个答案:

答案 0 :(得分:3)

您可以使用lordertsort实用程序确定订单,例如

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-grouplorder,则这可能只是高于tsort的好处。此外,它不允许像--start-group那样的相互/循环依赖。

答案 1 :(得分:2)

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

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

但是,您必须小心两个文件恰好包含相同定义的情况(您可以使用nm显式检查这一点,以查看每个库中包含的定义)