链接时使用 --start-group 和 --end-group 是否比创建静态库更快?
如果在构建脚本中构建静态库并且想要使用这些静态库链接最终的可执行文件,则提及 .a
文件的顺序很重要:
g++ main.o hw.a gui.a -o executable
如果 gui.a 使用
hw.a
中定义的内容,链接将失败,因为在处理 hw.a
时,链接器尚不知道需要该定义稍后,并且不将其包含在being.generate中可执行的。手动摆弄链接器行是不切实际的,因此解决方案是使用 --start-group
和 --end-group
这使得链接器运行两次库,直到不再找到未定义的符号。
g++ main.o -Wl,--start-group hw.a gui.a -Wl,--end-group -o executable
然而 GNU ld 手册说
使用此选项会产生显着的性能成本。最好仅当两个或多个档案之间不可避免地存在循环引用时才使用它。
所以我认为最好将所有 .a
文件放在一起到一个带有索引的 .a
文件中(-s
GNU ar) 的选项表示文件需要按什么顺序链接。然后,只将一个 .a
文件提供给 g++
。
但我想知道这比使用组命令更快还是更慢。这种方法有什么问题吗?我还想知道,有没有更好的方法来解决这些相互依赖的问题?
编辑:我编写了一个程序,它获取 .a
文件列表并生成合并的 .a
文件。适用于 GNU 通用 ar
格式。将 LLVM 的所有静态库打包在一起的工作方式如下
$ ./arcat -o combined.a ~/usr/llvm/lib/libLLVM*.a
我将速度与手动解压缩所有 .a
文件然后使用 ar 将它们放入新的
,重新计算索引。使用我的 arcat 工具,我获得了大约 500 毫秒的一致运行时间。采用手动方式,时间相差较大,需要2s左右。所以我认为这是值得的。.a
文件进行了比较
代码在这里。我把它放到了公共领域:)
If one builds static libraries in one's build scripts and one wants to use those static libraries in linking the final executable, the order one mentions the .a
files is important:
g++ main.o hw.a gui.a -o executable
If gui.a
uses something defined in hw.a
the link will fail, because at the time hw.a
is processed, the linker doesn't yet know that the definition is needed later, and doesn't include it in the being.generated executable. Manually fiddling around with the linker line is not practical, so a solution is to use --start-group
and --end-group
which makes the linker run twice through the libraries until no undefined symbols are found anymore.
g++ main.o -Wl,--start-group hw.a gui.a -Wl,--end-group -o executable
However the GNU ld manual says
Using this option has a significant performance cost. It is best to use it only when there are unavoidable circular references between two or more archives.
So I thought that it may be better to take all .a
files and put them together into one .a
file with an index (-s
option of GNU ar) which says in what order the files need to be linked. Then one gives only that one .a
file to g++
.
But I wonder whether that's faster or slower than using the group commands. And are there any problems with that approach? I also wonder, is there better way to solve these interdependency problems?
EDIT: I've written a program that takes a list of .a
files and generates a merged .a
file. Works with the GNU common ar
format. Packing together all static libs of LLVM works like this
$ ./arcat -o combined.a ~/usr/llvm/lib/libLLVM*.a
I compared the speed against unpacking all .a
files manually and then putting them into a new .a
file using ar
, recomputing the index. Using my arcat
tool, I get consistent runtimes around 500ms. Using the manual way, time varies greatly, and takes around 2s. So I think it's worth it.
Code is here. I put it into the public domain :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可以使用 lorder 和 tsort 实用程序确定顺序,例如
生成
/usr/lib/libedit.a /usr/lib/libncurses.a< /code> 因为 libedit 依赖于 libncurses。
如果您不为每个链接命令再次运行
lorder
和tsort
,这可能只是高于--start-group
的好处。此外,它不允许像--start-group
那样的相互/循环依赖。You can determine the order using the
lorder
andtsort
utilities, for exampleresulting in
/usr/lib/libedit.a /usr/lib/libncurses.a
because libedit depends on libncurses.This is probably only a benefit above
--start-group
if you do not runlorder
andtsort
again for each link command. Also, it does not allow mutual/cyclic dependencies like--start-group
does.是否还有第三种选择,您只需构建一个库即可开始?我遇到了类似的问题,最终决定采用第三种选择。
根据我的经验,分组比统一 .a 文件要慢。您可以从存档中提取所有文件,然后从较小的文件中创建一个新的 .a 文件。
但是,您必须小心两个文件碰巧包含相同定义的情况(您可以使用 < code>nm 查看每个库中包含哪些定义)
Is there a third option where you just build a single library to begin with? I had a similar problem and I eventually decided to go with the third option.
In my experience, group is slower than just unifying the .a files. You can extract all files from the archive, then create a new .a file from from the smaller files
However, you have to be careful about a circumstance where both files happen to contain the same definition (you can explicitly check for this by using
nm
to see what definitions are contained in each library)