When using LTO, we should repeat the compiler flags when linking. LTO basically recompiles by taking IR generated from all object files that will be part of the executable. Since it knows all the code that is going into the executable, it can do more optimisations.
Now since it does the whole IR → assembly code generation again at link time, the compile options at that time are important.
Impact Example
extern int x;
void foo() { x++; }
int main() {}
The simple program above compiles when compiled with
gcc lto-test.c -ffunction-sections -c
gcc lto-test.o -Wl,--gc-sections
This is because foo()
is not referenced anywhere and due to it being present in a different section which is unused, it gets removed from the executable. So, there’s no undefined reference to x
error.
If we add -flto
only to the compilation command, the link command gives the error:
/usr/bin/ld: /tmp/cclh6LYv.ltrans0.ltrans.o: in function `foo()':
<artificial>:(.text+0x7): undefined reference to `x'
This is because the linker command doesn’t know to put functions in different sections. Adding -ffunction-sections
to the link command fixes the error.
NOTE: Using CMake and enabling CMAKE_INTERPROCEDURAL_OPTIMIZATION
doesn’t copy compiler options either as we would expect.