如何使用 CMake 启用 link 时间优化 (LTO)?

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

我有最新的 cmake 构建并尝试所有构建配置(Debug、MinSizeRel、RelWithDebugInfo、Release、General)我在生成的 makefile 中看不到任何地方(文本搜索)字符串 -lto、so 或功能仍然不存在,或者它需要手动干预(在这种情况下,文本搜索 LTO 或 Link 时间优化)文档没有给出任何结果,所以我在官方文档中看不到启用 LTO 的方法。

有没有什么方法可以启用 LTO "globally"(对于所有编译器)而无需手动指定标志,这些标志在最坏的情况下只能由 GCC 支持?

编辑:截至 2015 年 10 月 28 日在 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     

相关 CMake 问题:https://gitlab.kitware.com/cmake/cmake/issues/15245


CMake 在目标上有 INTERPROCEDURAL_OPTIMIZATION 属性,听起来它可能会在某些平台上启用 LTO。

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

要在目标 MyLib 上启用它:

add_library(MyLib ...)
...
set_property(TARGET MyLib PROPERTY INTERPROCEDURAL_OPTIMIZATION True)

是的,根据源代码,gcc/clang 编译器不支持 LTO。他们只支持英特尔编译器。

我有一些 cmake 3.4.3 的 grep 输出:

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)

如您所见,我们只有 Intel 平台模块。

所以我已经为这个非常有用的功能创建了功能请求:https://cmake.org/Bug/view.php?id=15939

好消息! CMake v3.9终于支持LTO.


例子

这里有一个示例代码来展示它是如何工作的:

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()

对于 GCC,这会将 -flto -fno-fat-lto-objects 添加到目标编译命令。


检查编译器支持

模块 CheckIPOSupported 提供检查 过程间优化 (IPO/LTO) 是否被编译器支持或不是:

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

如果未传递任何参数 (= check_ipo_supported()),则会引发错误以指示它不受支持,否则 result 变量将设置为 YESNO.模块的文档中描述了更多详细信息。


启用 LTO

单个目标默认[=78=启用LTO ] 所有目标。

单个目标的 LTO

为目标集启用 LTO INTERPROCEDURAL_OPTIMIZATION to TRUE. This is done by the set_property() 命令:

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

默认为 LTO

可以通过将 CMAKE_INTERPROCEDURAL_OPTIMIZATION 设置为 TRUE:

来默认启用 LTO
set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)

这将为该行之后创建的所有目标启用INTERPROCEDURAL_OPTIMIZATION。之前创建的不受影响。


另见

目前gcc和clang都支持lto。 (参见:https://clang.llvm.org/docs/CommandGuide/clang.html https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html ) 您可以通过 cmake 启用它: 设置(CMAKE_INTERPROCEDURAL_OPTIMIZATION 真) 但是你需要版本 cmake >= 3.9,我认为可能会设置一些策略并检查编译器/工具链是否支持 LTO(检查 CMAKE_IPO_AVAILABLE 否则抛出错误)

并为 gcc/clang 设置标志(-flto 和 -ffat-lto-files 用于 fcc >4.7 或 -flto=full/thin 用于 clang)