步骤 11:添加导出配置¶
在本教程的 Installing and Testing 期间,我们为 CMake 添加了安装项目库和标头的功能。在 Packaging an Installer 期间,我们添加了打包此信息的功能,以便可以将其分发给其他人。
下一步是添加必要的信息,以便其他 CMake 项目可以使用我们的项目,无论是从构建目录、本地安装还是打包时。
第一步是更新我们的 install(TARGETS) 命令以不仅指定一个 DESTINATION 还指定一个 EXPORT。 EXPORT 关键字生成一个 CMake 文件,其中包含用于从安装树导入安装命令中列出的所有目标的代码。因此,让我们继续并通过更新 MathFunctions/CMakeLists.txt 中的 install 命令来明确地 EXPORT MathFunctions 库,如下所示:
set(installable_libs MathFunctions tutorial_compiler_flags)
if(TARGET SqrtLibrary)
list(APPEND installable_libs SqrtLibrary)
endif()
install(TARGETS ${installable_libs}
EXPORT MathFunctionsTargets
DESTINATION lib)
# install include headers
install(FILES MathFunctions.h DESTINATION include)
现在我们已经导出了``MathFunctions``,我们还需要明确安装生成的``MathFunctionsTargets.cmake``文件。这是通过将以下内容添加到顶级“CMakeLists.txt”的底部来完成的:
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
)
此时您应该尝试运行 CMake。如果一切设置正确,您将看到 CMake 将生成如下所示的错误:
Target "MathFunctions" INTERFACE_INCLUDE_DIRECTORIES property contains
path:
"/Users/robert/Documents/CMakeClass/Tutorial/Step11/MathFunctions"
which is prefixed in the source directory.
CMake 试图说明的是,在生成导出信息期间,它将导出一条与当前机器本质上相关的路径,并且在其他机器上无效。解决方案是更新``MathFunctions`` target_include_directories() 以了解它在构建目录和安装/包中使用时需要不同的``INTERFACE`` 位置。这意味着将对 MathFunctions 的 target_include_directories() 调用转换为如下所示:
target_include_directories(MathFunctions
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
更新后,我们可以重新运行 CMake 并验证它不再发出警告。
此时,我们已经让 CMake 正确打包了所需的目标信息,但我们仍需要生成一个 MathFunctionsConfig.cmake ,以便 CMake:command:find_package 命令可以找到我们的项目。因此,让我们继续并在项目的顶层添加一个名为“Config.cmake.in”的新文件,其内容如下:
@PACKAGE_INIT@
include ( "${CMAKE_CURRENT_LIST_DIR}/MathFunctionsTargets.cmake" )
然后,要正确配置和安装该文件,请将以下内容添加到顶层“CMakeLists.txt”的底部:
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
)
include(CMakePackageConfigHelpers)
接下来,我们执行 configure_package_config_file()。此命令将配置提供的文件,但与标准的 configure_file 方式有一些具体差异。为了正确使用这个函数,输入文件除了需要的内容外,还应该有一行包含文本“@PACKAGE_INIT@”。该变量将替换为将设置值转换为相对路径的代码块。这些新值可以用相同的名称引用,但要加上“PACKAGE_”前缀。
install(EXPORT MathFunctionsTargets
FILE MathFunctionsTargets.cmake
DESTINATION lib/cmake/MathFunctions
)
include(CMakePackageConfigHelpers)
# generate the config file that includes the exports
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake"
INSTALL_DESTINATION "lib/cmake/example"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
write_basic_package_version_file() 是下一个。此命令写入一个由 find_package() 使用的文件,记录所需包的版本和兼容性。在这里,我们使用 Tutorial_VERSION_* 变量并表示它与 AnyNewerVersion 兼容,表示此版本或任何更高版本与请求的版本兼容。
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake"
VERSION "${Tutorial_VERSION_MAJOR}.${Tutorial_VERSION_MINOR}"
COMPATIBILITY AnyNewerVersion
)
最后,设置要安装的两个生成的文件:
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsConfigVersion.cmake
DESTINATION lib/cmake/MathFunctions
)
至此,我们已经为我们的项目生成了一个可重定位的CMake Configuration,可以在项目安装或打包后使用。如果我们希望我们的项目也可以从构建目录中使用,我们只需将以下内容添加到顶层“CMakeLists.txt”的底部:
export(EXPORT MathFunctionsTargets
FILE "${CMAKE_CURRENT_BINARY_DIR}/MathFunctionsTargets.cmake"
)
通过这个导出调用,我们现在生成一个``MathFunctionsTargets.cmake``,允许其他项目使用构建目录中配置的``MathFunctionsConfig.cmake``,而无需安装它。