在链接时使用——start-group和——end-group比创建静态库要快



如果您在构建脚本中构建静态库,并且希望在链接最终可执行文件时使用这些静态库,那么提到.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手册说

使用这个选项会有很大的性能成本。最好只在两个或多个档案之间不可避免地存在循环引用时使用它。

所以我认为它可能是更好的把所有的.a文件,并把它们放在一个.a文件与索引(GNU ar的-s选项),说在什么顺序的文件需要被链接。然后只给g++一个.a文件。

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


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

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

我比较了手动解包所有.a文件的速度,然后使用ar将它们放入新的.a文件中,重新计算索引。使用我的arcat工具,我得到了大约500ms的稳定运行时间。使用手动方式,时间变化很大,大约需要2s左右。所以我觉得很值得。

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

您可以使用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。

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

是否有第三种选择,您只是建立一个单一的库开始?我也遇到过类似的问题,最后我决定采用第三种方法。

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

创建一个新的。a文件。

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

相关内容

  • 没有找到相关文章

最新更新