LTO с LLVM и CMake
Я пытаюсь применить Оптимизацию времени связи с 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 дополнительные шаги?
Ответы
Ответ 1
Правильный способ использования Clang и включения LTO использует флаг -flto
в командной строке clang
как во время компиляции, так и времени ссылки.
Кроме того, вам нужно будет работать на платформе с компоновщиком, который либо напрямую поддерживает LTO (обычно платформы Apple), либо имеет плагин LLVM-компоновщика (Linux с использованием компоновщика Gold, но я думаю, что некоторые из них получили BFD компоновщик для поддержки плагина компоновщика). Если вы используете плагин-компоновщик, вам нужно убедиться, что ваша установка LLVM построена и установлена плагином. Если это произойдет, Clang автоматически добавит необходимые параметры командной строки компоновщика, чтобы использовать плагин при связывании с -flto
, даже для общих объектов.
Кроме того, проект LLVM работает над новым компоновщиком (LLD), который будет поддерживать LTO из коробки на всех поддерживаемых платформах, но это все еще довольно рано. В настоящее время я знаю, что люди тестируют свою поддержку LTO в Windows и Linux, и, похоже, она работает хорошо, но по-прежнему не хватает многих функций.
Ответ 2
check_ipo_supported()
приведен для меня в "" Политика CMP0069 не установлена" на CMake 3.9.1.
За свою помощь CMake до 3,8 поддерживает только Intel компилятор 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 ()
Ответ 3
Включение (тонкое) 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
.