How do I enable link time optimization (LTO) with CMake?
Asked Answered
I

5

53

I have the most recent cmake build and trying all build configurations (Debug, MinSizeRel, RelWithDebugInfo, Release, General) I see nowhere (text search) in generated makefiles the string -lto, so or the functionality is still not present, or it requires manual intervertion (in that case a text search for LTO or Link time optimization) over the documentation gives no result, so I see nowhere in official documentation a way to enable LTO.

Is there any way to enable LTO "globally" (for all compilers) without specifying manually flags that could be at worst supported only by GCC?

Inaugural answered 11/7, 2015 at 9:37 Comment(1)
Nowadays, CMake do not have a crossplatform support for LTO. You ought to add it by yourself by adding desired compile options and using corresponding tools (like gcc-ar, gcc-nm and gcc-ranlib instead of defaults) because binutils, AFAIK, nowadays is not completely ready for this as well.Implicit
H
16

Edit: as of 28 October, 2015 on CMake IRC

jcelerier | I have a question about INTERPROCEDURAL_OPTIMIZATION
jcelerier | it sounds like it should enable -flto on gcc
+ngladitz | jcelerier: its only implemented for the intel compiler
jcelerier | ngladitz: ah, okay
jcelerier | are there other switches for pgo / lto ?
jcelerier | or must it be done by hand ?
+ngladitz | there currently is no first class support otherwise     

Related CMake issue: https://gitlab.kitware.com/cmake/cmake/issues/15245


CMake has the INTERPROCEDURAL_OPTIMIZATION property on targets, which sounds like it may enable LTO on some platforms.

Link : http://www.cmake.org/cmake/help/v3.0/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.html

To enable it on a target MyLib :

add_library(MyLib ...)
...
set_property(TARGET MyLib PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
Humanoid answered 20/7, 2015 at 17:23 Comment(4)
cmake documentation is verly lacky, just for completeness how someone is supposed to enable that flag in a Cmake script?Inaugural
@darioOO Added to the answerNonexistence
This seems like the CMake way to do it. However when testing on Debian Jessie with CMake 3.0 and gcc 4.9.2 and clang 3.5.0 this did not seem to activate any lto related compiler flags. :-/Resect
Edited my answer accordingly.Nonexistence
W
108

Good news! CMake v3.9 finally supports LTO.


Example

Here's an example code to show how it works:

cmake_minimum_required(VERSION 3.9.4)

include(CheckIPOSupported)
check_ipo_supported(RESULT supported OUTPUT error)

add_executable(example Example.cpp)

if( supported )
    message(STATUS "IPO / LTO enabled")
    set_property(TARGET example PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)
else()
    message(STATUS "IPO / LTO not supported: <${error}>")
endif()

For GCC this adds -flto -fno-fat-lto-objects to the targets compile commands.


Checking Compiler Support

The Module CheckIPOSupported provides checking whether interprocedural optimization (IPO/LTO) is supported by the compiler or not:

check_ipo_supported([RESULT <result>] [OUTPUT <output>]
                    [LANGUAGES <lang>...])

If no arguments is passed (= check_ipo_supported()) an error is raised to indicate it's not supported, otherwise the result variable is set to either YES or NO. More details are described in the documentation of the module.


Enabling LTO

LTO is enabled either for a single target or as default for all targets.

LTO for a single target

To enable LTO for a target set INTERPROCEDURAL_OPTIMIZATION to TRUE. This is done by the set_property() command:

set_property(TARGET name-target-here
             PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE)

LTO as default

It's possible to enable LTO per default by setting CMAKE_INTERPROCEDURAL_OPTIMIZATION to TRUE:

set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)

This will enable INTERPROCEDURAL_OPTIMIZATION for all targets created after this line. Those created before are not affected.


See also

Writeoff answered 18/11, 2017 at 20:30 Comment(8)
For LTO as default: "for all targets created after this line", this is supposed to affect child projects too (e.g. from add_subdirectory) right?Dangle
Short answer: Yes.Writeoff
Why the <beep> does a make tool need to support a particular compiler option?!?!Chasitychasm
I found that CMAKE_INTERPROCEDURAL_OPTIMIZATION works more reliably than setting INTERPROCEDURAL_OPTIMIZATION for individual targets, and mixing targets with and without LTO does not seem to work well. With Clang, I had link errors when linking LTO-ed libraries into a non-LTO target. Also, with MSVC setting LTO for targets individually will make the linker complain about it being incompatible with incremental linking.Kelso
Why the heck do I have to check for support myself? Edit: cmake.org/cmake/help/git-stage/policy/CMP0069.htmlEaglestone
So it's easier to just set the flags myself which I do anyway, and I have full control.Eaglestone
To give the rightful rant of @Eaglestone some context: setting the variable is not enough. In their deep wisdom the cmake devs have decided that the project also needs to manually add a check for LTO into the project's cmakefile. Only if that's there you may enable LTO with -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=TRUE. Of course nobody does that and you are forced to edit the project files...Supercolumnar
What's up with C++ programmers and build system (generators) they produce with an attitude that causes everything to look like they were tasked with half-assing something but they went ahead and half-assed the half-assing? 21 years of development, and all we have is some basic handwritten Makefile-tier if else to test whether compiler can into LTO, really now? Should I just write my own Makefile generator at this point if I want something to just work?Autotomy
H
16

