CMake 依赖管理
CMake Dependency Management
我正在寻找有关正确 CMake 依赖管理的一些见解。我遇到过 ExternalProject
和 FetchContent
,但两者都不能完全满足我的需求。让我详细解释一下:
我的项目结构如下:
main_project/
├── CMakeLists.txt
├── external/
│ ├── submodule1/
│ ├── submodule2/
│ ├── submodule3/
│ .
│ .
│ .
每个 submoduleN
都是一个 git 子模块,其中包含一个完整的 CMake 项目,带有自己的 安装目标 。我可以完全控制那些子模块(我编写它们)。我想使用 install targets 因为它们为子模块提供外部接口(具有适当的命名空间等)。我do not want to use the internal build targets。我想使用 find_package
来解决依赖关系。
其次,我不想使用某些下载机制来获取和部署依赖项。我想为此使用 git 个子模块,因为
- 我可以在主项目中冻结子模块版本(依赖版本管理)。
- 我可以轻松地检查任何其他版本以进行调试(无需编辑文件,只需使用 git 并手头有完整的提交消息以供参考)。
假设每个 submoduleN
都有自己相似的子结构,并且它们可能在内部相互依赖。如果他们碰巧有一个共享的依赖关系,我希望他们使用一个单一的、通用的版本。主项目中的层次结构优先于版本选择。例如,类似于 FetchContent
的 populate 习语:
FetchContent_GetProperties(mylib)
if(NOT mylib_POPULATED)
FetchContent_Populate(mylib)
# do build, install and other stuff
endif()
我希望安装目标在配置步骤中可用(即 find_package
),并且我希望在我编辑它们时重建它们(即在一个 submoduleN
中应用一些调试更改)。
问题:
- 我无法使用
ExternalProject_Add
,因为它仅在构建阶段可用。
- 我不能使用
FetchContent
因为它会忽略安装目标(甚至不构建它们)。
- 我不能使用
FetchContent
因为会有重复的目标名称(doc、main、tests 等)。
我知道 Hunter++,它几乎解决了我的问题,除了 git 子模块和非下载部分。我用 ExternalProject
做了一个部分工作的例子,但我发现它很乱而且没有解决常见的版本问题:
https://github.com/image357/cmake_tutorial_external
有什么想法吗?
编辑:
我刚刚在 CMake 上发现了一个类似的提案:
https://gitlab.kitware.com/cmake/cmake/-/issues/21687
快速更新:好像Hunter has a git submodule mode: https://hunter.readthedocs.io/en/latest/user-guides/hunter-user/git-submodule.html
因此它实际上非常适合我的用例。
有这个在你的CMakeLists.txt
include(your/local/path/to/HunterGate.cmake)
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.320.tar.gz"
SHA1 "9b4e732afd22f40482c11ad6342f7d336634226f"
LOCAL
)
hunter_add_package(mysubmodule_lib)
find_package(mysubmodule_lib CONFIG REQUIRED)
在你的项目 cmake/Hunter/config.cmake
中有这个:
hunter_config(mysubmodule_lib GIT_SUBMODULE your/path/to/mysubmodule_lib VERSION 1.2.3)
我正在寻找有关正确 CMake 依赖管理的一些见解。我遇到过 ExternalProject
和 FetchContent
,但两者都不能完全满足我的需求。让我详细解释一下:
我的项目结构如下:
main_project/
├── CMakeLists.txt
├── external/
│ ├── submodule1/
│ ├── submodule2/
│ ├── submodule3/
│ .
│ .
│ .
每个 submoduleN
都是一个 git 子模块,其中包含一个完整的 CMake 项目,带有自己的 安装目标 。我可以完全控制那些子模块(我编写它们)。我想使用 install targets 因为它们为子模块提供外部接口(具有适当的命名空间等)。我do not want to use the internal build targets。我想使用 find_package
来解决依赖关系。
其次,我不想使用某些下载机制来获取和部署依赖项。我想为此使用 git 个子模块,因为
- 我可以在主项目中冻结子模块版本(依赖版本管理)。
- 我可以轻松地检查任何其他版本以进行调试(无需编辑文件,只需使用 git 并手头有完整的提交消息以供参考)。
假设每个 submoduleN
都有自己相似的子结构,并且它们可能在内部相互依赖。如果他们碰巧有一个共享的依赖关系,我希望他们使用一个单一的、通用的版本。主项目中的层次结构优先于版本选择。例如,类似于 FetchContent
的 populate 习语:
FetchContent_GetProperties(mylib)
if(NOT mylib_POPULATED)
FetchContent_Populate(mylib)
# do build, install and other stuff
endif()
我希望安装目标在配置步骤中可用(即 find_package
),并且我希望在我编辑它们时重建它们(即在一个 submoduleN
中应用一些调试更改)。
问题:
- 我无法使用
ExternalProject_Add
,因为它仅在构建阶段可用。 - 我不能使用
FetchContent
因为它会忽略安装目标(甚至不构建它们)。 - 我不能使用
FetchContent
因为会有重复的目标名称(doc、main、tests 等)。
我知道 Hunter++,它几乎解决了我的问题,除了 git 子模块和非下载部分。我用 ExternalProject
做了一个部分工作的例子,但我发现它很乱而且没有解决常见的版本问题:
https://github.com/image357/cmake_tutorial_external
有什么想法吗?
编辑:
我刚刚在 CMake 上发现了一个类似的提案:
https://gitlab.kitware.com/cmake/cmake/-/issues/21687
快速更新:好像Hunter has a git submodule mode: https://hunter.readthedocs.io/en/latest/user-guides/hunter-user/git-submodule.html
因此它实际上非常适合我的用例。
有这个在你的CMakeLists.txt
include(your/local/path/to/HunterGate.cmake)
HunterGate(
URL "https://github.com/cpp-pm/hunter/archive/v0.23.320.tar.gz"
SHA1 "9b4e732afd22f40482c11ad6342f7d336634226f"
LOCAL
)
hunter_add_package(mysubmodule_lib)
find_package(mysubmodule_lib CONFIG REQUIRED)
在你的项目 cmake/Hunter/config.cmake
中有这个:
hunter_config(mysubmodule_lib GIT_SUBMODULE your/path/to/mysubmodule_lib VERSION 1.2.3)