gpt4 book ai didi

c++ - CMake 包配置文件中的通用 "transitive behavior"(find_dependency)

转载 作者:行者123 更新时间:2023-12-04 06:00:08 24 4
gpt4 key购买 nike

我正在尝试增强我的 CMake约定优于配置
目前的框架。我的每个 C++ 组件(即 CMake 项目)都是通过该框架构建的,并且该框架已经能够创建 CMake Package Configuration File使用 configure_package_config_file() 命令。

以下(最小)模板文件PackageConfig.cmake.in (v1) 由框架使用。

@PACKAGE_INIT@

include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
check_required_components("@PROJECT_NAME@")

如果使用该方法构建和安装组件 Foo 一切正常
由另一个组件 Bar 使用 find_package(<package> CONFIG) 命令(只要正确的目录路径指向
Foo 的已安装 CMake 包配置文件是通过 CLI 设置的)。

但是(当然)如果 A 本身具有一个或多个依赖项,就会出现问题。使用当前方法,B 必须 find_package()的每个依赖项
一个本身。这意味着传递依赖关系当前不会报告给需要依赖关系的组件。显然这不是我想要的
达到。

经过一番谷歌搜索后,我了解到 find_dependency() 为解决上述问题而创建的命令:

It is designed to be used in a Package Configuration File (<package>Config.cmake). find_dependency forwards the correct parameters for QUIET and REQUIRED which were passed to the original find_package() call. Any additional arguments specified are forwarded to find_package().



到目前为止一切顺利,但等等...我必须 明确 再次设置每个依赖项名称及其版本?在声明 CMakeLists.txt 中的依赖项时,我已经这样做了。 !如何创建可重用的通用包
配置文件使用那个方法?除了在 CMakeLists.txt 中明确列出所有依赖项(连同它们的版本)之外,我目前无法确定该问题的任何解决方案。并将该列表传递给 PackageConfig.cmake.in .

示例:未经测试 PackageConfig.cmake.in (v2):
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)

# TODO(wolters): How-to implement this with a generic approach? Would the
# following work? Does a better solution do the problem exist?
#
# 1. Add the following to `CMakeLists.txt`:
# list(APPEND target_dependencies "Baz 1.2.3")
# list(APPEND target_dependencies "Example 0.9.0")
# 2. "Pass" the variable `target_dependencies` to the
# `configure_package_config_file` command.
# 3. Add the following code to the CMake package config file.

foreach(dependency "@target_dependencies@")
find_dependency(${dependency})
endforeach()

include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
check_required_components("@PROJECT_NAME@")

虽然这感觉很奇怪,而且我(还)不知道它是否有效(但它应该,
理论上)。

所以我的问题是:我如何一般地实现传递行为
CMake 包配置文件。

最后但同样重要的是:我正在使用最新的稳定 CMake 版本 3.9.4。

最佳答案

这评论太长了,所以我发布作为答案......
首先,您可以在调用 configure_package_config_file 之前计算已加载包的列表。在一个名为 PACKAGE_DEPENDENCIES 的变量中.首先像这样调整您的模板:

@PACKAGE_INIT@

include(CMakeFindDependencyMacro)
@PACKAGE_DEPENDENCIES@

include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
check_required_components("@PROJECT_NAME@")
然后,计算 PACKAGE_DEPENDENCIES ,您可以使用如下代码段:
set(PACKAGE_DEPENDENCIES "")
get_property(packages GLOBAL PROPERTY PACKAGES_FOUND)
foreach (pkg IN LISTS packages)
get_property(is_transitive GLOBAL PROPERTY _CMAKE_${pkg}_TRANSITIVE_DEPENDENCY)
if (is_transitive)
continue()
elseif (${pkg}_VERSION)
string(APPEND PACKAGE_DEPENDENCIES "find_dependency(${pkg} ${${pkg}_VERSION})\n")
else ()
string(APPEND PACKAGE_DEPENDENCIES "find_dependency(${pkg})\n")
endif()
endforeach ()
然后您就可以调用 configure_package_config_file .
然而,这种方法有多种脆弱性:
  • 全局PACKAGES_FOUND属性包括所有包,即使是通过 find_dependency 递归找到的包,这很可能不是您想要的。使用未记录的内部属性 _CMAKE_<PKG>_TRANSITIVE_DEPENDENCY 对其进行过滤(就像我在这里所做的那样)可能会在较新的 CMake 版本中没有警告或策略而中断。它还依赖于调用 find_dependency 的包。而不是 find_package .
  • 通过 Find 模块(而不是配置文件)加载的包可能没有版本集。损坏的配置文件(即没有 PackageConfigVersion.cmake 文件的配置文件)也可能缺少版本信息。

  • (1) 的一个解决方案可能是仅将此行为应用于使用您的约定优于配置框架的包(例如,通过设置特殊的全局属性)。与(2)类似的故事。

    关于c++ - CMake 包配置文件中的通用 "transitive behavior"(find_dependency),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46836767/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com