Spec-Zone.ru › CMake

find_package

  • Типичное использование
  • Режимы поиска
  • Базовая сигнатура
  • Полная сигнатура
  • Процедура поиска в режиме Config
  • Выбор версии в режиме Config

    • Скрипт CMake
    • Спецификация Common Package
  • Переменные интерфейса файла пакета
  • Транзитивные зависимости CPS

Примечание

Using Dependencies Guide содержит краткое введение в эту общую тему. В нём представлен более широкий обзор того, как команда find_package() вписывается в общую картину, включая её связь с модулем FetchContent. Рекомендуется ознакомиться с этим руководством, прежде чем переходить к приведённым ниже подробностям.

Найти пакет (обычно предоставляемый чем-либо за пределами проекта) и загрузить сведения, относящиеся к этому пакету. Вызовы этой команды также могут перехватываться поставщиками зависимостей.

Типичное использование

Большинство вызовов find_package() обычно имеют следующий вид:

find_package(<PackageName> [<version>] [REQUIRED] [COMPONENTS <components>...])

<PackageName> — единственный обязательный аргумент. <version> часто опускается, а REQUIRED следует указывать, если проект невозможно успешно настроить без пакета. Некоторые более сложные пакеты поддерживают компоненты, которые можно выбрать с помощью ключевого слова COMPONENTS, однако большинство пакетов не обладают таким уровнем сложности.

Описанная выше сокращённая форма основана на базовой сигнатуре. По возможности проектам следует искать пакеты именно с помощью этой формы. Это снижает сложность и максимально расширяет способы, которыми пакет может быть найден или предоставлен.

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

Режимы поиска

Команда может искать пакеты в нескольких режимах:

Режим Module

В этом режиме CMake ищет файл с именем Find<PackageName>.cmake, сначала в расположениях, перечисленных в CMAKE_MODULE_PATH, а затем среди модулей Find, предоставляемых установкой CMake. Если файл найден, CMake считывает и обрабатывает его. Этот файл отвечает за поиск пакета, проверку версии и вывод необходимых сообщений. Некоторые модули Find лишь ограниченно поддерживают версии или не поддерживают их вовсе; см. документацию соответствующего модуля Find.

Файл Find<PackageName>.cmake обычно не предоставляется самим пакетом. Как правило, его предоставляет нечто внешнее по отношению к пакету, например операционная система, сам CMake или даже проект, из которого была вызвана команда find_package(). Поскольку модули Find предоставляются извне, они, как правило, основаны на эвристиках и со временем могут устаревать. Обычно они ищут определённые библиотеки, файлы и другие артефакты пакета.

Режим Module поддерживается только базовой сигнатурой команды.

Режим Config

В этом режиме CMake ищет файл, соответствующий одному из следующих шаблонов:

  • <PackageName>.cps
  • <lowercasePackageName>.cps
  • <lowercasePackageName>-config.cmake
  • <PackageName>Config.cmake

Если найден один из двух последних файлов, CMake также ищет соответственно <lowercasePackageName>-config-version.cmake или <PackageName>ConfigVersion.cmake, если указаны сведения о версии (объяснение использования этих отдельных файлов версий см. в разделе Выбор версии в режиме Config). Два последних варианта представляют собой описания пакетов в виде скриптов CMake. Первые два — описания пакетов в формате Common Package Specification (CPS), которые более переносимы и содержат сведения о версии в «базовом» файле. За исключением явно оговорённых случаев, все упоминания «файлов конфигурации», «режима Config», «файлов конфигурации пакета» и т. п. в равной степени относятся как к файлам CPS, так и к файлам скриптов CMake.

Примечание

Поиск устроен так, что в большинстве случаев файлы Common Package Specification имеют приоритет над файлами конфигурации в виде скриптов CMake. Указание CONFIGS исключает файлы CPS из рассмотрения.

В режиме Config команде можно передать список имён пакетов для поиска. Расположения, в которых CMake ищет файлы конфигурации и версии, значительно сложнее, чем в режиме Module (см. раздел Процедура поиска в режиме Config).

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

Режим Config поддерживается как базовой, так и полной сигнатурой команды.

Режим перенаправления FetchContent

Добавлено в версии 3.24: Вызов find_package() может быть перенаправлен внутри системы к пакету, предоставляемому модулем FetchContent. Для вызывающего кода такое поведение будет выглядеть аналогично режиму Config, за исключением того, что логика поиска пропускается, а сведения о компонентах не используются. Подробнее см. FetchContent_Declare() и FetchContent_MakeAvailable().

Если команда не перенаправлена к пакету, предоставляемому FetchContent, её аргументы определяют, будет ли использоваться режим Module или Config. При использовании базовой сигнатуры команда сначала выполняет поиск в режиме Module. Если пакет не найден, поиск продолжается в режиме Config. Пользователь может присвоить переменной CMAKE_FIND_PACKAGE_PREFER_CONFIG значение true, чтобы изменить приоритет и указать CMake сначала искать в режиме Config, а затем, если потребуется, перейти к режиму Module. Базовую сигнатуру также можно принудительно ограничить режимом Module с помощью ключевого слова MODULE. При использовании полной сигнатуры команда выполняет поиск только в режиме Config.

Базовая сигнатура

find_package(<PackageName> [<version>] [EXACT] [QUIET] [MODULE]
             [REQUIRED|OPTIONAL] [[COMPONENTS] <component>...]
             [OPTIONAL_COMPONENTS <component>...]
             [REGISTRY_VIEW {64|32|64_32|32_64|HOST|TARGET|BOTH}]
             [GLOBAL]
             [NO_POLICY_SCOPE]
             [BYPASS_PROVIDER]
             [UNWIND_INCLUDE])

