Spec-Zone.ru › CMake 3.31

cmake-buildsystem(7)

  • Введение
  • Бинарные цели

    • Бинарные исполняемые файлы
    • Типы бинарных библиотек

      • Обычные библиотеки

        • Фреймворки Apple
      • Библиотеки объектов
  • Требования к спецификации сборки и использованию

    • Команды целей
    • Спецификация сборки целей

      • Свойства компиляции целей
      • Свойства компоновки целей
    • Требования к использованию целей

      • Переходные свойства компиляции
      • Переходные свойства компоновки
    • Пользовательские переходные свойства
    • Свойства совместимого интерфейса
    • Отладка происхождения свойств
    • Спецификация сборки с выражениями генератора

      • Директории включения и требования к использованию
    • Связывание библиотек и выражения генератора
    • Выходные артефакты

      • Выходные артефакты во время выполнения
      • Выходные артефакты библиотек
      • Выходные артефакты архивов
    • Команды, применимые к директориям
  • Конфигурации сборки

    • Чувствительность к регистру
    • Основные и пользовательские конфигурации
  • Псевдоцели

    • Импортированные цели
    • Цели-псевдонимы
    • Библиотеки интерфейса

Введение

Система сборки на основе CMake организована как набор логических целей высокого уровня. Каждая цель соответствует исполняемому файлу или библиотеке, или является пользовательской целью, содержащей пользовательские команды. Зависимости между целями выражены в системе сборки, чтобы определить порядок сборки и правила перегенерации в ответ на изменения.

Бинарные цели

Исполняемые файлы и библиотеки определяются с помощью команд add_executable() и add_library(). Результирующие двоичные файлы имеют соответствующие PREFIX, SUFFIX и расширения для целевой платформы. Зависимости между бинарными целями выражаются с помощью команды target_link_libraries():

add_library(archive archive.cpp zip.cpp lzma.cpp)
add_executable(zipapp zipapp.cpp)
target_link_libraries(zipapp archive)

archive определена как STATIC библиотека — архив, содержащий объекты, скомпилированные из archive.cpp, zip.cpp, и lzma.cpp. zipapp определена как исполняемый файл, сформированный путём компиляции и компоновки zipapp.cpp. При компоновке исполняемого файла zipapp, в него подключается статическая библиотека archive.

Бинарные исполняемые файлы

Команда add_executable() определяет исполняемую цель:

add_executable(mytool mytool.cpp)

Команды, такие как add_custom_command(), которые генерируют правила, которые выполняются во время сборки, могут прозрачно использовать цель EXECUTABLE как исполняемый файл COMMAND. Правила системы сборки будут гарантировать, что исполняемый файл будет скомпилирован перед попыткой выполнить команду.

Типы бинарных библиотек

Обычные библиотеки

По умолчанию команда add_library() определяет STATIC библиотеку, если не указан тип. Тип может быть указан при использовании команды:

add_library(archive SHARED archive.cpp zip.cpp lzma.cpp)
add_library(archive STATIC archive.cpp zip.cpp lzma.cpp)

Переменная BUILD_SHARED_LIBS может быть включена, чтобы изменить поведение команды add_library() на построение общих библиотек по умолчанию.

В контексте определения системы сборки в целом, различие между SHARED и STATIC библиотеками в значительной степени не имеет значения — команды, спецификации зависимостей и другие API работают аналогично независимо от типа библиотеки. Тип библиотеки MODULE отличается тем, что, как правило, не подключается — он не используется в правой части команды target_link_libraries(). Это тип, который загружается как плагин с помощью методов выполнения. Если библиотека не экспортирует какие-либо неуправляемые символы (например, DLL ресурсов Windows, C++/CLI DLL), то необходимо, чтобы библиотека не была SHARED библиотекой, так как CMake ожидает, что SHARED библиотеки экспортируют по крайней мере один символ.

add_library(archive MODULE 7z.cpp)
Фреймворки Apple

Библиотека SHARED может быть помечена свойством цели FRAMEWORK для создания пакета macOS или iOS Framework Bundle. Библиотека со свойством цели FRAMEWORK также должна установить свойство цели FRAMEWORK_VERSION. Это свойство обычно устанавливается в значение "A" согласно соглашениям macOS. MACOSX_FRAMEWORK_IDENTIFIER устанавливает ключ CFBundleIdentifier и однозначно идентифицирует пакет.

add_library(MyFramework SHARED MyFramework.cpp)
set_target_properties(MyFramework PROPERTIES
  FRAMEWORK TRUE
  FRAMEWORK_VERSION A # Version "A" is macOS convention
  MACOSX_FRAMEWORK_IDENTIFIER org.cmake.MyFramework
)

Библиотеки объектов

Тип библиотеки OBJECT определяет неархивный набор файлов объектов, полученных в результате компиляции указанных исходных файлов. Набор файлов объектов может использоваться в качестве исходных входных данных для других целей с помощью синтаксиса $<TARGET_OBJECTS:name>. Это выражение генератора generator expression, которое может быть использовано для передачи содержимого библиотеки OBJECT другим целям:

add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)

add_library(archiveExtras STATIC $<TARGET_OBJECTS:archive> extras.cpp)

add_executable(test_exe $<TARGET_OBJECTS:archive> test.cpp)

Этап компоновки (или архивирования) этих других целей будет использовать набор файлов объектов в дополнение к файлам из собственных источников.

В качестве альтернативы библиотеки объектов могут быть подключены к другим целям:

add_library(archive OBJECT archive.cpp zip.cpp lzma.cpp)

add_library(archiveExtras STATIC extras.cpp)
target_link_libraries(archiveExtras PUBLIC archive)

add_executable(test_exe test.cpp)
target_link_libraries(test_exe archive)

Этап компоновки (или архивирования) этих других целей будет использовать файлы объектов из OBJECT библиотек, которые непосредственно подключены. Кроме того, требования к использованию OBJECT библиотек будут соблюдены при компиляции исходных кодов в этих других целях. Кроме того, эти требования к использованию будут распространяться транзитивно на зависимые от этих других целей.

Библиотеки объектов не могут использоваться как TARGET в использовании команды add_custom_command(TARGET). Однако список объектов может использоваться командой add_custom_command(OUTPUT) или file(GENERATE) с помощью $<TARGET_OBJECTS:objlib>.

Требования к спецификации сборки и использованию

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

Например:

add_library(archive SHARED archive.cpp zip.cpp)

if (LZMA_FOUND)
  # Add a source implementing support for lzma.
  target_sources(archive PRIVATE lzma.cpp)

  # Compile the 'archive' library sources with '-DBUILDING_WITH_LZMA'.
  target_compile_definitions(archive PRIVATE BUILDING_WITH_LZMA)
endif()

target_compile_definitions(archive INTERFACE USING_ARCHIVE_LIB)

