使用 LLVM 和 CMake 的 LTO
LTO with LLVM and CMake
我正在尝试在创建共享库的 CMake 项目上应用 Link 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
Link字节码:
llvm-link FirstClass.bc SecondClass.bc -o unoptimized.bc
优化字节码:
opt -O3 unoptimized.bc -o optimized.bc
将字节码转换为共享对象:
clang++ -shared optimized.bc -o libTest.so
有人可以告诉我如何使用 CMake 运行 额外的步骤吗?
使用 Clang 和启用 LTO 的正确方法是在编译 和 link 时对 clang
命令行使用 -flto
标志] 时间。
此外,您需要在带有 linker 的平台上工作,该平台要么直接支持 LTO(通常是 Apple 的平台),要么具有 LLVM linker 插件(Linux 使用 Gold linker,但我认为有些人已经使用 BFD linker 来支持 linker 插件)。如果您使用的是 linker 插件,则需要确保您安装的 LLVM 已构建并安装了该插件。如果是这样,Clang 将自动添加必要的 linker 命令行选项,以便在 link 使用 -flto
时使用插件,即使对于共享对象也是如此。
此外,LLVM 项目正在开发一个新的 linker (LLD),它将在其支持的所有平台上开箱即用地支持 LTO,但仍处于早期阶段。目前我知道有人在 Windows 和 Linux 上测试其 LTO 支持,它似乎运行良好但仍然缺少许多功能。
在 Cmake 3.9 和更新版本上启用(瘦)lto 应该很简单:
include(CheckIPOSupported)
check_ipo_supported()
set_target_properties(myProject PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
不是每个项目 set_target_properties
,而是可以完成 set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
的单个全局设置。
为了加快重新编译速度,可以设置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
的符号链接。
check_ipo_supported()
导致我在 CMake 3.9.1 上出现“Policy CMP0069 未设置”错误。
根据其帮助,CMake up to 3.8 仅支持 Intel 编译器的 LTO。它对 XCode 9 的 clang 也不起作用。
到底是什么起作用了:
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 ()
我正在尝试在创建共享库的 CMake 项目上应用 Link 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
Link字节码:
llvm-link FirstClass.bc SecondClass.bc -o unoptimized.bc
优化字节码:
opt -O3 unoptimized.bc -o optimized.bc
将字节码转换为共享对象:
clang++ -shared optimized.bc -o libTest.so
有人可以告诉我如何使用 CMake 运行 额外的步骤吗?
使用 Clang 和启用 LTO 的正确方法是在编译 和 link 时对 clang
命令行使用 -flto
标志] 时间。
此外,您需要在带有 linker 的平台上工作,该平台要么直接支持 LTO(通常是 Apple 的平台),要么具有 LLVM linker 插件(Linux 使用 Gold linker,但我认为有些人已经使用 BFD linker 来支持 linker 插件)。如果您使用的是 linker 插件,则需要确保您安装的 LLVM 已构建并安装了该插件。如果是这样,Clang 将自动添加必要的 linker 命令行选项,以便在 link 使用 -flto
时使用插件,即使对于共享对象也是如此。
此外,LLVM 项目正在开发一个新的 linker (LLD),它将在其支持的所有平台上开箱即用地支持 LTO,但仍处于早期阶段。目前我知道有人在 Windows 和 Linux 上测试其 LTO 支持,它似乎运行良好但仍然缺少许多功能。
在 Cmake 3.9 和更新版本上启用(瘦)lto 应该很简单:
include(CheckIPOSupported)
check_ipo_supported()
set_target_properties(myProject PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
不是每个项目 set_target_properties
,而是可以完成 set(CMAKE_INTERPROCEDURAL_OPTIMIZATION TRUE)
的单个全局设置。
为了加快重新编译速度,可以设置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
的符号链接。
check_ipo_supported()
导致我在 CMake 3.9.1 上出现“Policy CMP0069 未设置”错误。
根据其帮助,CMake up to 3.8 仅支持 Intel 编译器的 LTO。它对 XCode 9 的 clang 也不起作用。
到底是什么起作用了:
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 ()