Базовая сигнатура поддерживается режимами Module и Config. Ключевое слово MODULE означает, что для поиска пакета можно использовать только режим Module, без перехода к режиму Config.

Независимо от используемого режима устанавливается переменная <PackageName>_FOUND, указывающая, найден ли пакет. Если пакет найден, относящиеся к нему сведения могут предоставляться через другие переменные и импортируемые цели, описанные самим пакетом. Параметр QUIET отключает информационные сообщения, в том числе сообщение о том, что пакет не найден, если он не является REQUIRED. Параметр REQUIRED прерывает обработку с сообщением об ошибке, если пакет не найден.

После ключевого слова COMPONENTS можно перечислить список обязательных для конкретного пакета компонентов. Если удовлетворить требования хотя бы одного из этих компонентов невозможно, пакет в целом считается ненайденным. Если также указан параметр REQUIRED, это считается фатальной ошибкой; в противном случае выполнение продолжается. Для краткости, если указан параметр REQUIRED, ключевое слово COMPONENTS можно опустить и перечислить обязательные компоненты непосредственно после REQUIRED.

Переменную CMAKE_FIND_REQUIRED можно включить, чтобы по умолчанию сделать этот вызов REQUIRED. Это поведение можно переопределить, указав ключевое слово OPTIONAL. Как и в случае с параметром REQUIRED, список компонентов можно указать непосредственно после OPTIONAL; это равнозначно перечислению компонентов после ключевого слова COMPONENTS. Если указано ключевое слово OPTIONAL, предупреждение о ненайденном пакете не выводится.

После OPTIONAL_COMPONENTS можно перечислить дополнительные необязательные компоненты. Если удовлетворить требования этих компонентов невозможно, пакет всё равно может считаться найденным при условии, что удовлетворены требования всех обязательных компонентов.

Набор доступных компонентов и их назначение определяются целевым пакетом:

  • Для файлов конфигурации пакетов в виде скриптов CMake целевой пакет формально сам определяет, как интерпретировать переданные сведения о компонентах, однако ему следует придерживаться изложенных выше ожиданий. Для вызовов без указания компонентов единого ожидаемого поведения нет, поэтому целевым пакетам следует чётко описывать, что происходит в таких случаях. Среди распространённых вариантов — предполагать, что нужно найти все компоненты, ни одного компонента или некоторое чётко определённое подмножество доступных компонентов.
  • Пакеты Common Package Specification состоят из корневого файла конфигурации и нуля или более дополнений, каждое из которых предоставляет компоненты и может иметь зависимости. CMake всегда пытается загрузить корневой файл конфигурации. Дополнения загружаются, только если их зависимости можно удовлетворить и если они предоставляют запрошенные компоненты либо компоненты не запрашивались. Если зависимости дополнения, предоставляющего обязательный компонент, удовлетворить невозможно, пакет считается ненайденным. В противном случае это дополнение игнорируется.

Добавлено в версии 3.24: Ключевое слово REGISTRY_VIEW указывает, какие представления реестра следует запрашивать. Это ключевое слово имеет смысл только на платформах Windows и игнорируется на всех остальных. Формально целевой пакет сам определяет, как интерпретировать переданные ему сведения о представлении реестра.

Добавлено в версии 3.24: Указание ключевого слова GLOBAL переводит все импортируемые цели в глобальную область видимости импортирующего проекта. Эту возможность также можно включить, задав переменную CMAKE_FIND_PACKAGE_TARGETS_GLOBAL.

Аргумент <version> запрашивает версию, с которой должен быть совместим найденный пакет. Его можно указать в одной из двух форм:

  • Одна версия в формате major[.minor[.patch[.tweak]]], где каждый компонент является числовым значением.
  • Диапазон версий в формате versionMin...[<]versionMax, где versionMin и versionMax имеют тот же формат и те же ограничения на целочисленные значения компонентов, что и отдельная версия. По умолчанию обе граничные версии включаются в диапазон. Если указать <, верхняя граница не включается. Диапазоны версий поддерживаются только в CMake 3.19 и новее.

Примечание

За исключением пакетов CPS, поддержка версий в настоящее время реализуется отдельно для каждого пакета. Если указан диапазон версий, а пакет рассчитан только на одну версию, он проигнорирует верхнюю границу диапазона и будет учитывать только нижнюю версию. Пакеты, не использующие CPS и поддерживающие диапазоны версий, реализуют эту поддержку способом, определяемым конкретным пакетом. Подробности и важные оговорки см. в разделе Выбор версии ниже.

Параметр EXACT требует точного совпадения версии. Этот параметр несовместим с указанием диапазона версий.

Если во вложенном вызове из модуля find не указаны <version> и/или список компонентов, соответствующие аргументы автоматически передаются из внешнего вызова (включая флаг EXACT для <version>).

Обсуждение параметра NO_POLICY_SCOPE см. в документации команды cmake_policy().

Добавлено в версии 3.24: Ключевое слово BYPASS_PROVIDER разрешено использовать только при вызове find_package() поставщиком зависимостей. Поставщики могут использовать его для прямого вызова встроенной реализации find_package() и предотвращения повторной маршрутизации этого вызова к самому поставщику. В будущих версиях CMake попытки использовать это ключевое слово не из поставщика зависимостей могут обнаруживаться и завершаться фатальной ошибкой.

Добавлено в версии 4.2: Ключевое слово UNWIND_INCLUDE разрешено использовать только при вызове find_package() внутри родительского вызова find_package(). Если вызову find_package(UNWIND_INCLUDE) не удаётся найти требуемый пакет, начинается состояние «размотки». В этом состоянии дальнейшие вызовы find_package() и include() запрещены, а все родительские команды include() немедленно вызывают return() при достижении их области видимости. Эта «размотка» продолжается, пока не будет выполнен возврат к родительскому find_package().