add_executable(consumer consumer.cpp)

# Link 'consumer' to 'archive'.  This also consumes its usage requirements,
# so 'consumer.cpp' is compiled with '-DUSING_ARCHIVE_LIB'.
target_link_libraries(consumer archive)

Команды целей

Команды, специфичные для целевого объекта, заполняют спецификацию сборки бинарных целей и требования к использованию бинарных целей, библиотек интерфейса и импортированных целей.

Вызовы должны указывать ключевые слова области видимости, каждое из которых влияет на видимость аргументов, следующих за ним. Области видимости:

PUBLIC

Заполняет обе характеристики для собирания и характеристики для использования цели.

PRIVATE

Заполняет только характеристики для собирания цели.

INTERFACE

Заполняет только характеристики для использования цели.

Команды:

target_compile_definitions()

Заполняет COMPILE_DEFINITIONS спецификации сборки и INTERFACE_COMPILE_DEFINITIONS характеристики требования к использованию.

Например, вызов

target_compile_definitions(archive
  PRIVATE   BUILDING_WITH_LZMA
  INTERFACE USING_ARCHIVE_LIB
)

добавляет BUILDING_WITH_LZMA к свойству цели COMPILE_DEFINITIONS и добавляет USING_ARCHIVE_LIB к свойству цели %%%CODE_BLOCK_64%%.

target_compile_options()

Заполняет COMPILE_OPTIONS спецификации сборки и INTERFACE_COMPILE_OPTIONS характеристики требования к использованию.

target_compile_features()

Добавлено в версии 3.1.

Заполняет COMPILE_FEATURES спецификации сборки и INTERFACE_COMPILE_FEATURES характеристики требования к использованию.

target_include_directories()

Заполняет INCLUDE_DIRECTORIES спецификации сборки и INTERFACE_INCLUDE_DIRECTORIES характеристики требования к использованию. С помощью опции %%%CODE_BLOCK_74%%, она также заполняет INTERFACE_SYSTEM_INCLUDE_DIRECTORIES требования к использованию.

Для удобства переменная CMAKE_INCLUDE_CURRENT_DIR может быть включена для добавления исходного каталога и соответствующего каталога сборки как INCLUDE_DIRECTORIES ко всем целям. Аналогично, переменная CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE может быть включена для добавления их как INTERFACE_INCLUDE_DIRECTORIES ко всем целям.

target_sources()

Добавлено в версии 3.1.

Заполняет SOURCES спецификации сборки и INTERFACE_SOURCES характеристики требования к использованию.

Также поддерживает указание Наборов файлов, которые могут добавить исходные файлы и заголовки модулей C++ не указанные в свойствах SOURCES и %%%CODE_BLOCK_84%%. Наборы файлов также могут заполнить INCLUDE_DIRECTORIES спецификации сборки и INTERFACE_INCLUDE_DIRECTORIES характеристики требования к использованию каталогами заголовков.

target_precompile_headers()

Добавлено в версии 3.16.

Заполняет PRECOMPILE_HEADERS спецификации сборки и INTERFACE_PRECOMPILE_HEADERS характеристики требования к использованию.

target_link_libraries()

Заполняет LINK_LIBRARIES спецификации сборки и INTERFACE_LINK_LIBRARIES характеристики требования к использованию.

Это основной механизм, с помощью которого зависимости линковки и их требования к использованию транзитивно распространяются, чтобы повлиять на компиляцию и линковку целевого объекта.

target_link_directories()

Добавлено в версии 3.13.

Заполняет LINK_DIRECTORIES спецификации сборки и INTERFACE_LINK_DIRECTORIES характеристики требования к использованию.

target_link_options()

Добавлено в версии 3.13.

Заполняет LINK_OPTIONS спецификации сборки и INTERFACE_LINK_OPTIONS характеристики требования к использованию.

Спецификация сборки цели

Спецификация сборки бинарных целей представлена свойствами целевого объекта. Для каждого из следующих свойств компиляции и линковки, компиляция и линковка цели влияют как на собственное значение, так и на соответствующие требования к использованию свойства, с префиксом %%%CODE_BLOCK_99%%, собранные из транзитивного замыкания зависимостей линковки.

Свойства компиляции цели

Эти свойства представляют спецификацию сборки для компиляции цели.

COMPILE_DEFINITIONS

Список определений компиляции для компиляции исходных файлов в целевом объекте. Они передаются компилятору с -D флагами или эквивалентами в неопределённом порядке.

Свойство цели DEFINE_SYMBOL также используется как определение компиляции в качестве специального удобного случая для SHARED и MODULE библиотек.

COMPILE_OPTIONS

Список опций компиляции для компиляции исходных файлов в целевом объекте. Они передаются компилятору как флаги в порядке появления.

Опции компиляции автоматически экранируются для оболочки.

Некоторые опции компиляции лучше всего задавать через специализированные настройки, такие как свойство цели POSITION_INDEPENDENT_CODE.

COMPILE_FEATURES

Добавлен в версии 3.1.

Список compile features, необходимых для компиляции исходных файлов в целевом объекте. Обычно они гарантируют, что исходные файлы целевого объекта скомпилированы с достаточным уровнем стандарта языка.

INCLUDE_DIRECTORIES

Список каталогов включения для компиляции исходных файлов в целевом объекте. Они передаются компилятору с -I или -isystem флагами или эквивалентами в порядке появления.

Для удобства, переменная CMAKE_INCLUDE_CURRENT_DIR может быть включена для добавления каталога исходных файлов и соответствующего каталога сборки как INCLUDE_DIRECTORIES ко всем целевым объектам.

SOURCES

Список исходных файлов, связанных с целевым объектом. Это включает исходные файлы, заданные при создании целевого объекта командой add_executable(), add_library() или add_custom_target(). Также это включает исходные файлы, добавленные командой target_sources(), но не включает Наборы файлов.

PRECOMPILE_HEADERS

Добавлен в версии 3.16.

Список файлов заголовков для предварительной компиляции и включения при компиляции исходных файлов в целевом объекте.

AUTOMOC_MACRO_NAMES

Добавлен в версии 3.10.

Список имён макросов, используемых AUTOMOC для определения, нужно ли обрабатывать исходный файл C++ в целевом объекте с помощью moc.

AUTOUIC_OPTIONS

Добавлен в версии 3.0.

Список опций, используемых AUTOUIC при вызове uic для целевого объекта.

Свойства целевого объекта для линковки

Они представляют собой спецификацию сборки для линковки целевого объекта.

LINK_LIBRARIES

Список библиотек линковки для линковки целевого объекта, если это исполняемый файл, динамическая библиотека или модульная библиотека. Элементы для обычных библиотек передаются компоновщику либо путём указания путей к их линковки артефактам, либо с помощью -l флагов или эквивалентов. Элементы для библиотек объектных файлов передаются компоновщику по путям к их объектным файлам.

