我正在尝试在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运行其他步骤吗?
答案 0 :(得分:10)
使用Clang和启用LTO的正确方法是在编译和链接时将<div>
{{campaigns[].name}}
...
</div>
标志用于-flto
命令行。
此外,您需要在具有链接器的平台上工作,该链接器直接支持LTO(通常是Apple的平台)或具有LLVM链接器插件(Linux使用Gold链接器,但我认为一些已经让BFD链接器支持链接器插件)。如果您正在使用链接器插件,则需要确保安装了LLVM并安装了该插件。如果是这样,Clang将自动添加必要的链接器命令行选项,以便在链接clang
时使用该插件,即使对于共享对象也是如此。
此外,LLVM项目正在开发一个新的链接器(LLD),它将在它支持的所有平台上支持LTO开箱即用,但它仍处于早期阶段。目前我知道有人在Windows和Linux上测试其LTO支持,它似乎运行良好,但仍然遗漏了许多功能。
答案 1 :(得分:2)
在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
的符号链接。
答案 2 :(得分:2)
check_ipo_supported()
导致我进入&#34; Policy CMP0069未设置&#34; CMake 3.9.1上的错误。
根据它的帮助,CM高达3.8仅支持英特尔编译器的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 ()