LTO с LLVM и CMake

Я пытаюсь применить Link Time Optimization с LLVM к проекту CMake, который создает общую библиотеку. Мой вопрос почти такой же, как этот:

Переключение между GCC и Clang / LLVM с использованием 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 запускал дополнительные шаги?

12

Решение

Правильный способ использования Clang и включения LTO — использование -flto флаг к clang командная строка как при компиляции а также время ссылки.

Кроме того, вам нужно будет работать на платформе с компоновщиком, который либо напрямую поддерживает LTO (платформы Apple в целом), либо имеет плагин компоновщика LLVM (Linux использует компоновщик Gold, но я думаю, что некоторые получили компоновщик BFD для поддержки плагин компоновщика также). Если вы используете плагин компоновщика, вам необходимо убедиться, что в вашей установке LLVM собран и установлен плагин. Если это так, Clang автоматически добавит необходимые параметры командной строки компоновщика, чтобы использовать плагин при связывании с -fltoдаже для общих объектов.

Кроме того, проект LLVM работает над новым компоновщиком (LLD), который будет поддерживать LTO «из коробки» на всех платформах, которые он поддерживает, но это все еще довольно ранние времена. В настоящее время я знаю о людях, которые тестируют его поддержку LTO в Windows и Linux, и, кажется, он работает хорошо, но все еще скучает по многим функциям.

8

Другие решения

Включение (тонкого) lto на Cmake 3.9 и новее должно быть простым:

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

check_ipo_supported() привело меня вПолитика CMP0069 не установлена ​​»ошибка на CMake 3.9.1.

С его помощью CMake до 3.8 поддерживал только LTO компилятора Intel. Это не сработало для лязга 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
По вопросам рекламы [email protected]