Spec-Zone.ru › CMake 3.25

cmake-packages(7)

  • Введение
  • Использование пакетов

    • Пакеты конфигурационных файлов
    • Пакеты модулей поиска
  • Структура пакета

    • Файл конфигурации пакета
    • Файл версии пакета
  • Создание пакетов

    • Создание файла конфигурации пакета

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

    • Пользовательский реестр пакетов
    • Системный реестр пакетов
    • Отключение реестра пакетов
    • Пример реестра пакетов
    • Владение реестром пакетов

Введение

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

Использование пакетов

CMake предоставляет прямую поддержку двух форм пакетов, пакетов конфигурационных файлов и пакетов модулей поиска. Также предоставляется косвенная поддержка pkg-config пакетов через модуль FindPkgConfig. Во всех случаях базовая форма вызова find_package() одинакова:

find_package(Qt4 4.7.0 REQUIRED) # CMake provides a Qt4 find-module
find_package(Qt5Core 5.1.0 REQUIRED) # Qt provides a Qt5 package config file.
find_package(LibXml2 REQUIRED) # Use pkg-config via the LibXml2 find-module

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

find_package(Qt5Core 5.1.0 CONFIG REQUIRED)
find_package(Qt5Gui 5.1.0 CONFIG)

Аналогично, ключевое слово MODULE указывает на использование только модуля поиска:

find_package(Qt4 4.7.0 MODULE REQUIRED)

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

Оба типа пакетов также поддерживают указание компонентов пакета, либо после ключевого слова REQUIRED:

find_package(Qt5 5.1.0 CONFIG REQUIRED Widgets Xml Sql)

либо как отдельный список COMPONENTS:

find_package(Qt5 5.1.0 COMPONENTS Widgets Xml Sql)

или как отдельный список OPTIONAL_COMPONENTS:

find_package(Qt5 5.1.0 COMPONENTS Widgets
                       OPTIONAL_COMPONENTS Xml Sql
)

Обработка COMPONENTS и OPTIONAL_COMPONENTS определяется пакетом.

Установив переменную CMAKE_DISABLE_FIND_PACKAGE_<PackageName> в значение TRUE, пакет <PackageName> не будет просматриваться и всегда будет NOTFOUND. Аналогично, установка CMAKE_REQUIRE_FIND_PACKAGE_<PackageName> в TRUE сделает пакет ОБОЯЗАТЕЛЬНЫМ.

Пакеты конфигурационных файлов

Пакет конфигурационных файлов — это набор файлов, предоставляемых поставщиками для использования потребителями. CMake ищет файлы конфигурации пакета в ряде мест, как описано в документации к find_package(). Наиболее простой способ сообщить cmake(1) о поиске в нестандартном префиксе для пакета — установить переменную кэша CMAKE_PREFIX_PATH.

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

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

Пакеты модулей поиска

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

В отличие от случая с файлом конфигурации пакета, предоставляемого поставщиком, нет единственной точки отсчета, которая идентифицирует пакет как найденный, поэтому переменная <PackageName>_FOUND не устанавливается автоматически командой find_package(). Однако можно ожидать, что она будет установлена по соглашению, и ее должен установить автор модуля поиска. Аналогично, нет переменной <PackageName>_DIR , но каждый из артефактов, таких как расположение библиотек и заголовочных файлов, предоставляет отдельную переменную кэша.

См. руководство cmake-developer(7) для получения дополнительной информации о создании файлов модулей поиска.

Структура пакета

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

Файл конфигурации пакета

Представьте проект Foo , который устанавливает следующие файлы:

<prefix>/include/foo-1.2/foo.h
<prefix>/lib/foo-1.2/libfoo.a

Он также может предоставить файл конфигурации пакета CMake:

<prefix>/lib/cmake/foo-1.2/FooConfig.cmake

с содержанием, определяющим IMPORTED цели или определяющим переменные, такие как:

# ...
# (compute PREFIX relative to file location)
# ...
set(Foo_INCLUDE_DIRS ${PREFIX}/include/foo-1.2)
set(Foo_LIBRARIES ${PREFIX}/lib/foo-1.2/libfoo.a)

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

Команда find_package() может использоваться для поиска файла конфигурации пакета. Эта команда строит набор префиксов установки и ищет в каждом префиксе в нескольких местах. Учитывая имя Foo, она ищет файл с именем FooConfig.cmake или foo-config.cmake. Полный набор местоположений указан в документации к команде find_package(). Одно из мест, где она ищет, это:

