Spec-Zone.ru › CMake 3.31

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.
  • 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.31/manual/cmake-compile-features.7.html

Spec-Zone.ru

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