CMakePackageConfigHelpers
Функции-помощники для создания конфигурационных файлов, которые могут быть включены другими проектами для поиска и использования пакета.
Добавляет команды configure_package_config_file() и write_basic_package_version_file().
Генерация файла конфигурации пакета
-
configure_package_config_file -
Создаёт конфигурационный файл для проекта:
configure_package_config_file(<input> <output> INSTALL_DESTINATION <path> [PATH_VARS <var1> <var2> ... <varN>] [NO_SET_AND_CHECK_MACRO] [NO_CHECK_REQUIRED_COMPONENTS_MACRO] [INSTALL_PREFIX <path>] )
Следует использовать configure_package_config_file() вместо обычной команды configure_file() при создании файла <PackageName>Config.cmake или <PackageName>-config.cmake для установки проекта или библиотеки. Это помогает сделать релоцируемым полученный пакет, избегая жёстко закодированных путей в установленных файлах Config.cmake.
В файле FooConfig.cmake может быть код такого вида, чтобы места установки были известны использующему проекту:
set(FOO_INCLUDE_DIR "@CMAKE_INSTALL_FULL_INCLUDEDIR@" )
set(FOO_DATA_DIR "@CMAKE_INSTALL_PREFIX@/@RELATIVE_DATA_INSTALL_DIR@" )
set(FOO_ICONS_DIR "@CMAKE_INSTALL_PREFIX@/share/icons" )
#...logic to determine installedPrefix from the own location...
set(FOO_CONFIG_DIR "${installedPrefix}/@CONFIG_INSTALL_DIR@" )
Все 4 показанных варианта недостаточны, так как первые 3 жёстко кодируют абсолютные пути каталогов, а четвёртый вариант работает только если логика определения installedPrefix корректна, и если CONFIG_INSTALL_DIR содержит относительный путь, что в общем случае гарантировать нельзя. Это приводит к тому, что полученный файл FooConfig.cmake будет работать плохо в Windows и OSX, где пользователи привыкли выбирать место установки двоичного пакета во время установки, независимо от того, как был задан CMAKE_INSTALL_PREFIX при построении/cmake.
Использование configure_package_config_file помогает. Если используется корректно, то это делает полученный файл FooConfig.cmake релоцируемым. Использование:
- Напишите файл
FooConfig.cmake.in, как вы обычно делаете - Вставьте строку, содержащую только строку
@PACKAGE_INIT@ - Вместо
set(FOO_DIR "@SOME_INSTALL_DIR@"), используйтеset(FOO_DIR "@PACKAGE_SOME_INSTALL_DIR@")(эта строка должна следовать за строкой@PACKAGE_INIT@) - Вместо обычной команды
configure_file(), используйтеconfigure_package_config_file()
Аргументы <input> и <output> — входной и выходной файлы, так же, как и в configure_file().
Переменная <path>, передаваемая в INSTALL_DESTINATION, должна быть местом назначения, куда будет установлен файл FooConfig.cmake. Этот путь может быть либо абсолютным, либо относительным к пути INSTALL_PREFIX.
Переменные <var1> до <varN>, задаваемые как PATH_VARS, — это переменные, которые содержат места установки. Для каждой из них макрос создаёт вспомогательную переменную PACKAGE_<var...>. Эти вспомогательные переменные должны использоваться в файле FooConfig.cmake.in для указания места установки. Они вычисляются макросом configure_package_config_file, так что всегда являются относительными к месту установки пакета. Это работает как для относительных, так и для абсолютных путей. Для абсолютных путей это работает только если абсолютный путь является подкаталогом INSTALL_PREFIX.
Если передан аргумент INSTALL_PREFIX, он используется как базовый путь для вычисления всех относительных путей. Аргумент <path> должен быть абсолютным путём. Если этот аргумент не передан, используется переменная CMAKE_INSTALL_PREFIX. Значение по умолчанию подходит для генерации файла FooConfig.cmake для использования вашего пакета из дерева установки. При генерации файла FooConfig.cmake для использования вашего пакета из дерева сборки следует использовать этот параметр.
По умолчанию configure_package_config_file также генерирует два вспомогательных макроса, set_and_check() и check_required_components(), в файл FooConfig.cmake.
set_and_check() следует использовать вместо обычной команды set() для задания каталогов и путей к файлам. В дополнение к установке переменной он также проверяет, что указанный файл или каталог действительно существует, и при этом завершает работу с ошибкой. Это гарантирует, что созданный файл FooConfig.cmake не содержит неверных ссылок. При использовании NO_SET_AND_CHECK_MACRO, этот макрос не генерируется в файл FooConfig.cmake.
check_required_components(<PackageName>) следует вызывать в конце файла FooConfig.cmake. Этот макрос проверяет, были ли найдены все необходимые (не необязательные) компоненты, и если это не так, устанавливает переменную Foo_FOUND в значение FALSE, чтобы пакет считался не найденным. Для этого он проверяет переменные Foo_<Component>_FOUND для всех требуемых компонентов. Этот макрос должен быть вызван даже если пакет не предоставляет компонентов, чтобы гарантировать, что пользователи не указывают компоненты ошибочно. При использовании опции NO_CHECK_REQUIRED_COMPONENTS_MACRO, этот макрос не генерируется в файл FooConfig.cmake.
Пример см. ниже в документации для write_basic_package_version_file().
Генерация файла версии пакета
-
write_basic_package_version_file -
Создаёт файл версии для проекта:
write_basic_package_version_file(<filename> [VERSION <major.minor.patch>] COMPATIBILITY <AnyNewerVersion|SameMajorVersion|SameMinorVersion|ExactVersion> [ARCH_INDEPENDENT] )
Записывает файл для использования в качестве файла <PackageName>ConfigVersion.cmake в <filename>. См. документацию по find_package() для получения дополнительных сведений.
<filename> — имя выходного файла, оно должно находиться в дереве сборки. <major.minor.patch> — номер версии проекта, который будет установлен.
Если VERSION не задан, используется переменная PROJECT_VERSION. Если она не установлена, произойдёт ошибка.
Режим COMPATIBILITY AnyNewerVersion означает, что установленная версия пакета будет считаться совместимой, если она новее или точно такая же, как запрошенная версия. Этот режим следует использовать для пакетов, которые полностью обратной совместимы, также и между версиями с разными главными номерами. Если вместо SameMajorVersion используется AnyNewerVersion, то поведение отличается от AnyNewerVersion в том, что главный номер версии должен быть таким же, как и запрошенный, например, версия 2.0 не будет считаться совместимой, если запрошена версия 1.0. Этот режим следует использовать для пакетов, которые гарантируют обратную совместимость в пределах одной главной версии. Если используется SameMinorVersion, поведение такое же, как у SameMajorVersion, но должны совпадать и главная, и второстепенная версия, например, версия 0.2 не будет совместима, если запрошена версия 0.1. Если используется ExactVersion, пакет считается совместимым только если запрошенная версия точно совпадает с собственной версией пакета (без учёта незначительной версии). Например, версия 1.2.3 пакета считается совместимой только с запрошенной версией 1.2.3. Этот режим предназначен для пакетов без гарантий совместимости. Если ваш проект имеет более сложные правила сопоставления версий, вам придётся написать свой собственный файл ConfigVersion.cmake вместо использования этого макроса.
Если передан аргумент ARCH_INDEPENDENT, установленная версия пакета будет считаться совместимой, даже если она была скомпилирована для другой архитектуры, чем запрошенная. В противном случае будет выполнена проверка архитектуры, и пакет будет считаться совместимым только если архитектуры совпадают точно. Например, если пакет скомпилирован для 32-битной архитектуры, пакет считается совместимым только при использовании на 32-битной архитектуре, если не задан ARCH_INDEPENDENT, в этом случае пакет считается совместимым с любой архитектурой.
Примечание
ARCH_INDEPENDENT предназначен для библиотек только с заголовками или для аналогичных пакетов без двоичных файлов.
Внутренне, этот макрос выполняет configure_file() для создания результирующего файла версии. В зависимости от COMPATIBILITY, используется соответствующий файл BasicConfigVersion-<COMPATIBILITY>.cmake.in. Обратите внимание, что эти файлы являются внутренними для CMake, и вы не должны сами вызывать configure_file() на них, но их можно использовать в качестве отправной точки для создания более сложных пользовательских файлов ConfigVersion.cmake.
Пример генерации файлов пакета
Пример использования как configure_package_config_file(), так и write_basic_package_version_file():
CMakeLists.txt:
set(INCLUDE_INSTALL_DIR include/ ... CACHE )
set(LIB_INSTALL_DIR lib/ ... CACHE )
set(SYSCONFIG_INSTALL_DIR etc/foo/ ... CACHE )
#...
include(CMakePackageConfigHelpers)
configure_package_config_file(FooConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
INSTALL_DESTINATION ${LIB_INSTALL_DIR}/Foo/cmake
PATH_VARS INCLUDE_INSTALL_DIR SYSCONFIG_INSTALL_DIR)
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
VERSION 1.2.3
COMPATIBILITY SameMajorVersion )
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
DESTINATION ${LIB_INSTALL_DIR}/Foo/cmake )
FooConfig.cmake.in:
set(FOO_VERSION x.y.z) ... @PACKAGE_INIT@ ... set_and_check(FOO_INCLUDE_DIR "@PACKAGE_INCLUDE_INSTALL_DIR@") set_and_check(FOO_SYSCONFIG_DIR "@PACKAGE_SYSCONFIG_INSTALL_DIR@") check_required_components(Foo)
© 2000–2020 Kitware, Inc. and Contributors
Licensed under the BSD 3-clause License.
https://cmake.org/cmake/help/v3.15/module/CMakePackageConfigHelpers.html