【问题标题】:LTO with LLVM and CMakeLTO 与 LLVM 和 CMake
【发布时间】:2016-06-25 16:18:54
【问题描述】:

我正在尝试在创建共享库的 CMake 项目上使用 LLVM 应用链接时间优化。我的问题和这个差不多:

Switching between GCC and Clang/LLVM using CMake

但是,答案似乎不再适用,因为 llvm-ld 在新版本中不存在。在命令行上,我运行以下命令来获取 LTO(假设只有 2 个.cpp 文件):

编译成字节码:

clang++ -c FirstClass.cpp -O3 -flto -o FirstClass.bc
clang++ -c SecondClass.cpp -O3 -flto -o SecondClass.bc

链接字节码:

llvm-link FirstClass.bc SecondClass.bc -o unoptimized.bc

优化字节码:

opt -O3 unoptimized.bc -o optimized.bc

将字节码转换为共享对象:

clang++ -shared optimized.bc -o libTest.so

有人可以告诉我如何让 CMake 运行其他步骤吗?

【问题讨论】:

标签: c++ cmake clang llvm lto


【解决方案1】:

使用 Clang 和启用 LTO 的正确方法是在编译 链接时将 -flto 标志用于 clang 命令行。

此外,您将需要在具有直接支持 LTO(通常是 Apple 的平台)或具有 LLVM 链接器插件(使用 Gold 链接器的 Linux,但我认为有些人已经获得 BFD 的链接器)的平台上工作链接器也支持链接器插件)。如果您使用的是链接器插件,则需要确保您安装的 LLVM 已构建并安装了该插件。如果是这样,当与-flto 链接时,Clang 将自动添加必要的链接器命令行选项以使用该插件,即使对于共享对象也是如此。

此外,LLVM 项目正在开发一个新的链接器 (LLD),它将在其支持的所有平台上支持开箱即用的 LTO,但仍处于早期阶段。目前我知道有人在 Windows 和 Linux 上测试了它的 LTO 支持,它似乎运行良好,但仍然缺少许多功能。

【讨论】:

    【解决方案2】:

    check_ipo_supported() 导致我在 CMake 3.9.1 上出现“Policy CMP0069 未设置”错误。

    根据其帮助,最高 3.8 的 CMake 仅支持英特尔编译器的 LTO。它对我来说也不适用于 XCode 9 的叮当声。

    到底有什么效果:

    cmake_policy(SET CMP0069 NEW)
    include(CheckIPOSupported)
    check_ipo_supported()
    
    add_executable(Foobar SOURCES)
    set_target_properties(Foobar PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
    

    看起来add_executable() 需要在cmake_policy(SET CMP0069 NEW) 之后。

    LTO 缓存

    target_link_libraries(Foobar "-Wl,-cache_path_lto,${PROJECT_BINARY_DIR}/lto.cache") 没有伤害。

    选择你的命令行选项depending on your linker

    更残酷的选择

    根据@ChandlerCarruth 的回答:

    if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
        set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto")
        target_link_libraries(Foobar -flto)
    endif ()
    

    【讨论】:

      【解决方案3】:

      在 Cmake 3.9 和更高版本上启用(瘦)lto 应该很简单:

      include(CheckIPOSupported)
      check_ipo_supported()
      set_target_properties(myProject PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
      

      可以对每个项目进行 set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE) 的单个全局设置,而不是 set_target_properties

      为了加快重新编译的速度,可以为 LTO 设置一个缓存:

      function(append value)
          foreach(variable ${ARGN})
              set(${variable} "${${variable}} ${value}" PARENT_SCOPE)
          endforeach(variable)
      endfunction()
      
      append("-fuse-ld=gold -Wl,--no-threads,--plugin-opt,cache-dir=${PROJECT_BINARY_DIR}/lto.cache" CMAKE_EXE_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS)
      

      这会强制 gold 作为链接器,以便使用正确的命令行选项。它可能需要/usr/lib/LLVMgold.so/usr/lib/llvm-4.0/lib/LLVMgold.so 的符号链接。

      【讨论】:

      • 请注意,使用全局设置时,必须在添加目标之前对其进行定义。
      • 有没有办法让 cmake 通过 -flto 而不是 -flto=thin?
      猜你喜欢
      • 2017-03-14
      • 2023-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-05
      • 1970-01-01
      • 2014-04-20
      相关资源
      最近更新 更多