<prefix>/lib/cmake/Foo*/

где Foo* — это выражение нечувствительной к регистру подстановки. В нашем примере выражение подстановки будет соответствовать <prefix>/lib/cmake/foo-1.2 , и файл конфигурации пакета будет найден.

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

Файл версии пакета

Когда команда find_package() находит файл конфигурации пакета-кандидата, она ищет рядом с ним файл версии. Файл версии загружается для проверки, является ли версия пакета приемлемым соответствием запрошенной версии. Если файл версии заявляет о совместимости, файл конфигурации принимается. В противном случае он игнорируется.

Имя файла версии пакета должно совпадать с именем файла конфигурации пакета, но к нему добавлены -version или Version перед расширением .cmake. Например, файлы:

<prefix>/lib/cmake/foo-1.3/foo-config.cmake
<prefix>/lib/cmake/foo-1.3/foo-config-version.cmake

и:

<prefix>/lib/cmake/bar-4.2/BarConfig.cmake
<prefix>/lib/cmake/bar-4.2/BarConfigVersion.cmake

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

Когда команда find_package() загружает файл версии, она сначала устанавливает следующие переменные:

PACKAGE_FIND_NAME

<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

END_OF_DOCUMENT_MARKER

Файл версии должен использовать эти переменные для проверки совместимости или точного соответствия запрошенной версии и устанавливать следующие переменные с результатами:

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

Переменные сообщают о версии пакета, который фактически был найден. Часть их имени <PackageName> соответствует аргументу, переданному команде find_package().

Создание пакетов

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

project(UpstreamLib)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE ON)

set(Upstream_VERSION 3.4.1)

include(GenerateExportHeader)

add_library(ClimbingStats SHARED climbingstats.cpp)
generate_export_header(ClimbingStats)
set_property(TARGET ClimbingStats PROPERTY VERSION ${Upstream_VERSION})
set_property(TARGET ClimbingStats PROPERTY SOVERSION 3)
set_property(TARGET ClimbingStats PROPERTY
  INTERFACE_ClimbingStats_MAJOR_VERSION 3)
set_property(TARGET ClimbingStats APPEND PROPERTY
  COMPATIBLE_INTERFACE_STRING ClimbingStats_MAJOR_VERSION
)

install(TARGETS ClimbingStats EXPORT ClimbingStatsTargets
  LIBRARY DESTINATION lib
  ARCHIVE DESTINATION lib
  RUNTIME DESTINATION bin
  INCLUDES DESTINATION include
)
install(
  FILES
    climbingstats.h
    "${CMAKE_CURRENT_BINARY_DIR}/climbingstats_export.h"
  DESTINATION
    include
  COMPONENT
    Devel
)

include(CMakePackageConfigHelpers)
write_basic_package_version_file(
  "${CMAKE_CURRENT_BINARY_DIR}/ClimbingStats/ClimbingStatsConfigVersion.cmake"
  VERSION ${Upstream_VERSION}
  COMPATIBILITY AnyNewerVersion
)

export(EXPORT ClimbingStatsTargets
  FILE "${CMAKE_CURRENT_BINARY_DIR}/ClimbingStats/ClimbingStatsTargets.cmake"
  NAMESPACE Upstream::
)
configure_file(cmake/ClimbingStatsConfig.cmake
  "${CMAKE_CURRENT_BINARY_DIR}/ClimbingStats/ClimbingStatsConfig.cmake"
  COPYONLY
)

set(ConfigPackageLocation lib/cmake/ClimbingStats)
install(EXPORT ClimbingStatsTargets
  FILE
    ClimbingStatsTargets.cmake
  NAMESPACE
    Upstream::
  DESTINATION
    ${ConfigPackageLocation}
)
install(
  FILES
    cmake/ClimbingStatsConfig.cmake
    "${CMAKE_CURRENT_BINARY_DIR}/ClimbingStats/ClimbingStatsConfigVersion.cmake"
  DESTINATION
    ${ConfigPackageLocation}
  COMPONENT
    Devel
)

