最近开发 C++ 的程序在链接阶段发生了一个 LTO 相关的错误。链接时优化(Link Time Optimization, LTO) 是一种编译优化技术,旨在通过在链接阶段执行全程序优化来提升代码性能和减少二进制文件大小。其主要原理是在链接阶段而不是在编译阶段进行更高级的优化,允许跨文件的全局优化。LTO 的基本原理和过程是:

  • 中间表示:在编译阶段,编译器将每个源文件编译为一种中间表示(如 LLVM bitcode),而不是直接生成目标代码。
  • 全局优化:在链接阶段,链接器将所有中间表示文件合并,生成一个完整的程序表示。此时,优化器可以进行跨文件的全局优化,如函数内联、去除冗余代码和跨模块优化。
  • 生成目标文件:优化完成后,链接器生成最终的可执行文件或库。

我遇到的错误信息中的管件一句是:

1
attempt to add bitcode file after LTO (htons)

可以看到错误信息提示我们链接系统试图在 LTO 优化之后添加 bitcode。并且在后面的括号中链接器提到了一个符号 htons,这是来自 libc 库的一个符号。基于的 https://github.com/emscripten-core/emscripten/issues/16836 这个链接中的启发,我发现了一个 LTO 优化可能面临的普遍性问题。这个问题是 LTO 会尝试移除一些它认为不需要的符号从而减少编译出来的程序的体积,但是这个判断可能会不准确。它可能将一些实际会被使用的符号删除。为了解决这个问题,我们可以为链接器指定链接输入,强制保留指定的符号以避免错误的移除。针对我遇到的情况,为链接器加上 -Wl,-u,htons 的配置即可解决问题。

  • -Wl: 这个标志告诉编译器将接下来的选项传递给链接器(ld)。-Wl,option 是传递给链接器的标准方法。
  • -u,symbol: 这个选项告诉链接器强制包含指定的符号 symbol。在这个情况下,-u,htons 和 -u,htonl 告诉链接器强制包含 htons 和 htonl 函数