UNWIND_INCLUDE предназначено только для вызовов find_package(), создаваемых командой install(EXPORT_PACKAGE_DEPENDENCIES), но может быть полезно тем, кто хочет вручную управлять зависимостями аналогичным образом.

Полная сигнатура

find_package(<PackageName> [version] [EXACT] [QUIET]
             [REQUIRED|OPTIONAL] [[COMPONENTS] <component>...]
             [OPTIONAL_COMPONENTS <component>...]
             [CONFIG|NO_MODULE]
             [GLOBAL]
             [NO_POLICY_SCOPE]
             [BYPASS_PROVIDER]
             [NAMES <name>...]
             [CONFIGS <config>...]
             [HINTS <path>...]
             [PATHS <path>...]
             [REGISTRY_VIEW {64|32|64_32|32_64|HOST|TARGET|BOTH}]
             [PATH_SUFFIXES <suffix>...]
             [NO_DEFAULT_PATH]
             [NO_PACKAGE_ROOT_PATH]
             [NO_CMAKE_PATH]
             [NO_CMAKE_ENVIRONMENT_PATH]
             [NO_SYSTEM_ENVIRONMENT_PATH]
             [NO_CMAKE_PACKAGE_REGISTRY]
             [NO_CMAKE_BUILDS_PATH] # Deprecated; does nothing.
             [NO_CMAKE_SYSTEM_PATH]
             [NO_CMAKE_INSTALL_PREFIX]
             [NO_CMAKE_SYSTEM_PACKAGE_REGISTRY]
             [CMAKE_FIND_ROOT_PATH_BOTH |
              ONLY_CMAKE_FIND_ROOT_PATH |
              NO_CMAKE_FIND_ROOT_PATH])

Параметр CONFIG, его синоним NO_MODULE или использование параметров, не указанных в базовой сигнатуре, принудительно включают чистый режим Config. В чистом режиме Config команда пропускает поиск в режиме Module и сразу переходит к поиску в режиме Config.

В режиме Config команда пытается найти файл конфигурации, предоставленный искомым пакетом. Для хранения каталога, содержащего этот файл, создаётся запись кэша с именем <PackageName>_DIR. По умолчанию команда ищет пакет с именем <PackageName>. Если указан параметр NAMES, вместо <PackageName> используются следующие за ним имена. Эти имена также учитываются при определении возможности перенаправить вызов к пакету, предоставляемому FetchContent.

Для каждого указанного имени пакета команда ищет файл, имя которого соответствует одному из следующих шаблонов:

  • <PackageName>Config.cmake
  • <lowercasePackageName>-config.cmake
  • <PackageName>.cps
  • <lowercasePackageName>.cps

Набор альтернативных имён файлов конфигурации можно задать с помощью параметра CONFIGS. Процедура поиска в режиме Config описана ниже. После нахождения файла проверяется соответствие любым ограничениям на версию, и, если они соблюдены, CMake считывает и обрабатывает файл конфигурации. Поскольку этот файл предоставляется пакетом, в нём уже известно расположение содержимого пакета. Полный путь к файлу конфигурации сохраняется в переменной CMake <PackageName>_CONFIG.

Примечание

Поскольку файлам CPS запрещено иметь имена, которые не соответствуют имени пакета, указание CONFIGS исключает поиск файлов CPS.

Все файлы конфигурации, рассмотренные CMake при поиске пакета с подходящей версией, сохраняются в переменной <PackageName>_CONSIDERED_CONFIGS, а соответствующие версии — в переменной <PackageName>_CONSIDERED_VERSIONS.

Если файл конфигурации пакета не удаётся найти, CMake выдаст сообщение об ошибке с описанием проблемы, если не указан аргумент QUIET. Если указан REQUIRED, а пакет не найден, возникает фатальная ошибка и выполнение этапа настройки прекращается. Если для <PackageName>_DIR задан каталог, не содержащий файла конфигурации, или если запрошенная версия несовместима с пакетом, найденным в этом каталоге (см. раздел Выбор версии в режиме Config), CMake проигнорирует этот каталог и начнёт поиск заново.

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

Процедура поиска в режиме Config

Примечание

При использовании режима Config эта процедура поиска применяется независимо от того, была ли указана полная или базовая сигнатура.

Добавлено в версии 3.24: Все вызовы find_package() (даже в режиме Module) сначала ищут файл конфигурации пакета в каталоге CMAKE_FIND_PACKAGE_REDIRECTS_DIR. Модуль FetchContent или даже сам проект может записывать файлы в это расположение, чтобы перенаправлять вызовы find_package() на содержимое, уже предоставленное проектом. Если в этом расположении файл конфигурации пакета не найден, поиск продолжается по описанной ниже логике.

CMake формирует набор возможных префиксов установки пакета. В каждом префиксе выполняется поиск файла конфигурации в нескольких каталогах. В таблицах ниже приведены каталоги, в которых ведётся поиск. Каждая запись соответствует структурам установки, принятым в Windows (W), UNIX (U) или Apple (A):

Запись

Соглашение

<prefix>/<name>/cps/ [2]

W

<prefix>/<name>/*/cps/ [2]

W

<prefix>/cps/<name>/ [2]

W

<prefix>/cps/<name>/*/ [2]

W

<prefix>/cps/ [2]

W

<prefix>/

W

<prefix>/(cmake|CMake)/

W

<prefix>/<name>*/

W

<prefix>/<name>*/(cmake|CMake)/

W

<prefix>/<name>*/(cmake|CMake)/<name>*/ [1]

W

<prefix>/(lib/<arch>|lib*|share)/cps/<name>/ [2]

U

