Spec-Zone.ru › CMake 3.29

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. Выдастся сообщение об ошибке, если компилятор не поддерживает эту функцию.

Точные флаги компиляции и стандарт языка намеренно не являются частью интерфейса пользователя для этого случая. 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

Однако это может быть не поддерживаемо, если нужно абстрагировать много файлов. Необходимо использовать альтернативные каталоги включения в зависимости от возможностей компилятора.

END_OF_DOCUMENT_MARKER

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-базируемые компиляторы.
  • 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.29/manual/cmake-compile-features.7.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API