Модуль CMakePackageConfigHelpers предоставляет макрос для создания простого файла ConfigVersion.cmake. Этот файл устанавливает версию пакета. Он считывается CMake, когда вызывается find_package() для определения совместимости с запрошенной версией и для установки некоторых переменных, специфичных для версии <PackageName>_VERSION, <PackageName>_VERSION_MAJOR, <PackageName>_VERSION_MINOR и т.д. Команда install(EXPORT) используется для экспорта целей в наборе экспорта ClimbingStatsTargets, определённом ранее командой install(TARGETS). Эта команда генерирует файл ClimbingStatsTargets.cmake для хранения целей IMPORTED, подходящих для использования в пакетах нижнего уровня, и организует его установку в lib/cmake/ClimbingStats. Сгенерированный файл ClimbingStatsConfigVersion.cmake и файл cmake/ClimbingStatsConfig.cmake устанавливаются в то же место, завершая создание пакета.

Сгенерированные цели IMPORTED имеют установленные свойства для определения их требований к использованию, такие как INTERFACE_INCLUDE_DIRECTORIES, INTERFACE_COMPILE_DEFINITIONS и другие соответствующие встроенные свойства INTERFACE_. Вариант свойства INTERFACE пользователя, перечисленные в COMPATIBLE_INTERFACE_STRING и другие Свойства совместимого интерфейса, также распространяются на сгенерированные цели IMPORTED. В данном случае ClimbingStats_MAJOR_VERSION определяется как строка, которая должна быть совместима среди зависимостей любого зависимого объекта. Установив это пользовательское свойство в этой версии и в следующей версии ClimbingStats, cmake(1) выдаст сообщение об ошибке, если есть попытка использовать версию 3 вместе с версией 4. Пакеты могут выбрать использование такой схемы, если разные основные версии пакета предназначены для несовместимости.

Файл NAMESPACE с двойными двоеточиями указывается при экспорте целей для установки. Эта конвенция с двойными двоеточиями даёт CMake подсказку, что имя является целью IMPORTED, когда она используется пакетами нижнего уровня с командой target_link_libraries(). Таким образом, CMake может выдать сообщение об ошибке, если пакет, предоставляющий его, ещё не найден.

В этом случае при использовании install(TARGETS) был указан INCLUDES DESTINATION. Это приводит к тому, что у целей IMPORTED их INTERFACE_INCLUDE_DIRECTORIES заполняются каталогом include в CMAKE_INSTALL_PREFIX. При использовании цели IMPORTED пакетом нижнего уровня, он автоматически использует записи из этого свойства.

Создание файла конфигурации пакета

В данном случае, файл ClimbingStatsConfig.cmake может быть таким же простым, как:

include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsTargets.cmake")

Поскольку это позволяет пакетам нижнего уровня использовать цели IMPORTED. Если какие-либо макросы должны предоставляться пакетом ClimbingStats, они должны быть в отдельном файле, который устанавливается в то же место, что и файл ClimbingStatsConfig.cmake, и включаться оттуда.

Это также можно расширить, чтобы охватить зависимости:

# ...
add_library(ClimbingStats SHARED climbingstats.cpp)
generate_export_header(ClimbingStats)

find_package(Stats 2.6.4 REQUIRED)
target_link_libraries(ClimbingStats PUBLIC Stats::Types)

Поскольку цель Stats::Types является зависимостью PUBLIC от ClimbingStats, пакеты нижнего уровня также должны найти пакет Stats и связать его с библиотекой Stats::Types. Пакет Stats должен быть найден в файле ClimbingStatsConfig.cmake для этого. Макрос find_dependency из модуля CMakeFindDependencyMacro помогает в этом, распространяя, является ли пакет REQUIRED, или QUIET и т.д. Все REQUIRED зависимости пакета должны быть найдены в файле Config.cmake:

include(CMakeFindDependencyMacro)
find_dependency(Stats 2.6.4)

include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsTargets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsMacros.cmake")

Макрос find_dependency также устанавливает ClimbingStats_FOUND в False в случае, если зависимость не найдена, а также диагностику, что пакет ClimbingStats не может использоваться без пакета Stats.

Если COMPONENTS указываются при использовании пакетом нижнего уровня find_package(), они перечислены в переменной <PackageName>_FIND_COMPONENTS. Если определённый компонент является обязательным, то <PackageName>_FIND_REQUIRED_<comp> будет истинным. Это может быть проверено с помощью логики в файле конфигурации пакета:

include(CMakeFindDependencyMacro)
find_dependency(Stats 2.6.4)