Edit: as of 28 October, 2015 on CMake IRC

jcelerier | I have a question about INTERPROCEDURAL_OPTIMIZATION
jcelerier | it sounds like it should enable -flto on gcc
+ngladitz | jcelerier: its only implemented for the intel compiler
jcelerier | ngladitz: ah, okay
jcelerier | are there other switches for pgo / lto ?
jcelerier | or must it be done by hand ?
+ngladitz | there currently is no first class support otherwise     

Related CMake issue: https://gitlab.kitware.com/cmake/cmake/issues/15245


CMake has the INTERPROCEDURAL_OPTIMIZATION property on targets, which sounds like it may enable LTO on some platforms.

Link : http://www.cmake.org/cmake/help/v3.0/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.html

To enable it on a target MyLib :

add_library(MyLib ...)
...
set_property(TARGET MyLib PROPERTY INTERPROCEDURAL_OPTIMIZATION True)
Humanoid answered 20/7, 2015 at 17:23 Comment(4)
cmake documentation is verly lacky, just for completeness how someone is supposed to enable that flag in a Cmake script?Inaugural
@darioOO Added to the answerNonexistence
This seems like the CMake way to do it. However when testing on Debian Jessie with CMake 3.0 and gcc 4.9.2 and clang 3.5.0 this did not seem to activate any lto related compiler flags. :-/Resect
Edited my answer accordingly.Nonexistence
S
2

Revisiting this problem again in a project where I had to include the cmake configuration of an immutable subproject, it seems the most forceful way to enable LTO is adding this before defining any targets or including anything:

set(CMAKE_POLICY_DEFAULT_CMP0069 NEW)
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)

This enables LTO and shuts up CMAKE even if later included projects did not handle LTO via CheckIPOSupported themselves.

Supercolumnar answered 31/10, 2023 at 13:19 Comment(0)
B
1

Yep, according to source code there are no support for LTO for gcc/clang compilers. They have some support for Intel compiler only.

I have some grep output for cmake 3.4.3:

grep -HiR 'INTERPROCEDURAL_OPTIMIZATION' *
Help/manual/cmake-properties.7.rst:  
/prop_dir/INTERPROCEDURAL_OPTIMIZATION_CONFIG
Help/manual/cmake-properties.7.rst:  
/prop_dir/INTERPROCEDURAL_OPTIMIZATION
Help/manual/cmake-properties.7.rst:  
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG
Help/manual/cmake-properties.7.rst:  
/prop_tgt/INTERPROCEDURAL_OPTIMIZATION
Help/prop_dir/INTERPROCEDURAL_OPTIMIZATION.rst:INTERPROCEDURAL_OPTIMIZATION
Help/prop_dir/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst:INTERPROCEDURAL_OPTIMIZATION_<CONFIG    
Help/prop_dir/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst:This is a
per-configuration version of INTERPROCEDURAL_OPTIMIZATION.
Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION.rst:INTERPROCEDURAL_OPTIMIZATION
Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst:INTERPROCEDURAL_OPTIMIZATION_<CONFIG    
Help/prop_tgt/INTERPROCEDURAL_OPTIMIZATION_CONFIG.rst:This is a
per-configuration version of INTERPROCEDURAL_OPTIMIZATION.
Modules/Platform/Linux-Intel.cmake:    # INTERPROCEDURAL_OPTIMIZATION
Source/cmCommonTargetGenerator.cxx: 
if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
Source/cmGeneratorTarget.cxx:          
"INTERPROCEDURAL_OPTIMIZATION", config))
Source/cmMakefileLibraryTargetGenerator.cxx: 
if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION") &&
Tests/IPO/CMakeLists.txt:set_property(DIRECTORY PROPERTY
INTERPROCEDURAL_OPTIMIZATION 1)

As you can see we have only Intel platform module.

So I have created feature request for this extremely useful feature: https://cmake.org/Bug/view.php?id=15939

Below answered 28/1, 2016 at 12:42 Comment(0)
B
-2

At the moment both gcc and clang support lto. (See: https://clang.llvm.org/docs/CommandGuide/clang.html https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html ) You can enable it in via cmake: set (CMAKE_INTERPROCEDURAL_OPTIMIZATION True) However you need to have version cmake >= 3.9, and I think may be set some policy and check whether LTO is supported by the compiler / toolchain ( check CMAKE_IPO_AVAILABLE and throw error otherwise)

And set flags for gcc/clang ( -flto and -ffat-lto-files for fcc >4.7 or -flto=full/thin for clang)

Battista answered 27/2, 2020 at 12:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.