Кроме того, для компиляции и линковки самого целевого объекта, требования использования распространяются из LINK_LIBRARIES элементов, которые называют обычные библиотеки, интерфейсные библиотеки, библиотеки объектных файлов и импортированные целевые объекты, собранные над транзитивным замыканием их свойств INTERFACE_LINK_LIBRARIES.

LINK_DIRECTORIES

Добавлен в версии 3.13.

Список каталогов линковки для линковки целевого объекта, если это исполняемый файл, динамическая библиотека или модульная библиотека. Каталоги передаются компоновщику с -L флагами или эквивалентами.

LINK_OPTIONS

Добавлен в версии 3.13.

Список опций линковки для линковки целевого объекта, если это исполняемый файл, динамическая библиотека или модульная библиотека. Опции передаются компоновщику в качестве флагов в порядке появления.

Опции линковки автоматически экранируются для оболочки.

LINK_DEPENDS

Список файлов, от которых зависит линковка целевого объекта, если это исполняемый файл, динамическая библиотека или модульная библиотека. Например, скрипты компоновщика, указанные через LINK_OPTIONS, могут быть перечислены здесь, чтобы изменение их приводило к повторной линковке бинарных файлов.

Требования к использованию целевого объекта

Требования к использованию целевого объекта — это настройки, которые распространяются на потребителей, которые ссылаются на целевой объект через target_link_libraries(), для корректной компиляции и линковки с ним. Они представлены транзитивными свойствами компиляции и свойствами линковки.

Обратите внимание, что требования к использованию не предназначены для того, чтобы сделать последующие зависимости использовать определённые COMPILE_OPTIONS, COMPILE_DEFINITIONS и т. д. для удобства, только. Содержимое свойств должно быть требованием, а не просто рекомендацией.

См. раздел Создание переносимых пакетов руководства cmake-packages(7) для обсуждения дополнительных мер, которые необходимо принять при указании требований к использованию при создании пакетов для распространения.

Требования к использованию целевого объекта могут транзитивно распространяться на зависимые объекты. Команда target_link_libraries() имеет PRIVATE, INTERFACE и PUBLIC ключевые слова для управления распространением.

add_library(archive archive.cpp)
target_compile_definitions(archive INTERFACE USING_ARCHIVE_LIB)

add_library(serialization serialization.cpp)
target_compile_definitions(serialization INTERFACE USING_SERIALIZATION_LIB)

add_library(archiveExtras extras.cpp)
target_link_libraries(archiveExtras PUBLIC archive)
target_link_libraries(archiveExtras PRIVATE serialization)
# archiveExtras is compiled with -DUSING_ARCHIVE_LIB
# and -DUSING_SERIALIZATION_LIB

add_executable(consumer consumer.cpp)
# consumer is compiled with -DUSING_ARCHIVE_LIB
target_link_libraries(consumer archiveExtras)

Поскольку archive является PUBLIC зависимостью archiveExtras, требования к его использованию также распространяются на consumer.

Поскольку serialization является PRIVATE зависимостью archiveExtras, требования к его использованию не распространяются на consumer.

END_OF_DOCUMENT_MARKER

Как правило, зависимость должна быть указана в использовании target_link_libraries() с ключевым словом PRIVATE, если она используется только реализацией библиотеки, а не в заголовочных файлах. Если зависимость дополнительно используется в заголовочных файлах библиотеки (например, для наследования классов), то она должна быть указана как PUBLIC зависимость. Зависимость, которая не используется реализацией библиотеки, а только её заголовочными файлами, должна быть указана как INTERFACE зависимость. Команда target_link_libraries() может быть вызвана с несколькими использованиями каждого ключевого слова:

target_link_libraries(archiveExtras
  PUBLIC archive
  PRIVATE serialization
)

Требования к использованию распространяются путём чтения INTERFACE_ вариантов свойств целевых объектов из зависимостей и добавления значений к не-INTERFACE_ вариантам операнда. Например, INTERFACE_INCLUDE_DIRECTORIES зависимостей считывается и добавляется к INCLUDE_DIRECTORIES операнда. В случаях, когда порядок важен и сохраняется, а порядок, полученный от вызовов target_link_libraries(), не позволяет правильно скомпилировать, использование соответствующей команды для непосредственного задания свойства может обновить порядок.

Например, если связанные библиотеки для целевого объекта должны быть указаны в порядке lib1 lib2 lib3, но каталоги включаемых файлов должны быть указаны в порядке lib3 lib1 lib2:

target_link_libraries(myExe lib1 lib2 lib3)
target_include_directories(myExe
  PRIVATE $<TARGET_PROPERTY:lib3,INTERFACE_INCLUDE_DIRECTORIES>)

Обратите внимание, что необходимо быть внимательным при указании требований к использованию для целевых объектов, которые будут экспортированы для установки с помощью команды install(EXPORT). См. Создание пакетов для более подробной информации.

Переходные свойства компиляции

Эти свойства представляют требования к использованию для компиляции потребителей.

INTERFACE_COMPILE_DEFINITIONS

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

INTERFACE_COMPILE_OPTIONS

Список параметров компиляции для компиляции исходных файлов в потребителях целевого объекта.

INTERFACE_COMPILE_FEATURES

Добавлен в версии 3.1.

Список compile features, необходимых для компиляции исходных файлов в потребителях целевого объекта. Обычно они гарантируют, что заголовочные файлы целевого объекта обрабатываются при компиляции потребителей с достаточным уровнем языка.

INTERFACE_INCLUDE_DIRECTORIES

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

INTERFACE_SYSTEM_INCLUDE_DIRECTORIES

Список каталогов, которые, когда указаны как каталоги включения, например, с помощью INCLUDE_DIRECTORIES или INTERFACE_INCLUDE_DIRECTORIES, должны обрабатываться как "системные" каталоги включения при компиляции исходных файлов в потребителях целевого объекта.

INTERFACE_SOURCES

Список исходных файлов, которые нужно ассоциировать с потребителями целевого объекта.

INTERFACE_PRECOMPILE_HEADERS

Добавлен в версии 3.16.

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

INTERFACE_AUTOMOC_MACRO_NAMES

Добавлен в версии 3.27.

Список имён макросов, используемых AUTOMOC для определения, нужно ли обрабатывать исходный файл C++ в потребителях целевого объекта с помощью moc.

INTERFACE_AUTOUIC_OPTIONS

Добавлен в версии 3.0.

Список параметров, используемых AUTOUIC при вызове uic для потребителей целевого объекта.

Переходные свойства компоновки

Эти свойства представляют требования к использованию для компоновки потребителей.

INTERFACE_LINK_LIBRARIES

Список библиотек компоновки для компоновки потребителей целевого объекта, для тех, которые являются исполняемыми файлами, динамическими библиотеками или модульными библиотеками. Это переходные зависимости целевого объекта.

