问题 LTO与LLVM和CMake


我正在尝试在CMake项目上应用链接时间优化和LLVM,这将创建一个共享库。我的问题几乎和这个问题一样:

使用CMake在GCC和Clang / LLVM之间切换

但是,答案似乎不再适用,因为 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运行其他步骤吗?


5322
2018-03-10 17:12


起源

这可能是一项工作 add_custom_command cmake ...喜欢的东西 add_custom_command(OUTPUT libTest.so COMMAND clang++ -shared optimized.bc -o libTest.so MAIN_DEPENDENCY optimized.bc) 看到 stackoverflow.com/questions/13470499/... - francis


答案:


使用Clang和启用LTO的正确方法是使用 -flto 国旗 clang 命令行都在编译时  链接时间。

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

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


7
2018-05-31 06:16





check_ipo_supported() 导致我在“政策CMP0069 未设置“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") 没有伤害。

选择您的命令行选项 取决于您的链接器

更残酷的选择

根据@ ChandlerCarruth的回答:

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

2
2017-10-27 00:35





在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


1
2017-07-31 19:38



请注意,使用全局设置时,必须在添加目标之前对其进行定义。 - mrks