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

Joh*_*itb 11 linker static-libraries unix-ar .a

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

g++ main.o hw.a gui.a -o executable
Run Code Online (Sandbox Code Playgroud)

如果gui.a使用hw.a链接中定义的内容将失败,因为在hw.a处理时,链接器尚不知道稍后需要该定义,并且不将其包含在is.generated可执行文件中.与连接线手动摆弄周围是不实际的,所以解决方案是使用--start-group--end-group它通过库使得连接器运行两次,直到没有未定义的符号被发现了.

g++ main.o -Wl,--start-group hw.a gui.a -Wl,--end-group -o executable
Run Code Online (Sandbox Code Playgroud)

然而,GNU ld手册说

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

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

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


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

$ ./arcat -o combined.a ~/usr/llvm/lib/libLLVM*.a
Run Code Online (Sandbox Code Playgroud)

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

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

Foo*_*Bah 2

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

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

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

  • 即使 libB 依赖于 libA,它们作为单独的库也可以,只要 libA 可以独立于 libB 使用即可。但如果两者之间存在**相互依赖**,那么将它们分开纯粹是一种麻烦。 (3认同)
  • +1 当库相互依赖时,创建两个库绝对没有意义。 (2认同)