Кроме того, для компиляции и компоновки потребителей целевого объекта, требования к использованию собираются из транзитивного замыкания INTERFACE_LINK_LIBRARIES записей, именования обычных библиотек, интерфейсных библиотек, библиотек объектов и импортированных целевых объектов.

INTERFACE_LINK_DIRECTORIES

Добавлен в версии 3.13.

Список каталогов компоновки для компоновки потребителей целевого объекта, для тех, которые являются исполняемыми файлами, динамическими библиотеками или модульными библиотеками.

INTERFACE_LINK_OPTIONS

Добавлен в версии 3.13.

Список параметров компоновки для компоновки потребителей целевого объекта, для тех, которые являются исполняемыми файлами, динамическими библиотеками или модульными библиотеками.

INTERFACE_LINK_DEPENDS

Добавлен в версии 3.13.

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

Пользовательские переходные свойства

Добавлен в версии 3.30.

Генераторское выражение TARGET_PROPERTY оценивает вышеперечисленные свойства спецификации сборки и требований к использованию как встроенные переходные свойства. Оно также поддерживает пользовательские переходные свойства, определенные свойствами TRANSITIVE_COMPILE_PROPERTIES и TRANSITIVE_LINK_PROPERTIES на целевом объекте и его зависимостях компоновки.

Например:

add_library(example INTERFACE)
set_target_properties(example PROPERTIES
  TRANSITIVE_COMPILE_PROPERTIES "CUSTOM_C"
  TRANSITIVE_LINK_PROPERTIES    "CUSTOM_L"

  INTERFACE_CUSTOM_C "EXAMPLE_CUSTOM_C"
  INTERFACE_CUSTOM_L "EXAMPLE_CUSTOM_L"
  )

add_library(mylib STATIC mylib.c)
target_link_libraries(mylib PRIVATE example)
set_target_properties(mylib PROPERTIES
  CUSTOM_C           "MYLIB_PRIVATE_CUSTOM_C"
  CUSTOM_L           "MYLIB_PRIVATE_CUSTOM_L"
  INTERFACE_CUSTOM_C "MYLIB_IFACE_CUSTOM_C"
  INTERFACE_CUSTOM_L "MYLIB_IFACE_CUSTOM_L"
  )

add_executable(myexe myexe.c)
target_link_libraries(myexe PRIVATE mylib)
set_target_properties(myexe PROPERTIES
  CUSTOM_C "MYEXE_CUSTOM_C"
  CUSTOM_L "MYEXE_CUSTOM_L"
  )

add_custom_target(print ALL VERBATIM
  COMMAND ${CMAKE_COMMAND} -E echo
    # Prints "MYLIB_PRIVATE_CUSTOM_C;EXAMPLE_CUSTOM_C"
    "$<TARGET_PROPERTY:mylib,CUSTOM_C>"

    # Prints "MYLIB_PRIVATE_CUSTOM_L;EXAMPLE_CUSTOM_L"
    "$<TARGET_PROPERTY:mylib,CUSTOM_L>"

    # Prints "MYEXE_CUSTOM_C"
    "$<TARGET_PROPERTY:myexe,CUSTOM_C>"

    # Prints "MYEXE_CUSTOM_L;MYLIB_IFACE_CUSTOM_L;EXAMPLE_CUSTOM_L"
    "$<TARGET_PROPERTY:myexe,CUSTOM_L>"
  )

Совместимые свойства интерфейса

Некоторые целевые свойства должны быть совместимы между целевым объектом и интерфейсом каждой зависимости. Например, свойство целевого объекта POSITION_INDEPENDENT_CODE может указывать булево значение, определяющее, следует ли компилировать целевой объект как позиционно-независимый код, что имеет специфичные для платформы последствия. Целевой объект также может указывать требование использования INTERFACE_POSITION_INDEPENDENT_CODE для указания того, что потребители должны быть скомпилированы как позиционно-независимый код.

add_executable(exe1 exe1.cpp)
set_property(TARGET exe1 PROPERTY POSITION_INDEPENDENT_CODE ON)

add_library(lib1 SHARED lib1.cpp)
set_property(TARGET lib1 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)

add_executable(exe2 exe2.cpp)
target_link_libraries(exe2 lib1)

Здесь оба exe1 и exe2 будут скомпилированы как позиционно-независимый код. lib1 также будет скомпилирован как позиционно-независимый код, так как это значение по умолчанию для SHARED библиотек. Если зависимости имеют конфликтующие, несовместимые требования cmake(1) выводит диагностическое сообщение:

add_library(lib1 SHARED lib1.cpp)
set_property(TARGET lib1 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)

add_library(lib2 SHARED lib2.cpp)
set_property(TARGET lib2 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE OFF)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1)
set_property(TARGET exe1 PROPERTY POSITION_INDEPENDENT_CODE OFF)

add_executable(exe2 exe2.cpp)
target_link_libraries(exe2 lib1 lib2)

Требование lib1 INTERFACE_POSITION_INDEPENDENT_CODE не «совместимо» со свойством POSITION_INDEPENDENT_CODE целевого объекта exe1. Библиотека требует, чтобы потребители были построены как позиционно-независимый код, в то время как исполняемый файл задаёт не компилировать его как позиционно-независимый код, поэтому выдаётся диагностическое сообщение.

Требования lib1 и lib2 не «совместимы». Одно из них требует, чтобы потребители были построены как позиционно-независимый код, а другое — нет. Поскольку exe2 ссылается на оба, и они находятся в конфликте, выдаётся сообщение об ошибке CMake:

CMake Error: The INTERFACE_POSITION_INDEPENDENT_CODE property of "lib2" does
not agree with the value of POSITION_INDEPENDENT_CODE already determined
for "exe2".

Для «совместимости» свойство POSITION_INDEPENDENT_CODE, если оно установлено, должно быть таким же, в булевом смысле, как и свойство INTERFACE_POSITION_INDEPENDENT_CODE всех транзитивно указанных зависимостей, для которых это свойство установлено.

Это свойство «совместимого требования интерфейса» может быть расширено на другие свойства путём указания свойства в содержимом целевого свойства COMPATIBLE_INTERFACE_BOOL. Каждое указанное свойство должно быть совместимо между целевым объектом-потребителем и соответствующим свойством с префиксом INTERFACE_ из каждой зависимости:

add_library(lib1Version2 SHARED lib1_v2.cpp)
set_property(TARGET lib1Version2 PROPERTY INTERFACE_CUSTOM_PROP ON)
set_property(TARGET lib1Version2 APPEND PROPERTY
  COMPATIBLE_INTERFACE_BOOL CUSTOM_PROP
)

