Yan*_* TM 6 c++ macos compilation lto
我正在 Mac 上编译一些二进制文件,但是使用更新的编译器编译后的大小变得很大(从之前的 ~5MB 增加到 ~20MB)。我认为这与之前未激活的 LTO(链接时间优化)有关。我没有在 linux 上观察到这个文件膨胀。
在玩弄之后strip(实际上没有减少大小,尽管尝试基于 Xcode 的标志-S -x并且也没有标志,以及 GNU libtools strip 由 homebrew binutils 配方提供的标志-s,所有这些似乎都具有相同的效果)我找到了这个工具:https ://github.com/google/bloaty Bloaty McBloated,在我的二进制文件上运行时,它会产生以下输出:
FILE SIZE VM SIZE
-------------- --------------
53.9% 9.72Mi 53.8% 9.72Mi __GNU_LTO,__wrapper_sects
32.5% 5.86Mi 32.4% 5.86Mi __GNU_DWARF_LTO,__debug_info
6.2% 1.11Mi 6.2% 1.11Mi __TEXT,__text
2.2% 403Ki 2.2% 403Ki __TEXT,__eh_frame
1.6% 298Ki 1.6% 298Ki __GNU_LTO,__wrapper_names
1.0% 177Ki 1.0% 177Ki Export Info
0.7% 131Ki 0.7% 131Ki Weak Binding Info
0.4% 77.0Ki 0.4% 77.0Ki __GNU_DWARF_LTO,__debug_str
0.4% 75.8Ki 0.4% 75.8Ki __DATA,__gcc_except_tab
0.2% 44.6Ki 0.2% 44.6Ki __GNU_LTO,__wrapper_index
0.2% 39.4Ki 0.2% 39.4Ki __DATA_CONST,__const
0.2% 33.1Ki 0.2% 33.1Ki __GNU_DWARF_LTO,__debug_abbrev
0.1% 26.4Ki 0.1% 26.4Ki __GNU_DWARF_LTO,__debug_line
0.1% 21.7Ki 0.1% 23.6Ki [20 Others]
0.1% 19.0Ki 0.1% 19.0Ki __TEXT,__text_cold
0.1% 18.1Ki 0.1% 18.1Ki __TEXT,__const
0.0% 8.82Ki 0.0% 8.82Ki __TEXT,__text_startup
0.0% 8.60Ki 0.0% 8.60Ki __TEXT,__cstring
0.0% 0 0.0% 7.18Ki __DATA,__pu_bss5
0.0% 0 0.0% 6.88Ki __DATA,__bss5
0.0% 5.87Ki 0.0% 5.87Ki __DATA,__la_symbol_ptr
100.0% 18.1Mi 100.0% 18.1Mi TOTAL
Run Code Online (Sandbox Code Playgroud)
那么谁能告诉我这些巨大的*_LTO部分是做什么用的,以及如何通过后处理或向我的构建链添加编译标志来摆脱它们。
操作系统是 MacOS,我使用的是 g++ 10,完整的跟踪在这里:https : //github.com/yanntm/testGithbuActions/runs/1778387086?check_suite_focus=true
我正在尝试尽可能多地编译静态以获得更好的可移植性。然而,二进制文件仍然动态链接到 /usr/lib/libSystem.B.dylib(我显然不能用 libtool 静态链接这个)。
我不想要任何调试符号,因为这是面向最终用户的生产二进制文件。
您将在 gcc 的文档中找到答案:
\n\n\n链接时间优化是作为 GCC 前端实现的,用于 GIMPLE 的字节码表示,该表示在 .o 文件的特殊部分中发出。
\n[...]
\n由于 GIMPLE 字节码与最终目标代码一起保存,因此使用 LTO 支持生成的目标文件比常规目标文件更大。
\n[...]
\n当前的实现仅生成 \xe2\x80\x9cfat\xe2\x80\x9d 对象,有效地\n使编译时间加倍,并将文件大小增加到原始大小的 5 倍。
\n
但是等等,还有更多。您仅使用-flto. 你是否也用过-ffat-lto-objects,那么,如 gcc 的信息页面中所述:
\n\n\'-ffat-lto-objects\'
\n胖 LTO 对象是包含中间语言和目标代码的目标文件。这使得它们可用于 LTO\n链接和正常链接。此选项仅在使用 \'-flto\' 进行编译时才有效,并在链接时被忽略。
\n
尝试使用strip将是徒劳的。strip仅删除调试数据。这不是调试数据,而是基本上半编译的 C++ 代码,最终编译作为链接周期的一部分发生。如果您想“摆脱它们”,请不要使用 LTO。
编辑:某些 gcc/binutils 配置可能会在目标二进制文件中留下 LTO 部分。我研究了 Fedora 的默认 rpmbuild 配置,它默认使用 LTO 构建,但不会遭受相同的可执行文件膨胀。
\n事实证明,Fedora 的 rpmbuild 执行了一个brp-strip-lto脚本可归结为:
sh -c "$STRIP -p -R .gnu.lto_* -R .gnu.debuglto_* -N __gnu_lto_v1 \\"\\$@\\"" ARG0\nRun Code Online (Sandbox Code Playgroud)\n关键选项是两个-R选项,不清楚符号__gnu_lto_v1是什么,被删除-N。
| 归档时间: |
|
| 查看次数: |
370 次 |
| 最近记录: |