链接时使用 --start-group 和 --end-group 是否比创建静态库更快?

发布于 2024-11-29 13:57:10 字数 1268 浏览 0 评论 0原文

如果在构建脚本中构建静态库并且想要使用这些静态库链接最终的可执行文件,则提及 .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 将它们放入新的 .a 文件进行了比较,重新计算索引。使用我的 arcat 工具,我获得了大约 500 毫秒的一致运行时间。采用手动方式,时间相差较大,需要2s左右。所以我认为这是值得的。

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

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

羁拥 2024-12-06 13:57:10

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

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

生成 /usr/lib/libedit.a /usr/lib/libncurses.a< /code> 因为 libedit 依赖于 libncurses。

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

You can determine the order using the lorder and tsort utilities, for example

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

resulting 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 run lorder and tsort again for each link command. Also, it does not allow mutual/cyclic dependencies like --start-group does.

土豪 2024-12-06 13:57:10

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

根据我的经验,分组比统一 .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)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文