add_library(lib1Version3 SHARED lib1_v3.cpp)
set_property(TARGET lib1Version3 PROPERTY INTERFACE_CUSTOM_PROP OFF)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1Version2) # CUSTOM_PROP will be ON

add_executable(exe2 exe2.cpp)
target_link_libraries(exe2 lib1Version2 lib1Version3) # Diagnostic

Небулевы свойства также могут участвовать в вычислениях «совместимого интерфейса». Свойства, указанные в свойстве COMPATIBLE_INTERFACE_STRING, должны быть либо не указаны, либо иметь одинаковое строковое значение среди всех транзитивно указанных зависимостей. Это может быть полезно для обеспечения того, чтобы несколько несовместимых версий библиотеки не были связаны вместе через транзитивные требования целевого объекта:

add_library(lib1Version2 SHARED lib1_v2.cpp)
set_property(TARGET lib1Version2 PROPERTY INTERFACE_LIB_VERSION 2)
set_property(TARGET lib1Version2 APPEND PROPERTY
  COMPATIBLE_INTERFACE_STRING LIB_VERSION
)

add_library(lib1Version3 SHARED lib1_v3.cpp)
set_property(TARGET lib1Version3 PROPERTY INTERFACE_LIB_VERSION 3)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1Version2) # LIB_VERSION will be "2"

add_executable(exe2 exe2.cpp)
target_link_libraries(exe2 lib1Version2 lib1Version3) # Diagnostic

Свойство целевого объекта COMPATIBLE_INTERFACE_NUMBER_MAX определяет, что содержимое будет оцениваться численно, и будет вычислено максимальное значение среди всех указанных:

add_library(lib1Version2 SHARED lib1_v2.cpp)
set_property(TARGET lib1Version2 PROPERTY INTERFACE_CONTAINER_SIZE_REQUIRED 200)
set_property(TARGET lib1Version2 APPEND PROPERTY
  COMPATIBLE_INTERFACE_NUMBER_MAX CONTAINER_SIZE_REQUIRED
)

add_library(lib1Version3 SHARED lib1_v3.cpp)
set_property(TARGET lib1Version3 PROPERTY INTERFACE_CONTAINER_SIZE_REQUIRED 1000)

add_executable(exe1 exe1.cpp)
# CONTAINER_SIZE_REQUIRED will be "200"
target_link_libraries(exe1 lib1Version2)

add_executable(exe2 exe2.cpp)
# CONTAINER_SIZE_REQUIRED will be "1000"
target_link_libraries(exe2 lib1Version2 lib1Version3)

Аналогичным образом, свойство COMPATIBLE_INTERFACE_NUMBER_MIN может быть использовано для вычисления минимального числового значения свойства из зависимостей.

Вычисленное значение каждого «совместимого» свойства может быть прочитано потребителем во время генерации с помощью выражений генератора.

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

Отладка происхождения свойства

Поскольку спецификации сборки могут определяться зависимостями, отсутствие локальности кода, который создаёт целевой объект, и кода, ответственного за установку спецификаций сборки, может затруднить понимание кода. cmake(1) предоставляет средство отладки для вывода происхождения содержимого свойств, которые могут определяться зависимостями. Свойства, которые могут быть отлажены, перечислены в документации переменной CMAKE_DEBUG_TARGET_PROPERTIES:

set(CMAKE_DEBUG_TARGET_PROPERTIES
  INCLUDE_DIRECTORIES
  COMPILE_DEFINITIONS
  POSITION_INDEPENDENT_CODE
  CONTAINER_SIZE_REQUIRED
  LIB_VERSION
)
add_executable(exe1 exe1.cpp)

В случае свойств, перечисленных в COMPATIBLE_INTERFACE_BOOL или COMPATIBLE_INTERFACE_STRING, вывод отладки показывает, какой целевой объект отвечал за установку свойства и какие другие зависимости также определили это свойство. В случае COMPATIBLE_INTERFACE_NUMBER_MAX и COMPATIBLE_INTERFACE_NUMBER_MIN вывод отладки показывает значение свойства из каждой зависимости и определяет, определяет ли значение новое экстремальное значение.

Спецификация сборки с выражениями генератора

Спецификации сборки могут использовать generator expressions содержащие условия или значения, известные только во время генерации. Например, вычисленное «совместимое» значение свойства может быть прочитано с помощью выражения TARGET_PROPERTY:

add_library(lib1Version2 SHARED lib1_v2.cpp)
set_property(TARGET lib1Version2 PROPERTY
  INTERFACE_CONTAINER_SIZE_REQUIRED 200)
set_property(TARGET lib1Version2 APPEND PROPERTY
  COMPATIBLE_INTERFACE_NUMBER_MAX CONTAINER_SIZE_REQUIRED
)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1Version2)
target_compile_definitions(exe1 PRIVATE
    CONTAINER_SIZE=$<TARGET_PROPERTY:CONTAINER_SIZE_REQUIRED>
)

В этом случае файлы exe1 будут скомпилированы с -DCONTAINER_SIZE=200.

Унарное TARGET_PROPERTY выражение генератора и TARGET_POLICY выражение генератора оцениваются в контексте целевого объекта-потребителя. Это означает, что спецификация требования использования может быть оценена по-разному в зависимости от потребителя:

add_library(lib1 lib1.cpp)
target_compile_definitions(lib1 INTERFACE
  $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,EXECUTABLE>:LIB1_WITH_EXE>
  $<$<STREQUAL:$<TARGET_PROPERTY:TYPE>,SHARED_LIBRARY>:LIB1_WITH_SHARED_LIB>
  $<$<TARGET_POLICY:CMP0041>:CONSUMER_CMP0041_NEW>
)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1)

cmake_policy(SET CMP0041 NEW)

add_library(shared_lib shared_lib.cpp)
target_link_libraries(shared_lib lib1)

Исполняемый файл exe1 будет скомпилирован с -DLIB1_WITH_EXE, а общая библиотека shared_lib — с -DLIB1_WITH_SHARED_LIB и -DCONSUMER_CMP0041_NEW, так как политика CMP0041 имеет значение NEW в момент создания целевого объекта shared_lib.

Выражение BUILD_INTERFACE оборачивает требования, которые используются только при использовании их целевым объектом в той же системе сборки или при использовании их целевым объектом, экспортированным в каталог сборки с помощью команды export(). Выражение INSTALL_INTERFACE оборачивает требования, которые используются только при использовании их целевым объектом, который был установлен и экспортирован с помощью команды install(EXPORT):

add_library(ClimbingStats climbingstats.cpp)
target_compile_definitions(ClimbingStats INTERFACE
  $<BUILD_INTERFACE:ClimbingStats_FROM_BUILD_LOCATION>
  $<INSTALL_INTERFACE:ClimbingStats_FROM_INSTALLED_LOCATION>
)
install(TARGETS ClimbingStats EXPORT libExport ${InstallArgs})
install(EXPORT libExport NAMESPACE Upstream::
        DESTINATION lib/cmake/ClimbingStats)
