Compile flags in the linking command for link time optimization

According to gcc documentation for link time optimization:

It is recommended that you compile all the files participating in the same link with the same options and also specify those options at link time

I specify in CML.txt the following:


to see the actual emitted compile and linking command. My compile commands are like so [snipped for brevity]:

[33%] Building CXX object CMakeFiles/CMakeProject.dir/code/main.cpp.o

/usr/bin/c++ -O3 -flto -fno-fat-lto-objects -fPIE -m64 -fno-common -fPIC -fno-strict-aliasing -fexceptions -fopenmp -DNDEBUG -o CMakeFiles/CMakeProject.dir/code/main.cpp.o -c code/main.cpp

[ 66%] Building CXX object CMakeFiles/CMakeProject.dir/code/impl.cpp.o

/usr/bin/c++ -O3 -flto -fno-fat-lto-objects -fPIE -m64 -fno-common -fPIC -fno-strict-aliasing -fexceptions -fopenmp -DNDEBUG -o CMakeFiles/CMakeProject.dir/code/impl.cpp.o -c code/impl.cpp

The emitted linking command is like so:

[100%] Linking CXX executable CMakeProject
/snap/cmake/1336/bin/cmake -E cmake_link_script CMakeFiles/CMakeProject.dir/link.txt --verbose=1
/usr/bin/c++ -O3 -flto -fno-fat-lto-objects code/main.cpp.o code/impl.cpp.o -o CMakeProject -Wl,-rpath,/usr/local/lib -lm -lpthread -ldl

In particular, unlike as suggested over in the GCC site, I do not see flags such as -fPIC, etc., which feature in the compile stage appear in the linking stage. Although, I do see that both the linker and the compiler make use of -flto.

Is this because some of the flags that appear in the compile stage are not relevant to the linking stage? Is there CMake documentation of which flags are applicable to both the linker and the compiler and which are not? Clearly, CMake should be using this information to generate the right linking command for inter procedural/link time optimization.

Regarding POSITION_INDEPENDENT_CODE, to get correct flags at link step, you have to explicitly ask for by using CheckPIESupported module.
The reason for a such approach is the cost of a such test. It is too costly to be done at configuration, which would impact all users.

For -flto and others flags, involved in inter-procedural optimization, they are defined in both steps (compilation and link) because CMake offers a high-level concept (i.e. INTERPROCEDURAL_OPTIMIZATION target property) to manage this.

For the other flags, I am afraid it is your responsibility to set them for the link step (using target_link_options() command because CMake has no high-level concept for them so is not aware of the semantics attached to them (in particular what are the interaction between compilation and link steps).

1 Like

CMake documentation on IPO states this:

If set to true, enables interprocedural optimizations if they are known to be supported by the compiler.

Usage of the word “enable” in the documentation is my source of confusion. If I understand correctly, what the option actually does is that when the user sets this option to true, and the compiler supports it, the -flto flag is added at the compile as well as the link stage. That is it. To actually generate an executable that has benefitted from IPO, it is still the user’s responsibility to additionally manually figure out which others flags are to be added to the linker stage that also feature in the compile stage as recommended by GCC.

If I have understood this correctly based on your response, this is useful to know because it appears to me that the wording in the documentation should make this explicit: setting the option to true does not really “enable” IPO in that the resulting executable/target can be produced using IPO. It merely adds the flag -flto to the compiler and the linker.

Thank you for the response.