CMakePackageConfigHelpers¶
用于创建配置文件以供其他项目查找和使用包的辅助函数。
生成包配置文件¶
- 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>] )
当为安装项目或库创建 <PackageName>Config.cmake
或 <PackageName>-config.cmake
文件时,应使用 configure_package_config_file()
而不是普通的 configure_file()
命令。通过避免在安装的 <PackageName>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@" )
上面显示的四个选项都不够。前三个硬编码了绝对目录位置。第四种情况仅在确定 installedPrefix
的逻辑正确且 CONFIG_INSTALL_DIR
包含相对路径(通常无法保证)时才有效。这导致生成的 FooConfig.cmake
文件在 Windows 和 macOS 上表现不佳,因为用户习惯于在安装时选择二进制包的安装位置,而这与构建/CMake 时 CMAKE_INSTALL_PREFIX
的设置方式无关。
使用 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()
中的方式相同。
提供给 INSTALL_DESTINATION
的 <path>
必须是 FooConfig.cmake
文件将安装到的目标。此路径可以是绝对路径,也可以是相对于 INSTALL_PREFIX
路径的相对路径。
作为 PATH_VARS
给出的变量 <var1>
到 <varN>
是包含安装目标的变量。对于每个变量,宏将创建一个辅助变量 PACKAGE_<var...>
。这些辅助变量必须在 FooConfig.cmake.in
文件中用于设置安装位置。它们由 configure_package_config_file()
计算,因此它们始终相对于包的安装位置。这适用于相对位置和绝对位置。对于绝对位置,仅当绝对位置是 INSTALL_PREFIX
的子目录时才有效。
在版本 3.30 中添加: 变量 PACKAGE_PREFIX_DIR
将始终在 @PACKAGE_INIT@
行之后定义。它将保存基本安装位置的值。通常,应使用通过 PATH_VARS
机制定义的变量,但 PACKAGE_PREFIX_DIR
可用于那些不易由 PATH_VARS
处理的情况,例如直接安装到基本安装位置而不是其子目录的文件。
注意
当生成文件的使用者使用 CMake 3.29 或更早版本时,PACKAGE_PREFIX_DIR
的值可以通过调用 find_dependency()
或 find_package()
进行更改。如果项目依赖于 PACKAGE_PREFIX_DIR
,则项目有责任确保 PACKAGE_PREFIX_DIR
的值在任何此类调用或任何其他可能包含由 configure_package_config_file()
生成的文件的调用中得到保留。
在版本 3.1 中添加: 如果传递了 INSTALL_PREFIX
参数,则将其用作计算所有相对路径的基本路径。<path>
参数必须是绝对路径。如果未传递此参数,则将使用 CMAKE_INSTALL_PREFIX
变量。当生成 FooConfig.cmake
文件以从安装树使用包时,默认值是好的。当生成 FooConfig.cmake
文件以从构建树使用包时,应使用此选项。
默认情况下,configure_package_config_file()
还会在 FooConfig.cmake
文件中生成两个辅助宏:set_and_check()
和 check_required_components()
。
set_and_check()
应该用于设置目录和文件位置,而不是使用普通的 set()
命令。除了设置变量外,它还会检查引用的文件或目录是否实际存在,如果不存在则会引发致命错误。这确保了生成的 FooConfig.cmake
文件不包含错误的引用。添加 NO_SET_AND_CHECK_MACRO
选项可阻止在 FooConfig.cmake
文件中生成 set_and_check()
宏。
check_required_components(<PackageName>)
应该在 FooConfig.cmake
文件的末尾调用。此宏检查所有请求的非可选组件是否已找到,如果不是,则将 Foo_FOUND
变量设置为 FALSE
,以便包被视为未找到。它通过测试所有请求的必需组件的 Foo_<Component>_FOUND
变量来实现。即使包不提供任何组件,也应调用此宏,以确保用户不会错误地指定组件。添加 NO_CHECK_REQUIRED_COMPONENTS_MACRO
选项可阻止在 FooConfig.cmake
文件中生成 check_required_components()
宏。
另请参阅 示例生成包文件。
生成包版本文件¶
- write_basic_package_version_file¶
为项目创建版本文件
write_basic_package_version_file(<filename> [VERSION <major.minor.patch>] COMPATIBILITY <AnyNewerVersion|SameMajorVersion|SameMinorVersion|ExactVersion> [ARCH_INDEPENDENT] )
将文件写入 <filename>
,用作 <PackageName>ConfigVersion.cmake
文件。有关此类文件的详细信息,请参阅 find_package()
的文档。
<filename>
是输出文件名,应该在构建树中。<major.minor.patch>
是要安装的项目的版本号。
如果没有给定 VERSION
,则使用 PROJECT_VERSION
变量。如果未设置,则会报错。
COMPATIBILITY
模式 AnyNewerVersion
表示如果已安装的包版本比请求的版本更新或完全相同,则认为其兼容。此模式应用于完全向后兼容的包,包括跨主版本。如果改用 SameMajorVersion
,则其行为与 AnyNewerVersion
不同,即主版本号必须与请求的相同,例如,如果请求版本 1.0,则版本 2.0 将不被视为兼容。此模式应用于保证同一主版本内向后兼容的包。如果使用 SameMinorVersion
,则行为与 SameMajorVersion
相同,但主要版本和次要版本都必须与请求的相同,例如,如果请求版本 0.1,则版本 0.2 将不兼容。如果使用 ExactVersion
,则只有当请求的版本与其自身版本号完全匹配时(不考虑调整版本),才认为包兼容。例如,包的版本 1.2.3 仅被视为与请求的版本 1.2.3 兼容。此模式适用于不保证兼容性的包。如果您的项目具有更复杂的版本匹配规则,则需要编写自己的自定义 <PackageName>ConfigVersion.cmake
文件,而不是使用此宏。
在版本 3.11 中添加: SameMinorVersion
兼容模式。
在版本 3.14 中添加: 如果给定 ARCH_INDEPENDENT
,则即使已安装的包版本是为与请求的架构不同的架构构建的,也将被视为兼容。否则,将执行架构检查,并且只有当架构完全匹配时,包才会被视为兼容。例如,如果包是为 32 位架构构建的,则只有当它在 32 位架构上使用时才被视为兼容,除非给定 ARCH_INDEPENDENT
,在这种情况下,包被视为在任何架构上都兼容。
注意
ARCH_INDEPENDENT
适用于仅包含头文件的库或类似没有二进制文件的包。
在版本 3.19 中添加: 由 COMPATIBILITY
的 AnyNewerVersion
、SameMajorVersion
和 SameMinorVersion
参数生成的版本文件处理版本范围(如果指定了版本范围,请参阅 find_package()
命令了解详细信息)。ExactVersion
模式与版本范围不兼容,如果指定了版本范围,将显示作者警告。
在内部,此宏执行 configure_file()
以创建最终的版本文件。根据 COMPATIBILITY
,使用相应的 BasicConfigVersion-<COMPATIBILITY>.cmake.in
文件。请注意,这些文件是 CMake 内部文件,您不应自己调用 configure_file()
,但它们可以用作创建更复杂的自定义 <PackageName>ConfigVersion.cmake
文件的起点。
生成 Apple 平台选择文件¶
- generate_apple_platform_selection_file¶
在版本 3.29 中添加。
创建 Apple 平台选择文件
generate_apple_platform_selection_file(<filename> INSTALL_DESTINATION <path> [INSTALL_PREFIX <path>] [MACOS_INCLUDE_FILE <file>] [IOS_INCLUDE_FILE <file>] [IOS_SIMULATOR_INCLUDE_FILE <file>] [IOS_CATALYST_INCLUDE_FILE <file>] [TVOS_INCLUDE_FILE <file>] [TVOS_SIMULATOR_INCLUDE_FILE <file>] [WATCHOS_INCLUDE_FILE <file>] [WATCHOS_SIMULATOR_INCLUDE_FILE <file>] [VISIONOS_INCLUDE_FILE <file>] [VISIONOS_SIMULATOR_INCLUDE_FILE <file>] [ERROR_VARIABLE <variable>] )
写入一个文件,该文件包含一个 Apple 平台特定的
.cmake
文件,例如用作<PackageName>Config.cmake
。这可以与export(SETUP)
的XCFRAMEWORK_LOCATION
参数结合使用,以一种任何 Apple 平台构建的项目都可以使用包的方式导出包。INSTALL_DESTINATION <path>
调用者将生成文件安装到的路径,例如通过
install(FILES)
。该路径可以是相对于INSTALL_PREFIX
的相对路径,也可以是绝对路径。INSTALL_PREFIX <path>
调用者将包安装到的路径前缀。
<path>
参数必须是绝对路径。如果未传递此参数,则将使用CMAKE_INSTALL_PREFIX
变量。MACOS_INCLUDE_FILE <file>
如果平台是 macOS,则包含的文件。
IOS_INCLUDE_FILE <file>
如果平台是 iOS,则包含的文件。
IOS_SIMULATOR_INCLUDE_FILE <file>
如果平台是 iOS 模拟器,则包含的文件。
IOS_CATALYST_INCLUDE_FILE <file>
在版本 3.31 中添加。
如果平台是 iOS Catalyst,则包含的文件。
TVOS_INCLUDE_FILE <file>
如果平台是 tvOS,则包含的文件。
TVOS_SIMULATOR_INCLUDE_FILE <file>
如果平台是 tvOS 模拟器,则包含的文件。
WATCHOS_INCLUDE_FILE <file>
如果平台是 watchOS,则包含的文件。
WATCHOS_SIMULATOR_INCLUDE_FILE <file>
如果平台是 watchOS 模拟器,则包含的文件。
VISIONOS_INCLUDE_FILE <file>
如果平台是 visionOS,则包含的文件。
VISIONOS_SIMULATOR_INCLUDE_FILE <file>
如果平台是 visionOS 模拟器,则包含的文件。
ERROR_VARIABLE <variable>
如果消费项目是为不支持的平台构建的,则将
<variable>
设置为错误消息。包含者可以使用此信息假装未找到包。如果未给定此选项,则默认行为是发出致命错误。
如果未指定任何可选的包含文件,并且消费项目是为其对应的平台构建的,则生成的文件将认为该平台不受支持。其行为由
ERROR_VARIABLE
选项决定。
生成 Apple 架构选择文件¶
- generate_apple_architecture_selection_file¶
在版本 3.29 中添加。
创建 Apple 架构选择文件
generate_apple_architecture_selection_file(<filename> INSTALL_DESTINATION <path> [INSTALL_PREFIX <path>] [SINGLE_ARCHITECTURES <arch>... SINGLE_ARCHITECTURE_INCLUDE_FILES <file>...] [UNIVERSAL_ARCHITECTURES <arch>... UNIVERSAL_INCLUDE_FILE <file>] [ERROR_VARIABLE <variable>] )
根据
CMAKE_OSX_ARCHITECTURES
写入一个包含 Apple 架构特定.cmake
文件的文件,例如用于从 Apple 特定<PackageName>Config.cmake
文件中包含。INSTALL_DESTINATION <path>
调用者将生成文件安装到的路径,例如通过
install(FILES)
。该路径可以是相对于INSTALL_PREFIX
的相对路径,也可以是绝对路径。INSTALL_PREFIX <path>
调用者将包安装到的路径前缀。
<path>
参数必须是绝对路径。如果未传递此参数,则将使用CMAKE_INSTALL_PREFIX
变量。SINGLE_ARCHITECTURES <arch>...
由
SINGLE_ARCHITECTURE_INCLUDE_FILES
的条目提供的架构。SINGLE_ARCHITECTURE_INCLUDE_FILES <file>...
特定于架构的文件。当
CMAKE_OSX_ARCHITECTURES
包含与SINGLE_ARCHITECTURES
对应条目匹配的单个架构时,将加载其中一个。UNIVERSAL_ARCHITECTURES <arch>...
由
UNIVERSAL_INCLUDE_FILE
提供的架构。该列表可以包含
$(ARCHS_STANDARD)
以支持使用Xcode
生成器进行消费,但架构应始终单独列出。UNIVERSAL_INCLUDE_FILE <file>
当
CMAKE_OSX_ARCHITECTURES
包含UNIVERSAL_ARCHITECTURES
的(非严格)子集且不匹配任何SINGLE_ARCHITECTURES
时要加载的文件。ERROR_VARIABLE <variable>
如果消费项目是为不支持的架构构建的,则将
<variable>
设置为错误消息。包含者可以使用此信息假装未找到包。如果未给定此选项,则默认行为是发出致命错误。
示例生成包文件¶
使用 configure_package_config_file()
和 write_basic_package_version_file()
命令的示例
CMakeLists.txt
¶include(GNUInstallDirs)
set(INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}/Foo
CACHE PATH "Location of header files" )
set(SYSCONFIG_INSTALL_DIR ${CMAKE_INSTALL_SYSCONFDIR}/foo
CACHE PATH "Location of configuration files" )
#...
include(CMakePackageConfigHelpers)
configure_package_config_file(FooConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/FooConfig.cmake
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/Foo
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 ${CMAKE_INSTALL_LIBDIR}/cmake/Foo )
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)