export(EXPORT libExport NAMESPACE Upstream::)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 ClimbingStats)

В этом случае исполняемый файл exe1 будет скомпилирован с -DClimbingStats_FROM_BUILD_LOCATION. Команды экспорта генерируют целевые объекты IMPORTED с INSTALL_INTERFACE или BUILD_INTERFACE или без них и удаляют метку *_INTERFACE . Отдельный проект, использующий пакет ClimbingStats, будет содержать:

find_package(ClimbingStats REQUIRED)

add_executable(Downstream main.cpp)
target_link_libraries(Downstream Upstream::ClimbingStats)

В зависимости от того, был ли пакет ClimbingStats использован из каталога сборки или каталога установки, целевой объект Downstream будет скомпилирован либо с -DClimbingStats_FROM_BUILD_LOCATION, либо с -DClimbingStats_FROM_INSTALL_LOCATION. Дополнительную информацию о пакетах и экспорте см. в руководстве cmake-packages(7).

Директории включения и требования использования

Директории включения требуют особого внимания при указании их как требований использования и при использовании с выражениями генератора. Команда target_include_directories() принимает как относительные, так и абсолютные директории включения:

add_library(lib1 lib1.cpp)
target_include_directories(lib1 PRIVATE
  /absolute/path
  relative/path
)

Относительные пути интерпретируются относительно каталога исходных файлов, где появляется команда. Относительные пути не допускаются в свойстве INTERFACE_INCLUDE_DIRECTORIES целевых объектов IMPORTED.

В случаях, когда используется нетривиальное выражение генератора, выражение INSTALL_PREFIX может использоваться в аргументе выражения INSTALL_INTERFACE. Это маркер замены, который расширяется до префикса установки при импорте в проект-потребитель.

Требования к использованию каталогов включения часто отличаются между деревом сборки (build-tree) и деревом установки (install-tree). Выражения генератора BUILD_INTERFACE и INSTALL_INTERFACE можно использовать для описания отдельных требований к использованию в зависимости от расположения места использования. В выражении INSTALL_INTERFACE разрешены относительные пути, которые интерпретируются относительно префикса установки. Например:

add_library(ClimbingStats climbingstats.cpp)
target_include_directories(ClimbingStats INTERFACE
  $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/generated>
  $<INSTALL_INTERFACE:/absolute/path>
  $<INSTALL_INTERFACE:relative/path>
  $<INSTALL_INTERFACE:$<INSTALL_PREFIX>/$<CONFIG>/generated>
)

Предоставляются два удобных API, относящиеся к требованиям использования каталогов включения. Переменная CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE может быть включена, с эквивалентным эффектом:

set_property(TARGET tgt APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES
  $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR};${CMAKE_CURRENT_BINARY_DIR}>
)

для каждого затронутого целевого объекта. Удобство для установленных целевых объектов — это компонент INCLUDES DESTINATION с командой install(TARGETS):

install(TARGETS foo bar bat EXPORT tgts ${dest_args}
  INCLUDES DESTINATION include
)
install(EXPORT tgts ${other_args})
install(FILES ${headers} DESTINATION include)

Это эквивалентно добавлению ${CMAKE_INSTALL_PREFIX}/include к INTERFACE_INCLUDE_DIRECTORIES каждого из установленных IMPORTED целевых объектов при генерации с помощью install(EXPORT).

Когда INTERFACE_INCLUDE_DIRECTORIES импортированного целевого объекта используется, записи в свойстве могут обрабатываться как системные каталоги включения. Эффекты от этого зависят от инструментальной цепочки, но одним из общих эффектов является опущение предупреждений компилятора для заголовков, найденных в этих каталогах. Свойство SYSTEM установленного целевого объекта определяет это поведение (см. свойство EXPORT_NO_SYSTEM для изменения установленного значения для целевого объекта). Также можно изменить способ интерпретации потребителями системного поведения потребляемых импортированных целевых объектов, установив свойство целевого объекта NO_SYSTEM_FROM_IMPORTED на потребителе.

Если целевой объект бинарного типа транзитивно связан с macOS FRAMEWORK, каталог Headers фреймворка также обрабатывается как требование к использованию. Это эквивалентно передаче каталога фреймворка в качестве каталога включения.

Связывание библиотек и выражения генератора

Как и спецификации сборки, link libraries могут быть указаны с условиями выражений генератора. Однако, поскольку потребление требований к использованию основано на сборе от зависимых библиотек, существует дополнительное ограничение, что зависимости по ссылкам должны образовывать «направленный ациклический граф». То есть, если связь с целевым объектом зависит от значения свойства целевого объекта, то это свойство целевого объекта не может зависеть от зависимостей по ссылкам:

add_library(lib1 lib1.cpp)
add_library(lib2 lib2.cpp)
target_link_libraries(lib1 PUBLIC
  $<$<TARGET_PROPERTY:POSITION_INDEPENDENT_CODE>:lib2>
)
add_library(lib3 lib3.cpp)
set_property(TARGET lib3 PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 lib1 lib3)

Поскольку значение свойства POSITION_INDEPENDENT_CODE целевого объекта exe1 зависит от связанных библиотек (lib3), и ребро связывания exe1 определяется тем же свойством POSITION_INDEPENDENT_CODE, вышеприведенный граф зависимостей содержит цикл. cmake(1) выводит сообщение об ошибке.

Выходные артефакты

Целевые объекты системы сборки, созданные командами add_library() и add_executable(), создают правила для создания двоичных выходных данных. Точное расположение выходных данных бинарных файлов можно определить только на стадии генерации, так как оно может зависеть от конфигурации сборки и языка связывания зависимых библиотек и т. д. Выражения TARGET_FILE, TARGET_LINKER_FILE и аналогичные могут использоваться для доступа к имени и расположению сгенерированных бинарных файлов. Однако эти выражения не работают для библиотек OBJECT, так как такие библиотеки не генерируют один единственный файл, который был бы релевантен для этих выражений.

Существует три вида выходных артефактов, которые могут быть созданы целевыми объектами, как описано в следующих разделах. Их классификация отличается для платформ DLL и не-DLL. Все системы на базе Windows, включая Cygwin, являются платформами DLL.

Выходные артефакты времени выполнения

Выходным артефактом времени выполнения целевого объекта системы сборки может быть:

  • Исполняемый файл (например, .exe) целевого объекта исполняемого типа, созданного командой add_executable().
  • На платформах DLL: исполняемый файл (например, .dll) целевого объекта разделяемой библиотеки, созданного командой add_library() с опцией SHARED.

Свойства целевых объектов RUNTIME_OUTPUT_DIRECTORY и RUNTIME_OUTPUT_NAME могут использоваться для управления расположением и именами артефактов выходных данных времени выполнения в дереве сборки.

