为什么 FetchContent 更喜欢子目录包含而不是安装依赖项?

ein*_*ica 8 installation build cmake build-dependencies fetchcontent

考虑两个软件项目proj_aproj_b,后者取决于前者;两者都使用 CMake。

在阅读现代 CMake 时,人们会得到这样的信息:表达依赖关系的“适当”方式是通过目标依赖关系;并且应该进行安排,以便将依赖项目表示为您可以依赖的(导入的)目标。更具体地说,在我们的示例中,proj_b通常会具有:

find_package(proj_a)

# etc etc.

target_link_library(bar proj_a::foo)
Run Code Online (Sandbox Code Playgroud)

并且proj_a需要使用 CMake 安装和导出相关命令在proj_bCMake 调用将搜索proj_a-config.cmake.

我喜欢这种方法并鼓励其他人适应它。它提供了选择您自己的版本与proj_a系统版本的灵活性;proj_a并且还允许通过脚本进行非 CMake 的操作Findproj_a.cmake(同样,可以是系统级的或 的一部分proj_b)。

到目前为止一切都很好,对吧?然而,有些人希望在依赖关系方面“把事情掌握在自己手中” - CMake 官方承认了这一点,使用诸如ExternalProject和最近的FetchContent之类的命令:这允许proj_b的配置阶段实际下载一个(构建的,或者在我们的例子中是 proj_a 的源形式)版本。

让我困惑的是,proj_a下载后,比如说一个external/proj_a目录,CMake 的默认行为将是

add_subdirectory(external/proj_a)
Run Code Online (Sandbox Code Playgroud)

也就是说,将它们用作proj_a子项目proj_b并一起构建。虽然上面的惯用用法允许维护者proj_a在我的 CMakeFile 中“做自己的事情”,并且仅通过我导出/安装的内容为其他人保持整洁。

我的问题:

  1. 为什么有意义add_subdirectory(),而不是构建、安装和执行相当于find_package()满足依赖性?或者更确切地说,为什么应该将前者而不是后者作为默认值?
  2. 我真的应该编写我的项目级别CMakeLists.txt才能与add_subdirectory()“ed”兼容吗?

注意:仅举一些具体示例来说明此用途如何限制proj_a

  • 必须使用唯一的选项名称,不可能与超级项目名称冲突。所以不再是WITH_TESTSBUILD_STATIC_LIB- 它必须是:WITH_PROJ_A_TESTSBUILD_PROJ_A_STATIC_LIB
  • 您必须考虑到父项目已经搜索了其他依赖项,并且可能与您希望搜索它们的方式不同。

ein*_*ica 3

经过评论中的讨论,我决定发布有关此问题的错误报告:

#22904:支持FetchContent_MakeAvailable执行 build+install+find_package 而不是add_subdirectory

所以也许这种情况会改变,这个问题就变得毫无意义了。

  • 请参阅我在链接的 CMake 问题中的回复,希望它能让您了解该领域的整体情况(我是 FetchContent 的作者)。 (2认同)