include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsTargets.cmake")
include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsMacros.cmake")

set(_ClimbingStats_supported_components Plot Table)

foreach(_comp ${ClimbingStats_FIND_COMPONENTS})
  if (NOT ";${_ClimbingStats_supported_components};" MATCHES ";${_comp};")
    set(ClimbingStats_FOUND False)
    set(ClimbingStats_NOT_FOUND_MESSAGE "Unsupported component: ${_comp}")
  endif()
  include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStats${_comp}Targets.cmake")
endforeach()

Здесь ClimbingStats_NOT_FOUND_MESSAGE устанавливается в сообщение об ошибке, что пакет не был найден из-за указанного неверного компонента. Эта переменная сообщения может быть установлена для любого случая, когда переменная _FOUND установлена в False, и будет отображена пользователю.

Создание файла конфигурации пакета для дерева сборки

Команда export(EXPORT) создаёт файл определения целей IMPORTED, специфичный для дерева сборки, и не является переносимым. Это аналогично может использоваться с соответствующим файлом конфигурации пакета и файлом версии пакета для определения пакета для дерева сборки, который может использоваться без установки. Потребители дерева сборки могут просто убедиться, что CMAKE_PREFIX_PATH содержит каталог сборки или установить ClimbingStats_DIR на <build_dir>/ClimbingStats в кэше.

Создание переносимых пакетов

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

Пакеты, созданные с помощью install(EXPORT), предназначены для переноса, используя пути, относительные к расположению пакета. При определении интерфейса цели для EXPORT, имейте в виду, что каталоги заголовков должны быть указаны как относительные пути, которые относительны к CMAKE_INSTALL_PREFIX:

target_include_directories(tgt INTERFACE
  # Wrong, not relocatable:
  $<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include/TgtName>
)

target_include_directories(tgt INTERFACE
  # Ok, relocatable:
  $<INSTALL_INTERFACE:include/TgtName>
)

Можно использовать $<INSTALL_PREFIX> generator expression в качестве замены для префикса установки, чтобы не создавать непереносимый пакет. Это необходимо, если используются сложные генераторские выражения:

target_include_directories(tgt INTERFACE
  # Ok, relocatable:
  $<INSTALL_INTERFACE:$<$<CONFIG:Debug>:$<INSTALL_PREFIX>/include/TgtName>>
)

Это также относится к путям, ссылающимся на внешние зависимости. Не рекомендуется заполнять свойства, которые могут содержать пути, такие как INTERFACE_INCLUDE_DIRECTORIES и INTERFACE_LINK_LIBRARIES, путями, относящимися к зависимостям. Например, этот код может некорректно работать для переносимого пакета:

target_link_libraries(ClimbingStats INTERFACE
  ${Foo_LIBRARIES} ${Bar_LIBRARIES}
  )
target_include_directories(ClimbingStats INTERFACE
  "$<INSTALL_INTERFACE:${Foo_INCLUDE_DIRS};${Bar_INCLUDE_DIRS}>"
  )

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

В идеале такие зависимости должны использоваться через собственные IMPORTED цели, которые имеют свои свойства IMPORTED_LOCATION и требования к использованию, такие как INTERFACE_INCLUDE_DIRECTORIES, заполненные соответствующим образом. Эти импортированные цели затем могут использоваться с командой target_link_libraries() для ClimbingStats:

target_link_libraries(ClimbingStats INTERFACE Foo::Foo Bar::Bar)

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

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

  • При построении пакета укажите каждую запись кэша Foo_LIBRARY только как имя библиотеки, например -DFoo_LIBRARY=foo. Это сообщает соответствующему модулю поиска заполнить Foo_LIBRARIES только с foo для запроса у компоновщика поиска библиотеки, а не жёсткой фиксации пути.
  • Либо после установки содержимого пакета, но перед созданием исполняемого файла установки пакета для распространения, вручную замените абсолютные пути плейсхолдерами для подстановки инструментом установки, когда пакет устанавливается.

Реестр пакетов

CMake предоставляет два центральных места для регистрации пакетов, которые были построены или установлены где угодно в системе:

  • Пользовательский реестр пакетов
  • Системный реестр пакетов

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

Команда find_package() ищет два реестра пакетов как две стадии поиска, указанные в документации. Если у него достаточно прав, он также удаляет устаревшие записи реестра пакетов, которые ссылаются на каталоги, которые не существуют или не содержат соответствующий файл конфигурации пакета.

