5

I have a CMake project with several subprojects that create static libraries built with -flto=thin.

The project has a lot of tests that are linked against the aforementioned libraries. With LTO it takes a lot of time to build tests, therefore I have disabled LTO for tests using -fno-lto.

What I noticed though, is that lld performs LTO on tests even with -fno-lto. If I run the linker with --time-trace I can see that the majority of the time is spent on LTO.

My questions are:

  1. Is this expected? If so I can assume that lld performs LTO whenever it finds the LTO info in the object it links.
  2. If not, is there a way to disable this behavior? Adding -fno-lto to the compiler does not seem to work, and lld does not have a param to explicitly disable LTO.
  3. If not, is this a bug?

Update 1:

This is how I handle lto in CMake:

# 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()
Simone Rondelli
  • 356
  • 1
  • 18
  • Have you specified `-fno-lto` after `-flto=thin` (the rightmost settings wins)? Have you specified `-fno-lto` in a compiler flags (it should not be set on the linker flags)? – slsy May 10 '22 at 17:10
  • The tests do not have the `-flto=thin` at all (hence `-fno-lto` should be the default). To be sure I have explicitly added the `-fno-lto` param to the compiler. Updating the question. – Simone Rondelli May 10 '22 at 17:15
  • I cross-posted this in the LLVM bug tracker:https://github.com/llvm/llvm-project/issues/55431 – Simone Rondelli May 13 '22 at 12:16

1 Answers1

1

If you compile the libraries with -flto then, at least for gcc, the object files will only contain the intermediate language and no binary code.

That means when you link them into your test cases compiled with -fno-lto there is no binary code to link to. The linker has no choice but to first compile the intermediate language into binary for each needed function, which you would see as an LTO phase.

In gcc there is an option -ffat-lto-objects that tells gcc to include both the intermediate language as well as binary code in the object files. They can then be used for linking with LTO or without. The drawback is that this takes a bit longer to compile and produces larger object files.

You have to check if clang has the same option, they are usually pretty compatible with options.

Goswin von Brederlow
  • 11,875
  • 2
  • 24
  • 42
  • Thanks for the answer, this could explain the behavior. Unfortunately, clang does not seem to support `-ffat-lto-objects`. – Simone Rondelli May 16 '22 at 13:40
  • I posted this question to see if it is possible to have "fat LTO objects" with clang: https://stackoverflow.com/questions/72260320/clang-support-for-fat-lto-objects – Simone Rondelli May 16 '22 at 13:52