Выходные артефакты библиотек

Выходным артефактом библиотеки целевого объекта системы сборки может быть:

  • Файл модуля загрузки (например, .dll или .so) целевого объекта модульной библиотеки, созданного командой add_library() с опцией MODULE.
  • На платформах не-DLL: файл разделяемой библиотеки (например, .so или .dylib) целевого объекта разделяемой библиотеки, созданного командой add_library() с опцией SHARED.

Свойства целевых объектов LIBRARY_OUTPUT_DIRECTORY и LIBRARY_OUTPUT_NAME могут использоваться для управления расположением и именами выходных артефактов библиотек в дереве сборки.

Выходные артефакты архивов

Выходным артефактом архива целевого объекта системы сборки может быть:

  • Файл статической библиотеки (например, .lib или .a) целевого объекта статической библиотеки, созданного командой add_library() с опцией STATIC.
  • На платформах DLL: файл импортной библиотеки (например, .lib) целевого объекта разделяемой библиотеки, созданного командой add_library() с опцией SHARED. Этот файл гарантированно существует только в том случае, если библиотека экспортирует как минимум один необработанный символ.
  • На платформах DLL: файл импортной библиотеки (например, .lib) целевого объекта исполняемого типа, созданного командой add_executable(), когда свойство целевого объекта ENABLE_EXPORTS установлено.
  • На AIX: файл импорта компоновщика (например, .imp) целевого объекта исполняемого типа, созданного командой add_executable(), когда свойство целевого объекта ENABLE_EXPORTS установлено.
  • На macOS: файл импорта компоновщика (например, .tbd) целевого объекта разделяемой библиотеки, созданного командой add_library() с опцией SHARED и когда свойство целевого объекта ENABLE_EXPORTS установлено.

Свойства целевых объектов ARCHIVE_OUTPUT_DIRECTORY и ARCHIVE_OUTPUT_NAME могут использоваться для управления расположением и именами выходных артефактов архивов в дереве сборки.

Команды, ограниченные каталогом

Команды target_include_directories(), target_compile_definitions() и target_compile_options() оказывают влияние только на один целевой объект за раз. Команды add_compile_definitions(), add_compile_options() и include_directories() имеют аналогичную функцию, но для удобства действуют на уровне каталога, а не на уровне целевого объекта.

Конфигурации сборки

Конфигурации определяют параметры для определённого типа сборки, например Release или Debug. Способ указания этого зависит от типа используемого generator. Для генераторов с одной конфигурацией, таких как Генераторы Makefile и Ninja, конфигурация задаётся во время настройки переменной CMAKE_BUILD_TYPE. Для генераторов с несколькими конфигурациями, таких как Visual Studio, Xcode и Ninja Multi-Config, конфигурация выбирается пользователем во время сборки, и CMAKE_BUILD_TYPE игнорируется. В случае с несколькими конфигурациями набор доступных конфигураций задаётся во время настройки переменной CMAKE_CONFIGURATION_TYPES, но фактическая используемая конфигурация неизвестна до стадии сборки. Это различие часто неправильно понимается, что приводит к проблемному коду, подобному следующему:

# WARNING: This is wrong for multi-config generators because they don't use
#          and typically don't even set CMAKE_BUILD_TYPE
string(TOLOWER ${CMAKE_BUILD_TYPE} build_type)
if (build_type STREQUAL debug)
  target_compile_definitions(exe1 PRIVATE DEBUG_BUILD)
endif()

Вместо этого следует использовать Generator expressions, чтобы правильно обрабатывать логику, специфичную для конфигурации, независимо от используемого генератора. Например:

# Works correctly for both single and multi-config generators
target_compile_definitions(exe1 PRIVATE
  $<$<CONFIG:Debug>:DEBUG_BUILD>
)

При наличии целевых объектов IMPORTED, содержимое MAP_IMPORTED_CONFIG_DEBUG также учитывается вышеупомянутым выражением $<CONFIG:Debug>.

Регистрозависимость

CMAKE_BUILD_TYPE и CMAKE_CONFIGURATION_TYPES такие же, как и другие переменные, и поэтому любые строковые сравнения, использующие их значения, будут регистрозависимыми. Выражение генератора $<CONFIG> также сохраняет регистр конфигурации, установленный пользователем или по умолчанию CMake. Например:

# NOTE: Don't use these patterns, they are for illustration purposes only.

set(CMAKE_BUILD_TYPE Debug)
if(CMAKE_BUILD_TYPE STREQUAL DEBUG)
  # ... will never get here, "Debug" != "DEBUG"
endif()
add_custom_target(print_config ALL
  # Prints "Config is Debug" in this single-config case
  COMMAND ${CMAKE_COMMAND} -E echo "Config is $<CONFIG>"
  VERBATIM
)

set(CMAKE_CONFIGURATION_TYPES Debug Release)
if(DEBUG IN_LIST CMAKE_CONFIGURATION_TYPES)
  # ... will never get here, "Debug" != "DEBUG"
endif()

В противоположность этому, CMake обрабатывает тип конфигурации регистронезависимо, когда использует его внутри, в местах, которые изменяют поведение на основе конфигурации. Например, выражение генератора $<CONFIG:Debug> вернёт 1 не только для конфигурации Debug, но и для DEBUG, debug или даже DeBuG. Поэтому вы можете указывать типы конфигураций в CMAKE_BUILD_TYPE и CMAKE_CONFIGURATION_TYPES с любым сочетанием прописных и строчных букв, хотя есть чёткие соглашения (см. следующий раздел). Если необходимо проверить значение в строковых сравнениях, всегда сначала преобразуйте значение в верхний или нижний регистр и скорректируйте тест соответственно.

Конфигурации по умолчанию и пользовательские конфигурации

По умолчанию CMake определяет ряд стандартных конфигураций:

  • Debug
  • Release
  • RelWithDebInfo
  • MinSizeRel

В генераторах с несколькими конфигурациями переменная CMAKE_CONFIGURATION_TYPES будет, по умолчанию, заполняться (возможно, подмножеством) вышеперечисленного списка, если это не переопределено проектом или пользователем. Фактическая используемая конфигурация выбирается пользователем во время сборки.

Для генераторов с одной конфигурацией конфигурация задаётся переменной CMAKE_BUILD_TYPE во время настройки и не может быть изменена во время сборки. Значение по умолчанию часто не соответствует ни одной из стандартных конфигураций выше и будет пустой строкой. Распространённое заблуждение состоит в том, что это то же самое, что Debug, но это не так. Пользователи всегда должны явно указывать тип сборки, чтобы избежать этой распространённой проблемы.