Пользовательский реестр пакетов

Пользовательский реестр пакетов хранится в пользовательском местоположении. Команда export(PACKAGE) может быть использована для регистрации дерева сборки проекта в пользовательском реестре пакетов. В настоящее время CMake не предоставляет интерфейса для добавления деревьев установки в пользовательский реестр пакетов. Установщикам необходимо вручную обучить регистрировать пакеты, если это необходимо.

В Windows пользовательский реестр пакетов хранится в реестре Windows в ключе в HKEY_CURRENT_USER.

Может появиться <PackageName> под ключом реестра:

HKEY_CURRENT_USER\Software\Kitware\CMake\Packages\<PackageName>

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

На платформах UNIX пользовательский реестр пакетов хранится в домашнем каталоге пользователя в ~/.cmake/packages. Может появиться <PackageName> в каталоге:

~/.cmake/packages/<PackageName>

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

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

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

В Windows системный реестр пакетов хранится в реестре Windows в ключе в HKEY_LOCAL_MACHINE. Может появиться <PackageName> под ключом реестра:

HKEY_LOCAL_MACHINE\Software\Kitware\CMake\Packages\<PackageName>

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

Системный реестр пакетов отсутствует на платформах, отличных от Windows.

Отключение реестра пакетов

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

  • Команда export(PACKAGE) не заполняет пользовательский реестр пакетов, когда CMP0090 установлено в значение NEW, если переменная CMAKE_EXPORT_PACKAGE_REGISTRY явно не включена. Когда CMP0090 не установлено в NEW, тогда export(PACKAGE) заполняет пользовательский реестр пакетов, если переменная CMAKE_EXPORT_NO_PACKAGE_REGISTRY явно не отключена.
  • CMAKE_FIND_USE_PACKAGE_REGISTRY отключает пользовательский реестр пакетов во всех вызовах find_package(), когда установлено в FALSE.
  • Устаревшая переменная CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY отключает пользовательский реестр пакетов во всех вызовах find_package(), когда установлено в TRUE. Эта переменная игнорируется, когда CMAKE_FIND_USE_PACKAGE_REGISTRY установлено.
  • CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY отключает системный реестр пакетов во всех вызовах find_package().

Пример реестра пакетов

Простая конвенция для именования записей реестра пакетов - использование хэшей содержимого. Они детерминированы и маловероятны для коллизий (export(PACKAGE) использует этот подход). Имя записи, ссылающейся на конкретный каталог, - это просто хэш содержимого пути каталога.

Если проект организовал существование записей реестра пакетов, таких как:

> reg query HKCU\Software\Kitware\CMake\Packages\MyPackage
HKEY_CURRENT_USER\Software\Kitware\CMake\Packages\MyPackage
 45e7d55f13b87179bb12f907c8de6fc4 REG_SZ c:/Users/Me/Work/lib/cmake/MyPackage
 7b4a9844f681c80ce93190d4e3185db9 REG_SZ c:/Users/Me/Work/MyPackage-build

или:

$ cat ~/.cmake/packages/MyPackage/7d1fb77e07ce59a81bed093bbee945bd
/home/me/work/lib/cmake/MyPackage
$ cat ~/.cmake/packages/MyPackage/f92c1db873a1937f3100706657c63e07
/home/me/work/MyPackage-build

тогда код CMakeLists.txt:

find_package(MyPackage)

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

Владение реестром пакетов

Записи реестра пакетов индивидуально принадлежат установкам проектов, на которые они ссылаются. Установщик пакета отвечает за добавление собственной записи, а соответствующий удалитель отвечает за её удаление.

Команда export(PACKAGE) заполняет пользовательский реестр пакетов местоположением дерева сборки проекта. Деревья сборки, как правило, удаляются разработчиками и не имеют события "удаления", которое могло бы инициировать удаление их записей. Чтобы поддерживать реестры в чистоте, команда find_package() автоматически удаляет устаревшие записи, если у неё достаточно разрешений. CMake не предоставляет интерфейса для удаления записи, ссылающейся на существующее дерево сборки после того, как была вызвана export(PACKAGE). Однако, если проект удаляет свой файл конфигурации пакета из дерева сборки, запись, ссылающаяся на местоположение, будет считаться устаревшей.

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

Spec-Zone.ru

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