ale*_*cov 0 c c++ gcc visual-c++ lto
在编写代码或构建脚本以使用LTO进行编译时,需要记住哪些注意事项和陷阱?
这个问题背后的动机是更好地理解为什么启用LTO时为什么某些项目不能完全编译。特别是,无论是在MSVC还是在GCC中,我都无法构建启用LTO的ICU。在其他情况下,我可以使用给定的工具链版本启用LTO,但不能使用另一个(较新的)版本启用LTO。例如,这发生在libiconv中。
在我遇到的所有失败案例中,都涉及到由于符号未解析导致的链接失败。
为什么会这样呢?这是工具链,构建脚本还是源代码的问题?
这个答案总结了我的发现,涉及在GCC和MSVC中构建启用LTO的项目时涉及的一些复杂性。
首先,按照GCC Wiki的要求,要正确构建启用了LTO的项目,您必须:
gcc-ar使用而不是binutils ar;gcc-ranlib使用而不是binutils ranlib;gcc-nm使用而不是binutils nm;-flto。这意味着在传统./configure && make循环中,必须注意设置和的值AR=,RANLIB=并NM=在相关时使用。仅此而已;但是,这些步骤很容易被忽略,因为需要更改eg的值。AR很少见。
现在到问题:
在GCC 4.8和更早版本中,编译器默认发出胖对象文件。这意味着即使后编译工具(链接器,归档器等)无法识别LTO对象,它们也可以正常工作(但实际上并没有执行LTO)。
在GCC 4.9和更高版本中,编译器默认发出细长的目标文件,这意味着编译后工具必须识别LTO对象,否则工具将失败。这就解释了为什么有时在使用GCC 4.8时LTO构建会通过,而在使用GCC 4.9及更高版本时会失败。
我还注意到,构建脚本并不一定总是在需要时正确地将某些配置指令的值传递给子脚本。例如,当libiconv在MinGW-w64中使用LTO 构建静态对象时,configure脚本仍会libtool使用ar而不是来配置内部gcc-ar,即使被告知AR=gcc-ar。
LTO构建倾向于发现隐藏的错误,尤其是由静态初始化顺序惨败引起的错误。它们还可以妨碍其他优化,例如ICF(由Gold执行)。
最后,LTO机制中显然仍然存在许多错误。尝试使用启用了LTO和其他优化功能的MinGW-w64编译ICU时,我遇到了此错误和内部编译器错误(internal compiler error: in splice_child_die, at dwarf2out.c,可能-g与LTO配合使用)。
所有这些意味着,由于工具链中的一些缺陷,使用LTO建立随机项目仍然是不容易的。一些项目将成功构建,而另一些则不会。
要在MSVC中使用LTO进行编译(称为LTCG),/GL必须在编译/LTCG时使用,并且在链接时必须使用,实际上就是如此。
然而,当LTCG在MSVC启用,编译器不会发出传统的COFF对象。而是发出一种特殊的目标文件,其中包含IR,其标题(ANON_OBJECT_HEADER_BIGOBJ)与COFF标题(IMAGE_FILE_HEADER)不同。显然,这在构建项目时根本没有任何区别,因为这些细节留给了工具链来处理。
现在,当在MSVC中启用LTCG时,为什么ICU无法正确构建?
ICU有一个称为的工具pkgdata,可以为给定的体系结构生成目标代码。在构建过程中,该工具用于构建软件包中的其他实用程序。但是,pkgdata尝试通过检查给定的参考对象文件来猜测目标体系结构。在Windows中,该工具采用COFF标头,而在32位版本中,该工具错误地确定以64位体系结构为目标(由于内部的草率逻辑pkg_genc.c:getArchitecture())。因此,MSVC 32位LTCG构建失败。
| 归档时间: |
|
| 查看次数: |
1276 次 |
| 最近记录: |