cmake-compile-features(7)
- Введение
- Необязательные функции компиляции
- Условные параметры компиляции
- Поддерживаемые компиляторы
- Флаги стандартов языка
Введение
Исходный код проекта может зависеть от наличия определённых функций компилятора или быть условным в зависимости от их наличия. Существует три случая использования: Требования к функциям компиляции, Необязательные функции компиляции и Условные параметры компиляции.
Хотя функции обычно указываются в стандартах языков программирования, CMake предоставляет основной пользовательский интерфейс, основанный на подробном управлении функциями, а не на стандарте языка, который ввёл эту функцию.
Глобальные свойства CMAKE_C_KNOWN_FEATURES, CMAKE_CUDA_KNOWN_FEATURES и CMAKE_CXX_KNOWN_FEATURES содержат все известные CMake функции, независимо от поддержки компилятора для этих функций. Переменные CMAKE_C_COMPILE_FEATURES, CMAKE_CUDA_COMPILE_FEATURES и CMAKE_CXX_COMPILE_FEATURES содержат все функции, которые CMake знает, что поддерживаются компилятором, независимо от стандарта языка или флагов компиляции, необходимых для их использования.
Известные CMake функции в основном имеют ту же конвенцию именования, что и макросы тестирования функций Clang. Существуют некоторые исключения, такие как CMake, использующие cxx_final и cxx_override вместо одного cxx_override_control используемого Clang.
Обратите внимание, что для языков OBJC и OBJCXX нет отдельных свойств или переменных функций компиляции. Они основаны на C или C++ соответственно, поэтому вместо них следует использовать свойства и переменные соответствующего основного языка.
Требования к функциям компиляции
Требования к функциям компиляции могут быть указаны с помощью команды target_compile_features(). Например, если целевой объект должен быть скомпилирован с поддержкой компилятора функции cxx_constexpr:
add_library(mylib requires_constexpr.cpp) target_compile_features(mylib PRIVATE cxx_constexpr)
При обработке требования к функции cxx_constexpr, cmake(1) убедится, что используемый C++ компилятор поддерживает эту функцию, и добавит необходимые флаги, такие как -std=gnu++11, в строки компиляции файлов C++ в целевом объекте mylib. Если компилятор не поддерживает эту функцию, выдаётся FATAL_ERROR.
Точные флаги компиляции и стандарт языка преднамеренно не являются частью пользовательского интерфейса для этого случая использования. CMake вычислит соответствующие флаги компиляции, учитывая указанные для каждой цели функции.
Эти флаги добавляются даже если компилятор поддерживает данную функцию без флага. Например, GNU компилятор поддерживает вариативные шаблоны (с предупреждением), даже если -std=gnu++98 используется. CMake добавляет флаг -std=gnu++11 если cxx_variadic_templates указан в качестве требования.
В приведённом выше примере mylib требует cxx_constexpr при собственной сборке, но потребители mylib не обязаны использовать компилятор, который поддерживает cxx_constexpr. Если интерфейс mylib требует функции cxx_constexpr (или любой другой известной функции), это можно указать с использованием сигнатур PUBLIC или INTERFACE target_compile_features():
add_library(mylib requires_constexpr.cpp) # cxx_constexpr is a usage-requirement target_compile_features(mylib PUBLIC cxx_constexpr) # main.cpp will be compiled with -std=gnu++11 on GNU for cxx_constexpr. add_executable(myexe main.cpp) target_link_libraries(myexe mylib)
Требования к функциям оцениваются транзитивно, потребляя реализацию связи. См. cmake-buildsystem(7) для получения дополнительной информации о транзитивном поведении свойств сборки и требованиях к использованию.
Требование стандартов языка
В проектах, использующих большое количество широко доступных функций из определённого стандарта языка (например, C++ 11), можно указать мета-функцию (например, cxx_std_11), которая требует использования режима компилятора, по крайней мере, знакомого с этим стандартом, но может быть и более новым. Это проще, чем указывать все функции по отдельности, но не гарантирует существования какой-либо конкретной функции. Диагностика использования неподдерживаемых функций будет отложена до времени компиляции.
Например, если функции C++ 11 широко используются в заголовочных файлах проекта, то клиенты должны использовать режим компилятора не ниже C++ 11. Это можно запросить с помощью кода:
target_compile_features(mylib PUBLIC cxx_std_11)
В этом примере CMake убедится, что компилятор вызывается в режиме не ниже C++ 11 (или C++ 14, C++ 17, ...), добавив необходимые флаги, такие как -std=gnu++11 при необходимости. Это относится к исходным файлам в mylib и всем зависимостям (которые могут включать заголовочные файлы из mylib).
Примечание
Если уровень стандартного режима компилятора по умолчанию не ниже запрашиваемой функции, CMake может опустить флаг -std= . Флаг может быть добавлен, если режим расширений компилятора по умолчанию не соответствует свойству целевого объекта <LANG>_EXTENSIONS, или если свойство целевого объекта <LANG>_STANDARD установлено.
Доступность расширений компилятора
Свойство целевого объекта <LANG>_EXTENSIONS по умолчанию принимает значение по умолчанию компилятора (см. CMAKE_<LANG>_EXTENSIONS_DEFAULT). Обратите внимание, что, поскольку большинство компиляторов по умолчанию включают расширения, это может привести к появлению проблем с переносимостью в пользовательском коде или в заголовках зависимых сторонних библиотек.
<LANG>_EXTENSIONS по умолчанию устанавливалось в значение ON. См. CMP0128.
Необязательные функции компиляции
Функции компиляции могут быть предпочтительными, если они доступны, без создания жёсткого требования. Этого можно добиться, не указывая функции с помощью target_compile_features(), а вместо этого проверяя возможности компилятора с помощью условий препроцессора в коде проекта.
В этом случае проект может установить определённый стандарт языка, если он доступен из компилятора, и использовать условия препроцессора для обнаружения фактически доступных функций. Стандарт языка может быть установлен с помощью Требования к стандартам языка с использованием target_compile_features() с мета-функциями, такими как cxx_std_11, или путём установки свойства целевого объекта CXX_STANDARD или переменной CMAKE_CXX_STANDARD.
См. также политику CMP0120 и документацию по старым версиям о Примеры использования устаревшего модуля WriteCompilerDetectionHeader.
Условные параметры компиляции
Библиотеки могут предоставлять совершенно разные заголовочные файлы в зависимости от запрошенных функций компилятора.
Например, заголовок в with_variadics/interface.h может содержать:
template<int I, int... Is>
struct Interface;
template<int I>
struct Interface<I>
{
static int accumulate()
{
return I;
}
};
template<int I, int... Is>
struct Interface
{
static int accumulate()
{
return I + Interface<Is...>::accumulate();
}
};
в то время как заголовок в no_variadics/interface.h может содержать:
template<int I1, int I2 = 0, int I3 = 0, int I4 = 0>
struct Interface
{
static int accumulate() { return I1 + I2 + I3 + I4; }
};
Возможно создание абстрактного заголовка interface.h содержащего что-то вроде:
#ifdef HAVE_CXX_VARIADIC_TEMPLATES #include "with_variadics/interface.h" #else #include "no_variadics/interface.h" #endif
Однако это может быть неустойчиво, если для абстрагирования требуется много файлов. Необходимо использовать альтернативные каталоги включения в зависимости от возможностей компилятора.
CMake предоставляет COMPILE_FEATURES generator expression для реализации таких условий. Это может быть использовано с командами свойств сборки, такими как target_include_directories() и target_link_libraries(), для установки соответствующих buildsystem свойств:
add_library(foo INTERFACE)
set(with_variadics ${CMAKE_CURRENT_SOURCE_DIR}/with_variadics)
set(no_variadics ${CMAKE_CURRENT_SOURCE_DIR}/no_variadics)
target_include_directories(foo
INTERFACE
"$<$<COMPILE_FEATURES:cxx_variadic_templates>:${with_variadics}>"
"$<$<NOT:$<COMPILE_FEATURES:cxx_variadic_templates>>:${no_variadics}>"
)
Потребляемый код затем просто подключается к целевому объекту foo как обычно и использует каталог включения, соответствующий функции.
add_executable(consumer_with consumer_with.cpp) target_link_libraries(consumer_with foo) set_property(TARGET consumer_with CXX_STANDARD 11) add_executable(consumer_no consumer_no.cpp) target_link_libraries(consumer_no foo)
Поддерживаемые компиляторы
В настоящее время CMake знает о C++ standards и compile features, доступных от следующих compiler ids по состоянию на указанные версии:
-
AppleClang: Apple Clang для Xcode версий 4.4+. -
Clang: Clang компилятор версий 2.9+. -
GNU: GNU компилятор версий 4.4+. -
MSVC: Microsoft Visual Studio версии 2010+. -
SunPro: Oracle SolarisStudio версии 12.4+. -
Intel: Intel компилятор версий 12.1+.
В настоящее время CMake знает о C standards и compile features, доступных от следующих compiler ids по состоянию на указанные версии:
- все компиляторы и версии, перечисленные выше, для C++.
-
GNU: GNU компилятор версий 3.4+
CMake в настоящее время знает о C++ standards и их связанных мета-функциях (например, cxx_std_11) доступных от следующих compiler ids по состоянию на указанные версии:
-
Cray: Cray Compiler Environment версия 8.1+. -
Fujitsu: Fujitsu HPC компилятор 4.0+. -
PGI: PGI версия 12.10+. -
NVHPC: NVIDIA HPC компиляторы версия 11.0+. -
TI: Texas Instruments компилятор. -
TIClang: Texas Instruments Clang-based компиляторы. -
XL: IBM XL версия 10.1+.
CMake в настоящее время знает о C standards и их связанных мета-функциях (например, c_std_99) доступных от следующих compiler ids по состоянию на указанные версии:
- все компиляторы и версии, перечисленные выше, только с мета-функциями для C++.
CMake в настоящее время знает о CUDA standards и их связанных мета-функциях (например, cuda_std_11) доступных от следующих compiler ids по состоянию на указанные версии:
-
Clang: Clang компилятор 5.0+. -
NVIDIA: NVIDIA nvcc компилятор 7.5+.
Флаги стандарта языка
Для удовлетворения требований, указанных командой target_compile_features() или переменной CMAKE_<LANG>_STANDARD, CMake может передать флаг стандарта языка компилятору, например -std=c++11.
Для Генераторов Visual Studio, CMake не может точно управлять размещением флага стандарта языка в командной строке компилятора. Для Генераторов Ninja, Генераторов Makefile и Xcode, CMake помещает флаг стандарта языка сразу после флагов языка из CMAKE_<LANG>_FLAGS и CMAKE_<LANG>_FLAGS_<CONFIG>.
Изменено в версии 3.26: Флаг стандарта языка помещается перед флагами, заданными другими абстракциями, такими как команда target_compile_options(). До CMake 3.26 флаг стандарта языка размещался после них.
© 2000–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.30/manual/cmake-compile-features.7.html