考虑两个软件项目proj_a和proj_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 中“做自己的事情”,并且仅通过我导出/安装的内容为其他人保持整洁。
我的问题:
add_subdirectory(),而不是构建、安装和执行相当于find_package()满足依赖性?或者更确切地说,为什么应该将前者而不是后者作为默认值?CMakeLists.txt才能与add_subdirectory()“ed”兼容吗?注意:仅举一些具体示例来说明此用途如何限制proj_a:
WITH_TESTS, …当我使用 CMake FetchContent 导入 OpenCV 时,它工作正常:
include(FetchContent)
# Fetch OpenCV
FetchContent_Declare(
opencv
GIT_REPOSITORY https://gitee.com/aiproach/opencv.git
GIT_TAG 4.4.0
)
FetchContent_MakeAvailable(opencv)
set(OpenCV_DIR ${CMAKE_CURRENT_BINARY_DIR})
find_package(OpenCV REQUIRED)
Run Code Online (Sandbox Code Playgroud)
但在我添加特征之后:
# Fetch Eigen
FetchContent_Declare(
eigen
GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git
GIT_TAG 3.3.9
)
FetchContent_MakeAvailable(eigen)
find_package(eigen3 REQUIRED)
Run Code Online (Sandbox Code Playgroud)
它会发出错误:
include(FetchContent)
# Fetch OpenCV
FetchContent_Declare(
opencv
GIT_REPOSITORY https://gitee.com/aiproach/opencv.git
GIT_TAG 4.4.0
)
FetchContent_MakeAvailable(opencv)
set(OpenCV_DIR ${CMAKE_CURRENT_BINARY_DIR})
find_package(OpenCV REQUIRED)
Run Code Online (Sandbox Code Playgroud)
有人告诉我这是由命名空间冲突引起的,但我不知道如何解决该问题。我在 GitHub 上搜索了“FetchContent”,但似乎每个人都和我一样使用它。是否有一种通用方法可以使用 FetchContent 获取所有内容,只需插入项目名称和 URL?