为什么 foo-config.cmake 和 foo-config-version.cmake 应该分开?

Why should foo-config.cmake and foo-config-version.cmake be separate?

在 Daniel Pfeiffer 的演讲中(Effective CMake) and by Deniz Bahadir (More Modern CMake), and even in the CMake documentation,建议(至少)生成 .cmake 文件以便在其他项目中使用带有 CMake 的存储库:foo-config.cmakefoo-config-version.cmake(对于包 foo;另一种可能的命名方案是 FooConfig.cmakeFooConfigVersion.cmake)。

这对我来说已经很奇怪了。为什么 foo-config.cmake 不应该 information/commands 关于已安装的版本?这两个单独的文件是否存在某些 objective 原因,或者它只是一个 CMake 设计 'gaffe'?

编辑: 删掉了这个问题的其余部分,为了集中注意力,因为我弄错了。

评论太多但不是完整答案:

我生成的项目中的一个典型序列是使用 CMakePackageConfigHelper and GNUInstallDirs 模块 来自CMake。

不需要生成foo-config-version.cmake模板。只需使用此模块中的 write_basic_package_version_file 命令即可完成工作。

如果您想使用构建目录中的配置包而不需要安装它们,export 命令会派上用场。

参见示例:

# Support find_package(Foo NO_MODULE).
set(FOO_DOC_DIR ${CMAKE_INSTALL_DOCDIR})
set(FOO_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
set(FOO_LIB_DIR ${CMAKE_INSTALL_LIBDIR})
set(FOODIR ${CMAKE_INSTALL_PREFIX})

include(CMakePackageConfigHelpers)
include(GNUInstallDirs)

configure_package_config_file(foo-config.cmake.in "${CMAKE_CURRENT_BINARY_DIR}/foo-config.cmake"
  INSTALL_DESTINATION ${FOO_CONFIG_PACKAGE_LOCATION}
  PATH_VARS FOODIR FOO_INCLUDE_DIR FOO_LIB_DIR FOO_DOC_DIR
)

write_basic_package_version_file("${CMAKE_CURRENT_BINARY_DIR}/foo-config-version.cmake"
  VERSION ${PROJECT_VERSION}
  COMPATIBILITY SameMajorVersion
)

# To make the component usable not only from the install directory but also from the build directory
export(
  TARGETS Foo
  FILE foo-export.cmake
)

install(FILES "${CMAKE_CURRENT_BINARY_DIR}/foo-config.cmake" "${CMAKE_CURRENT_BINARY_DIR}/foo-config-version.cmake"
  DESTINATION ${FOO_CONFIG_PACKAGE_LOCATION}
  COMPONENT development
)

install(EXPORT Foo
  DESTINATION ${FOO_CONFIG_PACKAGE_LOCATION}
  NAMESPACE ${PROJECT_NAME}::
  FILE foo-export.cmake
  COMPONENT development
)

Why shouldn't foo-config.cmake also have information/commands regarding the installed version?

包脚本foo-config.cmake可以自由创建目标(不能删除),在父作用域中设置变量,等等。将 foo-config-version.cmake 拆分为在隔离范围内运行的脚本,可以轻松地进行包搜索,而不必担心破坏变量。 可能 将所有这些功能合并到一个文件中(find modules 的方式),但历史表明这种做法是错误的-容易和多余。

基本上有两个优点:

  1. 隔离。 运行 版本脚本不会破坏 find_package 调用程序中的变量。 foo-config.cmake 运行后,它可以设置包变量、创建目标等,并完全相信用户有意执行此操作。
  2. 减少样板文件。 CMakePackageConfigHelpers 可以在 CMakeLists.txt 文件中以两行为代价生成良好的版本脚本。鉴于 CMake 3.19 中的新版本范围功能,这是一项受欢迎的自动化任务。