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