【问题标题】:How do I enable link time optimization (LTO) with CMake?如何使用 CMake 启用链接时间优化 (LTO)?
【发布时间】:2015-09-30 02:00:37
【问题描述】:

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

是否有任何方法可以“全局”启用 LTO(适用于所有编译器),而无需手动指定只能由 GCC 支持的标志?

【问题讨论】:

  • 现在,CMake 没有对 LTO 的跨平台支持。您应该通过添加所需的编译选项并使用相应的工具(如 gcc-argcc-nmgcc-ranlib 而不是默认值)自行添加它,因为 binutils、AFAIK 现在还没有完全准备好。跨度>

标签: cmake lto


【解决方案1】:

好消息! 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/LT​​O)

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

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


启用 LTO

单个目标启用LTO,或为所有目标启用默认

单个目标的 LTO

为目标集启用 LTO,将 INTERPROCEDURAL_OPTIMIZATION 设置为 TRUE。这是通过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。之前创建的不受影响。


另见

【讨论】:

  • 对于 LTO 作为默认值:“对于在此行之后创建的所有目标”,这应该也会影响子项目(例如来自 add_subdirectory)对吗?
  • 简短回答:是的。
  • 为什么 make 工具需要支持特定的编译器选项?!?!
  • 我发现 CMAKE_INTERPROCEDURAL_OPTIMIZATION 比为单个目标设置 INTERPROCEDURAL_OPTIMIZATION 更可靠,并且混合使用和不使用 LTO 的目标似乎效果不佳。使用 Clang,在将 LTO 版库链接到非 LTO 目标时出现链接错误。此外,使用 MSVC 为目标单独设置 LTO 会使链接器抱怨它与增量链接不兼容。
  • 为什么我必须自己检查支持?编辑:cmake.org/cmake/help/git-stage/policy/CMP0069.html
【解决方案2】:

编辑:截至 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。

链接: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)

【讨论】:

  • cmake 文档非常缺乏,只是为了完整起见,应该如何在 Cmake 脚本中启用该标志?
  • @darioOO 添加到答案中
  • 这似乎是 CMake 的做法。但是,当使用 CMake 3.0 和 gcc 4.9.2 和 clang 3.5.0 在 Debian Jessie 上进行测试时,这似乎没有激活任何与 lto 相关的编译器标志。 :-/
  • 相应地编辑了我的答案。
【解决方案3】:

是的,根据源代码,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)

如您所见,我们只有英特尔平台模块。

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

【讨论】:

    【解决方案4】:

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

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

    【讨论】:

      猜你喜欢
      • 2014-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-12-15
      • 1970-01-01
      • 1970-01-01
      • 2019-12-22
      • 2010-11-07
      相关资源
      最近更新 更多