Вышеперечисленные стандартные типы конфигураций обеспечивают разумное поведение на большинстве платформ, но их можно расширить, чтобы получить другие типы. Каждая конфигурация определяет набор переменных флагов компилятора и линковщика для используемого языка. Эти переменные следуют соглашению CMAKE_<LANG>_FLAGS_<CONFIG>, где <CONFIG> всегда является именем конфигурации в верхнем регистре. При определении пользовательского типа конфигурации убедитесь, что эти переменные установлены должным образом, обычно как переменные кэша.

Псевдоцелевые объекты

Некоторые типы целевых объектов не представляют собой выходные данные системы сборки, а только входные данные, такие как внешние зависимости, псевдонимы или другие объекты, не относящиеся к сборке. Псевдоцелевые объекты не представлены в сгенерированной системе сборки.

Импортированные целевые объекты

Целевой объект IMPORTED представляет собой существующую зависимость. Обычно такие целевые объекты определяются пакетной системой верхнего уровня и должны рассматриваться как неизменяемые. После объявления целевого объекта IMPORTED можно изменить его свойства, используя обычные команды, такие как target_compile_definitions(), target_include_directories(), target_compile_options() или target_link_libraries(), как и с любым другим обычным целевым объектом.

Целевые объекты IMPORTED могут иметь те же требования к использованию, что и бинарные целевые объекты, такие как INTERFACE_INCLUDE_DIRECTORIES, INTERFACE_COMPILE_DEFINITIONS, INTERFACE_COMPILE_OPTIONS, INTERFACE_LINK_LIBRARIES и INTERFACE_POSITION_INDEPENDENT_CODE.

Цель LOCATION также может быть получена из импортируемой цели, хотя для этого редко есть основания. Команды, такие как add_custom_command(), могут прозрачно использовать IMPORTED EXECUTABLE целевой объект как COMMAND исполняемый файл.

Область определения импортируемой IMPORTED цели — это директория, в которой она была определена. К ней можно получить доступ и использовать её из поддиректорий, но не из родительских или братских директорий. Область действия подобна области действия переменной cmake.

Также можно определить GLOBAL IMPORTED целевой объект, который доступен глобально в системе сборки.

См. руководство cmake-packages(7) для получения дополнительных сведений о создании пакетов с IMPORTED целевыми объектами.

Целевые псевдонимы

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

add_library(lib1 lib1.cpp)
install(TARGETS lib1 EXPORT lib1Export ${dest_args})
install(EXPORT lib1Export NAMESPACE Upstream:: ${other_args})

add_library(Upstream::lib1 ALIAS lib1)

В другой директории можно безусловно связать целевой объект Upstream::lib1, который может быть IMPORTED целевым объектом из пакета или целевым объектом ALIAS при сборке в рамках той же системы сборки.

if (NOT TARGET Upstream::lib1)
  find_package(lib1 REQUIRED)
endif()
add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 Upstream::lib1)

Целевые псевдонимы ALIAS не изменяемы, не устанавливаются и не экспортируются. Они полностью локальны для описания системы сборки. Можно проверить, является ли имя псевдонимом ALIAS, прочитав свойство ALIASED_TARGET из него:

get_target_property(_aliased Upstream::lib1 ALIASED_TARGET)
if(_aliased)
  message(STATUS "The name Upstream::lib1 is an ALIAS for ${_aliased}.")
endif()

Интерфейсные библиотеки

Целевой объект интерфейсной библиотеки не компилирует исходные файлы и не создаёт артефакт библиотеки на диске, поэтому у него нет LOCATION.

Он может указывать требования к использованию, такие как INTERFACE_INCLUDE_DIRECTORIES, INTERFACE_COMPILE_DEFINITIONS, INTERFACE_COMPILE_OPTIONS, INTERFACE_LINK_LIBRARIES, INTERFACE_SOURCES и INTERFACE_POSITION_INDEPENDENT_CODE. Только режимы INTERFACE команд target_include_directories(), target_compile_definitions(), target_compile_options(), target_sources() и target_link_libraries() могут использоваться с интерфейсными библиотеками INTERFACE.

Начиная с CMake 3.19, целевой объект интерфейсной библиотеки может необязательно содержать исходные файлы. Интерфейсная библиотека, содержащая исходные файлы, будет включена как целевой объект сборки в сгенерированной системе сборки. Она не компилирует исходные файлы, но может содержать пользовательские команды для генерации других исходных файлов. Кроме того, среды разработки покажут исходные файлы как часть целевого объекта для интерактивного чтения и редактирования.

Основное применение интерфейсных библиотек — это библиотеки только с заголовками. Начиная с CMake 3.23, файлы заголовков могут быть связаны с библиотекой, добавив их в набор заголовков с помощью команды target_sources():

add_library(Eigen INTERFACE)

target_sources(Eigen PUBLIC
  FILE_SET HEADERS
    BASE_DIRS src
    FILES src/eigen.h src/vector.h src/matrix.h
)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 Eigen)

Когда мы указываем FILE_SET здесь, BASE_DIRS которые мы определяем, автоматически становятся каталогами включения в требованиях к использованию для целевого объекта Eigen. Требования к использованию из целевого объекта используются при компиляции, но не влияют на компоновку.

Другое применение — использовать полностью ориентированную на целевой объект конструкцию для требований к использованию:

add_library(pic_on INTERFACE)
set_property(TARGET pic_on PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE ON)
add_library(pic_off INTERFACE)
set_property(TARGET pic_off PROPERTY INTERFACE_POSITION_INDEPENDENT_CODE OFF)

add_library(enable_rtti INTERFACE)
target_compile_options(enable_rtti INTERFACE
  $<$<OR:$<COMPILER_ID:GNU>,$<COMPILER_ID:Clang>>:-rtti>
)

add_executable(exe1 exe1.cpp)
target_link_libraries(exe1 pic_on enable_rtti)

Таким образом, спецификация сборки exe1 выражается полностью как связанные целевые объекты, а сложность флагов, специфичных для компилятора, инкапсулируется в целевом объекте интерфейсной библиотеки INTERFACE.

Интерфейсные библиотеки INTERFACE могут быть установлены и экспортированы. Мы можем установить набор заголовков по умолчанию вместе с целевым объектом:

add_library(Eigen INTERFACE)

target_sources(Eigen INTERFACE
  FILE_SET HEADERS
    BASE_DIRS src
    FILES src/eigen.h src/vector.h src/matrix.h
)

install(TARGETS Eigen EXPORT eigenExport
  FILE_SET HEADERS DESTINATION include/Eigen)
install(EXPORT eigenExport NAMESPACE Upstream::
  DESTINATION lib/cmake/Eigen
)

Здесь заголовки, определённые в наборе заголовков, устанавливаются в include/Eigen. Назначение установки автоматически становится каталогом включения, который является требованием к использованию для потребителей.

© 2000–2024 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.31/manual/cmake-buildsystem.7.html

Spec-Zone.ru

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