【问题标题】:If I find_package in CMakeLists.txt, must I find_dependency in my installed config.cmake?如果我在 CMakeLists.txt 中找到_package,我必须在我安装的 config.cmake 中找到_dependency 吗?
【发布时间】:2020-03-25 20:35:48
【问题描述】:

我正在使用 CMake 构建和安装某个库,foo

我的库依赖于其他库 bar,它有一个配置 CMake 脚本,所以我有:

find_package(bar REQUIRED)
target_link_libraries(foo PUBLIC bar::bar)

就建筑而言。对于安装,我有适当的install() 命令,包括导出、版本配置和所有这些东西。这生成包的-config.cmake 文件(以及版本配置文件),所以我不需要在存储库中保留一个,也不需要在我的@987654327 中逐行生成@

现在,CMake 有一个名为find_dependency() 的模块,其documentation 建议用于包配置文件中。但是 - 我没有明确地将它添加到那里。我是不是该?更一般地说:在什么情况下,我应该手动确保包配置文件有一个 find_dependency() 用于各种 find_package() 的?

【问题讨论】:

    标签: build cmake installation dependencies dependency-management


    【解决方案1】:

    首先,CMake 不支持 find_package() 的“传递”行为(检查 this question)。

    documentation 建议“应在 Config.cmake 文件中找到包的所有必需依赖项”:

    # <package>Config.cmake file
    include(CMakeFindDependencyMacro)
    find_dependency(Stats 2.6.4)
    
    include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsTargets.cmake") # They depend on Stats
    include("${CMAKE_CURRENT_LIST_DIR}/ClimbingStatsMacros.cmake")
    

    所以,回答你的问题:

    • “我没有明确添加它。应该吗?”您实际上必须这样做,至少对于 REQUIRED 包而言。
    • “在什么情况下我应该手动确保一个包配置文件有一个 find_dependency() 用于各种 find_package() 的?”对于所需的软件包,您必须。对于可选包,您可能需要将其添加到配置文件中,以便可选功能可用。

    我正在开发一个依赖于外部包 (Catch2) 的项目。在我的顶级 CMakelists.txt 我有:

    # Top level CMakelists.txt
    set(Catch2_DIR "${PATH_TO_CATCH2}/lib/cmake/Catch2/")
    find_package(Catch2 ${CATCH2_VERSION} REQUIRED)
    

    然后我将以下内容添加到我的包配置文件中:

    # <package>Config.cmake file
    include(CMakeFindDependencyMacro)
    set(Catch2_DIR "@PATH_TO_CATCH2@/lib/cmake/Catch2/") #be careful, path hard coded
    find_dependency(Catch2 REQUIRED)
    

    请小心,因为find_dependency 是一个宏,它会更改包配置文件中PACKAGE_PREFIX_DIR 变量的值。

    【讨论】:

    • 1.但是我的包配置文件是使用install(EXPORT) 命令自动生成的...我不想编写-config.cmake 文件。 2. 如果 CMake 可以继承我的目标的 link_libraries 和 include_directories,那为什么不能传递地继承任何创建这些依赖目标的东西(例如我的示例中的 bar::bar)?
    • 在 CMake 项目中,您添加了多个目标。 CMake install(EXPORT) 作用于一个配置为导出的目标。他们的 CMake 会生成一个导出目标的文件,即它的名称和属性。为此,它创建了一个文件foo.cmake。请注意,CMake 知道目标依赖项,但不知道它们来自哪里,是构建还是导入。因此,您必须明确告诉 cmake 也导出该信息。
    • 当然知道。或者更确切地说——它可以知道。每个目标都是通过调用一些 cmake 函数/宏创建的,可能在更大的宏/函数中,如 find_package()。并且很有可能标记目标,例如使用属性,以及关于它们是如何创建的某种链接/信息,以获得不那么短暂的知识。 CMake 可以检查这些属性以在生成的.cmake 中添加find_dependency() 调用。
    • 依赖目标不知道,但依赖目标知道(或者,同样,可以知道)。
    • @einpoklum 是对的。恕我直言,这是 CMake 最大的缺陷之一。我很难想象它是如何得到如此多的采用的。我有一个用 CMake 构建的库,该库具有复杂的配置时配置和许多可选的依赖库。如果我想将一个新应用程序链接到我的库,我必须在两个地方复制所有有条件地调用 find_package 的逻辑和不同的必需组件:一个在库的 CMakeLists.txt 文件中,另一个在库的安装的配置文件。这不是好的设计。
    猜你喜欢
    • 2022-11-20
    • 1970-01-01
    • 1970-01-01
    • 2021-10-11
    • 1970-01-01
    • 1970-01-01
    • 2020-09-14
    • 1970-01-01
    • 2019-08-19
    相关资源
    最近更新 更多