即使传递了 -fno-lto,lld 也会运行 LTO

lld runs LTO even if -fno-lto is passed

我有一个包含多个子项目的 CMake 项目,这些子项目创建了使用 -flto=thin 构建的静态库。

该项目有很多链接到上述库的测试。使用 LTO 构建测试需要花费大量时间,因此我使用 -fno-lto.

禁用了 LTO 测试

不过我注意到,lld 即使使用 -fno-lto 也会在测试中执行 LTO。如果我 运行 带有 --time-trace 的链接器,我可以看到大部分时间都花在了 LTO 上。

我的问题是:

  1. 这是预期的吗?如果是这样,我可以假设 lld 在它链接的对象中找到 LTO 信息时执行 LTO。
  2. 如果没有,是否有办法禁用此行为?将 -fno-lto 添加到编译器似乎不起作用,并且 lld 没有明确禁用 LTO 的参数。
  3. 如果不是,这是一个错误吗?

更新 1:

这是我在 CMake 中处理 lto 的方式:

# Enable Thin LTO only on non-test targets.
if(ENABLE_LTO)
  if (IS_TEST)
    target_compile_options(${TARGET} PRIVATE -fno-lto)
    # Probably pointless.
    target_link_options(${TARGET} PRIVATE -fno-lto)
  else()
    message(STATUS "ENABLE_LTO on target ${TARGET})")
    target_compile_options(${TARGET} PRIVATE -flto=thin)
    target_link_options(${TARGET} PRIVATE -flto=thin -Wl,--thinlto-cache-dir=${CMAKE_BINARY_DIR}/lto.cache)
  endif()
endif()

如果你用 -flto 编译库,那么至少对于 gcc 来说,目标文件将只包含中间语言而不包含二进制代码。

这意味着当您 link 将它们放入用 -fno-lto 编译的测试用例时,没有二进制代码到 link 。 linker 别无选择,只能先将中间语言编译成二进制文件,用于每个需要的功能,您可以将其视为 LTO 阶段。

在 gcc 中有一个选项 -ffat-lto-objects 告诉 gcc 在目标文件中包括中间语言和二进制代码。然后,无论是否使用 LTO,它们都可以用于 linking。缺点是这需要更长的时间来编译并生成更大的目标文件。

你必须检查 clang 是否有相同的选项,它们通常与选项兼容。