<prefix>/(lib/<arch>|lib*|share)/cps/<name>/*/ [2]

U

<prefix>/(lib/<arch>|lib*|share)/cps/ [2]

U

<prefix>/(lib/<arch>|lib*|share)/cmake/<name>*/

U

<prefix>/(lib/<arch>|lib*|share)/<name>*/

U

<prefix>/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/

U

<prefix>/<name>*/(lib/<arch>|lib*|share)/cmake/<name>*/

W/U

<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/

W/U

<prefix>/<name>*/(lib/<arch>|lib*|share)/<name>*/(cmake|CMake)/

W/U

[1]

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

[2] (1,2,3,4,5,6,7,8)

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

В системах с поддержкой macOS FRAMEWORK и BUNDLE выполняется поиск следующих каталогов, содержащих Frameworks или пакеты приложений с файлом конфигурации:

Запись

Соглашение

<prefix>/<name>.framework/Versions/*/Resources/CPS/ [3]

A

<prefix>/<name>.framework/Resources/CPS/ [3]

A

<prefix>/<name>.framework/Resources/

A

<prefix>/<name>.framework/Resources/CMake/

A

<prefix>/<name>.framework/Versions/*/Resources/

A

<prefix>/<name>.framework/Versions/*/Resources/CMake/

A

<prefix>/<name>.app/Contents/Resources/CPS/ [3]

A

<prefix>/<name>.app/Contents/Resources/

A

<prefix>/<name>.app/Contents/Resources/CMake/

A

[3] (1,2,3)

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

При поиске по указанным выше путям find_package ищет файлы .cps только в путях поиска, содержащих /cps/, а в остальных случаях ищет только файлы .cmake. (Это относится только к указанным путям и не учитывает содержимое <prefix> или <name>.)

Во всех случаях <name> не учитывает регистр и соответствует любому из указанных имён (<PackageName> или имён, заданных с помощью NAMES).

Если включён хотя бы один компилируемый язык, каталоги lib/<arch> и lib*, зависящие от архитектуры, могут проверяться с учётом целевой архитектуры компилятора в следующем порядке:

lib/<arch>

Поиск выполняется, если задана переменная CMAKE_LIBRARY_ARCHITECTURE.

lib64

Поиск выполняется на 64-разрядных платформах (CMAKE_SIZEOF_VOID_P равно 8), если свойство FIND_LIBRARY_USE_LIB64_PATHS установлено в TRUE.

lib32

Поиск выполняется на 32-разрядных платформах (CMAKE_SIZEOF_VOID_P равно 4), если свойство FIND_LIBRARY_USE_LIB32_PATHS установлено в TRUE.

libx32

Поиск выполняется на платформах, использующих ABI x32, если свойство FIND_LIBRARY_USE_LIBX32_PATHS установлено в TRUE.

lib

Поиск выполняется всегда.

Изменено в версии 3.24: На платформе Windows запросы к реестру можно включать в каталоги, указанные с помощью ключевых слов HINTS и PATHS, используя специальный синтаксис. Такие спецификации игнорируются на всех остальных платформах.

Добавлено в версии 3.24: Можно указать REGISTRY_VIEW для управления запросами к реестру Windows, заданными в составе PATHS и HINTS.

Указывает, какие представления реестра необходимо запрашивать. Этот параметр имеет смысл только на платформах Windows и игнорируется на остальных. Если параметр не задан, используется представление TARGET, когда политика CMP0134 установлена в NEW. Сведения о представлении по умолчанию, когда политика установлена в OLD, см. в описании CMP0134.

64

Запросить 64-разрядный реестр. В 32-разрядной Windows всегда возвращает строку /REGISTRY-NOTFOUND.

32

Запросить 32-разрядный реестр.

64_32

Запросить оба представления (64 и 32) и сформировать путь для каждого.

32_64

Запросить оба представления (32 и 64) и сформировать путь для каждого.

HOST

Запросить реестр, соответствующий архитектуре хоста: 64 в 64-разрядной Windows и 32 в 32-разрядной Windows.

TARGET

Запросить реестр, соответствующий архитектуре, заданной переменной CMAKE_SIZEOF_VOID_P. Если она не определена, использовать представление HOST.

BOTH

Запросить оба представления (32 и 64). Порядок определяется следующими правилами: если переменная CMAKE_SIZEOF_VOID_P определена, используйте представление, соответствующее значению этой переменной:

  • 8: 64_32
  • 4: 32_64

Если переменная CMAKE_SIZEOF_VOID_P не определена, используйте архитектуру хоста:

  • 64-разрядная: 64_32
  • 32-разрядная: 32

Если указан PATH_SUFFIXES, суффиксы добавляются поочерёдно к каждой записи каталога (W) или (U).

Этот набор каталогов предназначен для совместного использования с проектами, которые устанавливают файлы конфигурации в свои деревья установки. Каталоги, отмеченные выше как (W), предназначены для установки в Windows, где префикс может указывать на верхний уровень каталога установки приложения. Каталоги, отмеченные как (U), предназначены для установки в UNIX, где префикс является общим для нескольких пакетов. Это всего лишь соглашение, поэтому во всех платформах поиск по-прежнему выполняется во всех каталогах (W) и (U). Каталоги, отмеченные как (A), предназначены для установки на платформах Apple. Порядок предпочтения определяется переменными CMAKE_FIND_FRAMEWORK и CMAKE_FIND_APPBUNDLE.

Предупреждение

Если установить CMAKE_FIND_FRAMEWORK или CMAKE_FIND_APPBUNDLE в значение, отличное от FIRST (используемого по умолчанию), CMake будет искать файлы Common Package Specification в порядке, отличающемся от указанного в спецификации.

Набор префиксов установки формируется в несколько этапов. Если указан NO_DEFAULT_PATH, включаются все параметры NO_*.

  1. Поиск префиксов, относящихся только к текущему искомому <PackageName>. См. политику CMP0074.

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

    В частности, поиск выполняется в префиксах, заданных следующими переменными, в указанном порядке:

    1. переменная CMake <PackageName>_ROOT, где <PackageName> — имя пакета с сохранением регистра.
    2. переменная CMake <PACKAGENAME>_ROOT, где <PACKAGENAME> — имя пакета в верхнем регистре. См. политику CMP0144.

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

    3. переменная среды <PackageName>_ROOT, где <PackageName> — имя пакета с сохранением регистра.
    4. переменная среды <PACKAGENAME>_ROOT, где <PACKAGENAME> — имя пакета в верхнем регистре. См. политику CMP0144.

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

    Переменные корневых каталогов пакетов поддерживаются в виде стека, поэтому при вызове из модуля поиска после путей текущего пакета также выполняется поиск по корневым путям из родительского модуля поиска. Этот поиск можно пропустить, передав NO_PACKAGE_ROOT_PATH или установив переменную CMAKE_FIND_USE_PACKAGE_ROOT_PATH в FALSE.

  2. Поиск путей, указанных в специальных переменных кэша CMake. Предполагается, что они задаются в командной строке с помощью -DVAR=VALUE. Значения интерпретируются как списки, разделённые точками с запятой. Этот этап можно пропустить, передав NO_CMAKE_PATH или установив переменную CMAKE_FIND_USE_CMAKE_PATH в FALSE:

    • CMAKE_PREFIX_PATH
    • CMAKE_FRAMEWORK_PATH
    • CMAKE_APPBUNDLE_PATH
  3. Поиск путей, указанных в специальных переменных среды CMake. Предполагается, что они задаются в конфигурации командной оболочки пользователя, поэтому в них используется стандартный для хоста разделитель путей (; в Windows и : в UNIX). Этот этап можно пропустить, передав NO_CMAKE_ENVIRONMENT_PATH или установив переменную CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH в FALSE:

    • <PackageName>_DIR
    • CMAKE_PREFIX_PATH
    • CMAKE_FRAMEWORK_PATH
    • CMAKE_APPBUNDLE_PATH
  4. Поиск путей, указанных параметром HINTS. Это должны быть пути, вычисленные посредством анализа системы, например подсказка, полученная на основе расположения уже найденного элемента. Жёстко заданные предположительные пути следует указывать параметром PATHS.
  5. Поиск в стандартных переменных среды системы. Этот этап можно пропустить, передав NO_SYSTEM_ENVIRONMENT_PATH или установив переменную CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH в FALSE. Записи путей, оканчивающиеся на /bin или /sbin, автоматически преобразуются в родительские каталоги:

    • PATH
  6. Поиск путей, сохранённых в реестре пакетов пользователя CMake. Этот этап можно пропустить, передав NO_CMAKE_PACKAGE_REGISTRY, установив переменную CMAKE_FIND_USE_PACKAGE_REGISTRY в FALSE или установив устаревшую переменную CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY в TRUE.

    Подробные сведения о реестре пакетов пользователя см. в руководстве cmake-packages(7).

  7. Поиск переменных CMake, определённых в файлах платформы для текущей системы. Поиск в CMAKE_INSTALL_PREFIX и CMAKE_STAGING_PREFIX можно пропустить, передав NO_CMAKE_INSTALL_PREFIX или установив переменную CMAKE_FIND_USE_INSTALL_PREFIX в FALSE. Поиск во всех этих расположениях можно пропустить, передав NO_CMAKE_SYSTEM_PATH или установив переменную CMAKE_FIND_USE_CMAKE_SYSTEM_PATH в FALSE:

    • CMAKE_SYSTEM_PREFIX_PATH
    • CMAKE_SYSTEM_FRAMEWORK_PATH
    • CMAKE_SYSTEM_APPBUNDLE_PATH

    Пути платформы, содержащиеся в этих переменных, указывают на расположения, в которых обычно находится установленное программное обеспечение. Например, /usr/local для платформ на базе UNIX.

  8. Поиск путей, сохранённых в системном реестре пакетов CMake. Этот этап можно пропустить, передав NO_CMAKE_SYSTEM_PACKAGE_REGISTRY, установив переменную CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY в FALSE или установив устаревшую переменную CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY в TRUE.

    Подробные сведения о системном реестре пакетов см. в руководстве cmake-packages(7).

  9. Поиск путей, указанных параметром PATHS. Обычно это жёстко заданные предположительные пути.

Переменные CMAKE_IGNORE_PATH, CMAKE_IGNORE_PREFIX_PATH, CMAKE_SYSTEM_IGNORE_PATH и CMAKE_SYSTEM_IGNORE_PREFIX_PATH также могут привести к игнорированию некоторых из перечисленных выше расположений.

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

Для путей поиска с шаблонами подстановки (*) каталоги, соответствующие шаблону, по умолчанию проверяются в естественном порядке по убыванию. Это поведение можно изменить, задав соответствующим образом переменные CMAKE_FIND_PACKAGE_SORT_ORDER и CMAKE_FIND_PACKAGE_SORT_DIRECTION. Эти переменные определяют порядок, в котором CMake рассматривает соответствия шаблону. Например, если файловая система содержит файлы конфигурации пакета

<prefix>/example-1.2/example-config.cmake
<prefix>/example-1.10/example-config.cmake
<prefix>/share/example-2.0/example-config.cmake

то find_package(example) (если вышеупомянутые переменные не заданы) выберет example-1.10 (при условии, что и example-1.2, и example-1.10 являются подходящими). Однако обратите внимание, что find_package не найдёт example-2.0, поскольку один из двух других вариантов будет найден раньше.

Чтобы управлять порядком поиска find_package по каталогам, соответствующим шаблону подстановки, используйте CMAKE_FIND_PACKAGE_SORT_ORDER и CMAKE_FIND_PACKAGE_SORT_DIRECTION. Например, чтобы в приведённом выше примере выбрать example-1.2, можно установить

set(CMAKE_FIND_PACKAGE_SORT_ORDER NATURAL)
set(CMAKE_FIND_PACKAGE_SORT_DIRECTION ASC)

перед вызовом find_package.

Добавлено в версии 3.16: Добавлены переменные CMAKE_FIND_USE_<CATEGORY> для глобального отключения различных расположений поиска.

Изменено в версии 4.0: Переменные CMAKE_FIND_PACKAGE_SORT_ORDER и CMAKE_FIND_PACKAGE_SORT_DIRECTION теперь также управляют порядком, в котором find_package выполняет поиск в каталогах, соответствующих шаблону подстановки в путях поиска <prefix>/<name>.framework/Versions/*/Resources/ и <prefix>/<name>.framework/Versions/*/Resources/CMake. В предыдущих версиях CMake этот порядок не был определён.

Изменено в версии 4.2: Если найдено несколько подходящих совпадений, find_package теперь по умолчанию выбирает версию с самым поздним номером. В предыдущих версиях CMake результат не был определён. В связи с этим значение по умолчанию для CMAKE_FIND_PACKAGE_SORT_ORDER изменено с NONE на NATURAL, а для CMAKE_FIND_PACKAGE_SORT_DIRECTION теперь по умолчанию используется DEC (по убыванию) вместо ASC (по возрастанию).

Переменная CMake CMAKE_FIND_ROOT_PATH задаёт один или несколько каталогов, которые добавляются в начало всех остальных каталогов поиска. Фактически это «переносит корень» всего поиска в указанные расположения. Пути, являющиеся потомками CMAKE_STAGING_PREFIX, исключаются из такого переноса корня, поскольку эта переменная всегда указывает на путь в хост-системе. По умолчанию переменная CMAKE_FIND_ROOT_PATH пуста.

Переменную CMAKE_SYSROOT также можно использовать для указания ровно одного каталога в качестве префикса. Задание CMAKE_SYSROOT имеет и другие последствия. Дополнительные сведения см. в документации по этой переменной.

Эти переменные особенно полезны при кросс-компиляции: они позволяют указать корневой каталог целевой среды, где CMake также будет выполнять поиск. По умолчанию сначала выполняется поиск в каталогах, перечисленных в CMAKE_FIND_ROOT_PATH, затем в каталоге CMAKE_SYSROOT, а после этого — в каталогах без перенесённого корня. Поведение по умолчанию можно изменить, задав переменную CMAKE_FIND_ROOT_PATH_MODE_PACKAGE. Это поведение можно вручную переопределить для отдельного вызова с помощью параметров:

CMAKE_FIND_ROOT_PATH_BOTH

Выполнить поиск в описанном выше порядке.

NO_CMAKE_FIND_ROOT_PATH

Не использовать переменную CMAKE_FIND_ROOT_PATH.

ONLY_CMAKE_FIND_ROOT_PATH

Выполнять поиск только в каталогах с перенесённым корнем и каталогах внутри CMAKE_STAGING_PREFIX.

Порядок поиска по умолчанию подходит для распространённых случаев использования: от наиболее специфичного к наименее специфичному. Проекты могут переопределить порядок, просто вызвав команду несколько раз и используя параметры NO_*:

find_package (<PackageName> PATHS <paths>... NO_DEFAULT_PATH)
find_package (<PackageName>)

Как только один из вызовов завершится успешно, переменной результата будет присвоено значение, которое сохранится в кэше, поэтому дальнейшие вызовы не будут выполнять поиск.

По умолчанию переменная результата содержит путь, по которому найден файл. Перед вызовом find_package можно установить переменную CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS в TRUE, чтобы разрешить символические ссылки и сохранить настоящий путь к файлу.

Любой вызов find_package, не являющийся REQUIRED, можно отключить или сделать обязательным:

  • Установка переменной CMAKE_DISABLE_FIND_PACKAGE_<PackageName> в TRUE отключает пакет. Это также отключает перенаправление к пакету, предоставленному FetchContent.
  • Установка переменной CMAKE_REQUIRE_FIND_PACKAGE_<PackageName> в TRUE делает пакет обязательным.

Одновременная установка обеих переменных в TRUE приводит к ошибке.

Переменная CMAKE_REQUIRE_FIND_PACKAGE_<PackageName> имеет приоритет над ключевым словом OPTIONAL при определении того, является ли пакет обязательным.

Выбор версии в режиме Config

Примечание

При использовании режима Config этот процесс выбора версии применяется независимо от того, была ли указана полная или базовая сигнатура.

Если указан аргумент <version>, режим Config найдёт только ту версию пакета, которая заявляет о совместимости с запрошенной версией (см. описание формата). Если указан параметр EXACT, можно найти только версию пакета, заявляющую о точном совпадении с запрошенной версией. CMake не устанавливает соглашений о значении номеров версий.

Сценарии CMake

Для файлов конфигурации пакетов в виде сценариев CMake номера версий пакетов проверяются с помощью файлов «версии», предоставляемых самими пакетами или FetchContent. Для файла конфигурации пакета-кандидата <config-file>.cmake соответствующий файл версии находится рядом с ним и называется либо <config-file>-version.cmake, либо <config-file>Version.cmake. Если такой файл версии отсутствует, считается, что файл конфигурации несовместим с любой запрошенной версией. Базовый файл версии с универсальным кодом сопоставления версий можно создать с помощью модуля CMakePackageConfigHelpers. Найденный файл версии загружается для проверки запрошенного номера версии. Файл версии загружается во вложенную область видимости, в которой определены следующие переменные:

PACKAGE_FIND_NAME

The <PackageName>

PACKAGE_FIND_VERSION

Полная запрошенная строка версии

PACKAGE_FIND_VERSION_MAJOR

Основная версия, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_MINOR

Дополнительная версия, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_PATCH

Версия исправления, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_TWEAK

Версия доработки, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_COUNT

Количество компонентов версии, от 0 до 4

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

PACKAGE_FIND_VERSION_RANGE

Полная запрошенная строка диапазона версий

PACKAGE_FIND_VERSION_RANGE_MIN

Указывает, должна ли нижняя граница диапазона версий включаться или исключаться. В настоящее время единственное поддерживаемое значение этой переменной — INCLUDE.

PACKAGE_FIND_VERSION_RANGE_MAX

Указывает, должна ли верхняя граница диапазона версий включаться или исключаться. Поддерживаемые значения этой переменной: INCLUDE и EXCLUDE.

PACKAGE_FIND_VERSION_MIN

Полная запрошенная строка версии нижней границы диапазона

PACKAGE_FIND_VERSION_MIN_MAJOR

Основная версия нижней границы, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_MIN_MINOR

Дополнительная версия нижней границы, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_MIN_PATCH

Версия исправления нижней границы, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_MIN_TWEAK

Версия доработки нижней границы, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_MIN_COUNT

Количество компонентов версии нижней границы, от 0 до 4

PACKAGE_FIND_VERSION_MAX

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

PACKAGE_FIND_VERSION_MAX_MAJOR

Основная версия верхней границы, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_MAX_MINOR

Дополнительная версия верхней границы, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_MAX_PATCH

Версия исправления верхней границы, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_MAX_TWEAK

Версия доработки верхней границы, если она запрошена, иначе 0

PACKAGE_FIND_VERSION_MAX_COUNT

Количество компонентов версии верхней границы, от 0 до 4

Независимо от того, указана ли одна версия или диапазон версий, будет определена переменная PACKAGE_FIND_VERSION_COMPLETE, содержащая полную запрошенную строку версии в указанном виде.

Файл версии проверяет, соответствует ли он запрошенной версии, и задает следующие переменные:

PACKAGE_VERSION

Полная предоставленная строка версии

PACKAGE_VERSION_EXACT

Истина, если версия полностью совпадает

PACKAGE_VERSION_COMPATIBLE

Истина, если версия совместима

PACKAGE_VERSION_UNSUITABLE

Истина, если версия не подходит ни в каком качестве

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

<PackageName>_VERSION

Полная предоставленная строка версии

<PackageName>_VERSION_MAJOR

Основная версия, если она предоставлена, иначе 0

<PackageName>_VERSION_MINOR

Дополнительная версия, если она предоставлена, иначе 0

<PackageName>_VERSION_PATCH

Версия исправления, если она предоставлена, иначе 0

<PackageName>_VERSION_TWEAK

Версия доработки, если она предоставлена, иначе 0

<PackageName>_VERSION_COUNT

Количество компонентов версии, от 0 до 4

и загружается соответствующий файл конфигурации пакета.

Примечание

Хотя точное поведение при сопоставлении версий определяется отдельным пакетом, многие пакеты используют write_basic_package_version_file() для предоставления этой логики. Сценарии проверки версии, создаваемые этой командой, имеют некоторые важные особенности при работе с диапазонами версий:

  • Верхняя граница диапазона версий является жестким ограничением для принимаемых версий. Поэтому запрос версии 1.4.0 может быть удовлетворен пакетом версии 1.6.0, который объявляет совместимость в пределах «той же основной версии», однако тот же пакет будет отклонен, если запрошенный диапазон версий — 1.4.0...1.5.0.
  • Обе границы диапазона версий должны соответствовать объявленному уровню совместимости пакета. Например, если пакет объявляет совместимость в пределах «той же основной и дополнительной версии», запрос диапазона версий 1.4.0...<1.5.5 или 1.4.0...1.5.0 приведет к отклонению этого пакета, даже если версия пакета — 1.4.1.

В результате невозможно использовать диапазон версий, чтобы расширить диапазон принимаемых совместимых версий пакета.

Общая спецификация пакетов

Для файлов конфигурации пакетов Общей спецификации пакетов CMake проверяет номера версий пакетов согласно набору распознаваемых схем версий. В настоящее время распознаются следующие схемы:

simple

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

custom

Механизм интерпретации номеров версий не определен. Для принятия пакета строки версий должны полностью совпадать.

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

Помимо version пакета, CPS позволяет пакетам при необходимости указывать compat_version — самую раннюю версию, с которой пакет совместим. Иными словами, пакет гарантирует, что потребитель, которому нужна compat_version, сможет использовать этот пакет, даже если фактическая версия пакета новее. Если значение не указано, compat_version неявно равна версии пакета, то есть обратная совместимость не обеспечивается.

Если пакет использует распознаваемую схему, CMake определяет, является ли пакет приемлемым, согласно следующим правилам:

  • Если указано EXACT или пакет не предоставляет compat_version, version пакета должна совпадать с запрошенной версией.
  • В противном случае:

    • version пакета должна быть больше или равна запрошенной (минимальной) версии, и
    • compat_version пакета должна быть меньше или равна запрошенной (минимальной) версии, и
    • если указана запрошенная максимальная версия, она должна быть больше (или равна — в зависимости от того, задана ли максимальная версия как включительная или исключительная) version пакета.

Примечание

Этот способ сопоставления диапазонов выбран для максимально точного соответствия поведению write_basic_package_version_file(), хотя и без случая, когда чрезмерно широкий диапазон не соответствует ничему.

Для пакетов, использующих схему версий simple, если версия приемлема, задаются следующие переменные:

<PackageName>_VERSION

Полная предоставленная строка версии

<PackageName>_VERSION_MAJOR

Основная версия, если она предоставлена, иначе 0

<PackageName>_VERSION_MINOR

Дополнительная версия, если она предоставлена, иначе 0

<PackageName>_VERSION_PATCH

Версия исправления, если она предоставлена, иначе 0

<PackageName>_VERSION_TWEAK

Версия доработки, если она предоставлена, иначе 0

<PackageName>_VERSION_COUNT

Количество компонентов версии, неотрицательное число

Переменные интерфейса файла пакета

При загрузке модуля поиска или файла конфигурации пакета в виде сценария CMake команда find_package определяет переменные, предоставляющие сведения об аргументах вызова (и восстанавливает их исходные значения перед возвратом):

CMAKE_FIND_PACKAGE_NAME

Искомый <PackageName>

<PackageName>_FIND_REQUIRED

Истина, если был указан параметр REQUIRED

<PackageName>_FIND_QUIETLY

Истина, если был указан параметр QUIET

<PackageName>_FIND_REGISTRY_VIEW

Запрошенный вид, если был указан параметр REGISTRY_VIEW

<PackageName>_FIND_VERSION

Полная запрошенная строка версии

<PackageName>_FIND_VERSION_MAJOR

Основная версия, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_MINOR

Дополнительная версия, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_PATCH

Версия исправления, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_TWEAK

Версия доработки, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_COUNT

Количество компонентов версии, от 0 до 4

<PackageName>_FIND_VERSION_EXACT

Истина, если был указан параметр EXACT

<PackageName>_FIND_COMPONENTS

Список указанных компонентов (обязательных и необязательных)

<PackageName>_FIND_REQUIRED_<c>

Истина, если компонент <c> является обязательным, ложь, если компонент <c> является необязательным

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

<PackageName>_FIND_VERSION_RANGE

Полная запрошенная строка диапазона версий

<PackageName>_FIND_VERSION_RANGE_MIN

Указывает, включается или исключается нижняя граница диапазона версий. В настоящее время INCLUDE — единственное поддерживаемое значение.

<PackageName>_FIND_VERSION_RANGE_MAX

Указывает, включается или исключается верхняя граница диапазона версий. Возможные значения этой переменной: INCLUDE или EXCLUDE.

<PackageName>_FIND_VERSION_MIN

Полная запрошенная строка версии нижней границы диапазона

<PackageName>_FIND_VERSION_MIN_MAJOR

Основная версия нижней границы, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_MIN_MINOR

Дополнительная версия нижней границы, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_MIN_PATCH

Версия исправления нижней границы, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_MIN_TWEAK

Версия доработки нижней границы, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_MIN_COUNT

Количество компонентов версии нижней границы, от 0 до 4

<PackageName>_FIND_VERSION_MAX

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

<PackageName>_FIND_VERSION_MAX_MAJOR

Основная версия верхней границы, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_MAX_MINOR

Дополнительная версия верхней границы, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_MAX_PATCH

Версия исправления верхней границы, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_MAX_TWEAK

Версия доработки верхней границы, если она запрошена, иначе 0

<PackageName>_FIND_VERSION_MAX_COUNT

Количество компонентов версии верхней границы, от 0 до 4

Независимо от того, указана ли одна версия или диапазон версий, будет определена переменная <PackageName>_FIND_VERSION_COMPLETE, содержащая полную запрошенную строку версии в указанном виде.

В режиме Module загруженный модуль поиска отвечает за выполнение запроса, описанного этими переменными; подробности см. в документации модуля поиска. В режиме Config команда find_package автоматически обрабатывает параметры REQUIRED, QUIET и <version>, но оставляет за файлом конфигурации пакета обработку компонентов способом, подходящим для этого пакета. Файл конфигурации пакета может задать <PackageName>_FOUND равной false, чтобы сообщить find_package, что требования к компонентам не выполнены.

Транзитивные требования CPS

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

Если в описании пакета в виде сценария CMake для обработки транзитивных зависимостей использовалась бы команда find_dependency(), то для CPS CMake обрабатывает транзитивные зависимости с помощью внутреннего вложенного вызова find_package. Этот вызов может разрешать зависимости пакетов CPS через либо другой пакет CPS, либо пакет, описанный сценарием CMake. Способ обработки зависимостей компонентов CPS имеет некоторые особенности.

Если кандидатом для разрешения транзитивной зависимости является другой пакет CPS, всё просто: COMPONENTS и «компоненты» CPS напрямую сопоставимы (и фактически являются синонимами «импортированных целей» CMake). Однако пакеты, описанные сценариями CMake, обычно проверяют, были ли найдены требуемые компоненты, даже если в описании пакета отдельные компоненты не указаны. Кроме того, даже те пакеты, в которых компоненты описаны, обычно не связывают их с импортированными целями так же, как это принято в CPS. Поэтому передача набора компонентов, объявленных обязательными пакетом CPS, в COMPONENTS приводила бы к ложным ошибкам при разрешении зависимостей.

Чтобы решить эту проблему, если кандидатом для разрешения транзитивной зависимости CPS является пакет, описанный сценарием CMake, CMake передает требуемые компоненты, объявленные потребляющим пакетом CPS, как OPTIONAL_COMPONENTS и выполняет отдельную внутреннюю проверку, что пакет-кандидат предоставил требуемые импортированные цели. Эти цели должны называться <PackageName>::<ComponentName> в соответствии с соглашением CPS, иначе при проверке пакет будет считаться ненайденным.

© 2000–2026 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/latest/command/find_package.html

Spec-Zone.ru

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