使用g++创建静态库的优化和标志

29

我刚开始在Linux上使用g++编译器,并对编译器标志有一些问题。以下是这些问题:

优化

我阅读了g++手册页面中关于优化标志 -O1-O2-O3的文章。我不明白何时应该使用这些标志。通常你使用哪种优化级别?g++手册对-O2如下所述:

进行更多优化。GCC执行几乎所有不涉及空间 - 速度权衡的支持优化。当指定-O2时,编译器不执行循环展开或函数内联。与-O相比,此选项增加了编译时间和生成代码的性能。

如果它不执行内联和循环展开,那么如何实现所述的性能益处,这个选项是否推荐使用?

静态库

我如何使用g++创建静态库?在Visual Studio中,我可以选择一个类库项目,然后它将被编译成“lib”文件。在g++中等价的是什么?


1
在2003年,GCC的-O3存在缺陷并且声名狼藉。现在只有当你违反规则时才会产生糟糕的代码,但人们喜欢打破规则,并且在后果发生时感到愤怒,因此他们坚持使用-O2以避免编写非法代码的后果。 - Mooing Duck
5个回答

41

经验之谈:

当你需要进行调试时,请使用 -O0(以及 -g 生成调试符号)。

当你准备发布时,请使用 -O2。

当你使用 gentoo 时,请使用 -O3...!

当你需要将其放在嵌入式系统中时,请使用 -Os(优化大小而非效率)。


7
为什么不在所有平台上都使用 -O3? Windows 无法处理 -O3 吗? 提示:-O3 是 GCC 和 Clang 编译器的优化标志,用于使生成的代码更快。 - Felipe
谢谢你的经验之谈,Josh。Linux man手册中没有包含这个关键的排序。 - john_science
1
我只是想为 -O3 这个东西辩护,指出它可能会带来更多问题而不是解决问题。-O3 默认情况下涉及循环展开和其他危险的优化,这些优化假设您的代码被调用的方式。作为经验法则,-O2 是安全的,但您应该有一个 /理由/ 去使用 -O3。 - joshk0
3
比这个回答更严肃和有用的解答可以在这里找到:https://dev59.com/Omgu5IYBdhLWcg3wJD2b?rq=1 - Scott

6

gcc手册列出了每个优化级别下的所有隐含选项。在O2级别下,您将获得像常量折叠、分支预测等功能,这些功能可以根据您的代码显著改变应用程序的速度。确切的选项因版本而异,但有详细的文档记录。

要构建静态库,您可以使用以下ar命令:

ar rc libfoo.a foo.o foo2.o ....
ranlib libfoo.a

不一定总是需要使用Ranlib,但没有理由不使用它。


根据 ranlib 的 man 手册,它与执行 ar -s 完全相同。我相信上面的内容可以简化为一行:ar rcs libfoo.a foo.o foo2.o ... - Daniel Stevens

4
关于何时使用哪种优化选项 - 没有单一正确的答案。
某些优化级别可能会降低性能。这取决于您正在编写的代码类型及其执行模式,并取决于您运行的特定CPU。
(举个简单的例子 - 编译器可以决定使用一种优化,使您的代码略微变大。这可能导致某个代码部分不再适合指令缓存,此时需要访问更多的内存 - 例如在循环中)。
最好根据您需要的内容进行测量和优化。尝试、测量和决定。
一个重要的经验法则是 - 对您的代码进行的优化越多,使用调试器(或阅读其反汇编)就越难调试它,因为C/C++源视图与生成的二进制文件越来越远。出于这个原因,在开发/调试时使用较少的优化是一个好的经验法则。

2

编译器除了循环展开和内联之外,还可以执行许多优化。之所以特别提到循环展开和内联,是因为虽然它们可以加速代码,但也会使代码变得更大。

要创建静态库,可以使用'g++ -c'生成.o文件,然后使用'ar'将它们归档到库中。


谢谢。什么是“ar”?它是g++编译器的开关还是shell?如果您能向我展示如何使用“ar”,那就太好了。 - Navaneeth K N
没问题。我已经检查了“ar”,并找到了它的手册。非常感谢。 - Navaneeth K N

0
关于静态库的问题,David Cournapeau 给出的答案是正确的,但您也可以使用 'ar' 的 's' 标志,而不是在静态库文件上运行 ranlib。 'ar' 手册页面 指出:

在存档上运行 ar s 等效于在其上运行 ranlib。

无论您使用哪种方法,都只是个人喜好的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接