news 2026/5/11 21:50:53

【CMake】在CMake项目中,Vcpkg、Conan或Spack用于C++依赖

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【CMake】在CMake项目中,Vcpkg、Conan或Spack用于C++依赖


#【CMake】在CMake项目中,Vcpkg、Conan或Spack用于C++依赖

我最近用过一点 Vcpkg,也在更好地了解它。我也看过 Conan,但最近没怎么深入研究 Spack。我从开发者的角度来看,想改进第三方依赖的处理。这并不是要穷尽一切,而是想探讨我最感兴趣的一个具体用例:在某些依赖关系很大需要缓存的情况下,我能以最优雅的方式处理我的项目依赖。

Conan

一开始让我却步的是 Python 的要求,这意味着我需要很大程度上依赖所有依赖。话虽如此,安装过程相当简单:

mkvirtualenv conan pipinstallconan --upgrade

Arch Linux 上还有一个 AUR 包。有了之后,你需要创建一个包含依赖的conanfile.txt,以及使用conan 配置文件 detect --force 的 Conan配置文件。配置文件包含了可以使用的 C++ 标准和构建模式。所以你需要创建一个配置文件用于调试、发布等。

我喜欢默认依赖指定方式的一点是规范中使用了版本。以下是我添加到 angohr 仓库以满足相同 vcpkg 依赖的内容:

[requires]fmt/10.2.1gtest/1.14.0spdlog/1.13.0[generators]CMakeDepsCMakeToolchain

然后使用配置文件安装这些依赖:

conaninstall.--output-folder=build-release --build=missing

一旦完成这些作,命令会自动CMakeUserPresets.json添加该目录中的文件,这意味着我现有的预设不容易被重用。为了测试,我选择了以下几种:

CC=clangCXX=clang++ cmake -G Ninja --preset conan-release -DDuckDB_DIR=/home/marcus/src/duckdb/build

完成这些并修复了 CMake 代码中的一个 bug 后,我就能成功编译项目并运行测试。这个提交显示了依赖文件的添加,以及它发现的实际查找和使用spdlog的修复方法。

Spack

Spack 也有类似的依赖,这让我对 Conan 有兴趣,因为它基于 Python,意味着我的依赖构建依赖相当大。我知道我们通常都有 Python 可用,所以绝不是致命缺点。它还提供克隆或 Arch Linux 的 AUR 包。我试过用这个包,但每次运行时都会被要求权限提升,我在这种情况下可不想要!所以克隆的方法是:

gitclone -c feature.manyFiles=true https://github.com/spack/spack.git.spack/share/spack/setup-env.sh

这提供了一个不试图获得更多权限的安装,接下来是如何指定我的项目依赖。文档内容详尽,仔细阅读后,环境大概是我在这个语境下想要的。

spackenvcreate angohr spackenvactivate angohr

然后,您向环境添加规格有点奇怪

spackaddfmtspackaddgoogletest spackaddspdlog spackinstall

这导致我安装了三个包管理器中最多的一组,像autotoolsgcccmake和 perl 这样的工具在屏幕上闪烁。它可能是最自成一体的,但这并不是我特别需要的。安装这三个软件包后,结果是:

$ spackfind==>In environment angohr==>Root specsfmtgoogletest spdlog==>Installed packages -- linux-archrolling-zen4 / gcc@13.2.1 -------------------------- berkeley-db@18.1.40 diffutils@3.9 googletest@1.14.0 perl@5.38.0 bzip2@1.0.8 fmt@10.2.1 libiconv@1.17 pkgconf@1.9.5 ca-certificates-mozilla@2023-05-30 gcc-runtime@13.2.1 ncurses@6.4 readline@8.2 cmake@3.27.9 gdbm@1.23 nghttp2@1.57.0 spdlog@1.12.0 curl@8.6.0 gmake@4.4.1 openssl@3.2.1 zlib-ng@2.1.5==>20installed packages

对于一个相对较小的轻量级库来说,这感觉有点多。

CC=clangCXX=clang++ cmake -B build -S.-G Ninja -DDuckDB_DIR=/home/marcus/src/duckdb/build cmake --build build

这个配置是完成的,但编译失败了,因为看起来 spdlog 使用了内置的 fmt 副本。我相信这确实是可以修复的问题,但开箱即用的体验令人失望。总的来说,最符合环境创建体验的方法是,你可以在代码目录里创建一个 YAML 文件来指定依赖,这个文件在环境部分稍后一些。

Vcpkg

我觉得 Vcpkg 在很多方面学习曲线最陡峭,需要学习第三方(指定构建参数)、用 git magic 创建使用 git trees 的端口,以及指定预设。一旦做到这一点,它还提供了一个依赖最少且与 CMake 集成最紧密的构建环境。以下内容将构建一个项目:

cmake --preset default -DDuckDB_DIR=/home/marcus/src/duckdb/build cmake --build build

依赖的规范是最简单的,只需在源树中添加 vcpkg.json:

{"dependencies":["fmt","gtest","spdlog"]}

我不喜欢的一点也成了巨大优势,它与 git 深度集成,我可以指定我想用的注册表的基础 SHA。这会锁定所有依赖,直到该 SHA 更新:

{"default-registry":{"kind":"git","repository":"https://github.com/microsoft/vcpkg","baseline":"80403036a665cb8fcc1a1b3e17593d20b03b2489"}}

我不太喜欢但后来接受的是,使用配置步骤让所有这些都用预设实现,这让一切变得简单,添加以下条目后,预设会使用 vcpkg:

"CMAKE_TOOLCHAIN_FILE":{"type":"PATH","value":"$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"},"VCPKG_TARGET_TRIPLET":{"type":"STRING","value":"x64-linux-dynamic"}

上游显然不认为我们应该在 Linux 上使用动态库,我强烈不同意,但他们也提供了多种机制来利用这些库。我认为另一个缺点是默认为每个包构建调试和发布版本,这需要两倍时间,而且通常不需要。你可以用一些技巧来避免这种情况,但默认的姿势令人恼火。

CMake 包管理器

我提到 CMake 包管理器,我会把它归为与上述三个不同的类别,因为它不支持依赖解决或缓存二进制文件。拉入小型依赖非常方便,你可以从 Git 仓库抓取它们,轻松配置和构建。我建议在你选择的上述方法之上叠加,针对那些使用 CMake 的小依赖。

它是纯粹的 CMake 实现,几乎没有额外的依赖(只有一些 CMake 代码),而且有不少不错的例子可以找到。其他包管理器都提供添加自己包的方式,但没有哪个能比得上它的简单。它与 CMake 集成得非常好,你的项目可以非常无缝地使用,但对于配置和构建需要超过 20-30 秒的项目,我可能会选择上述三种方案中的一个。

结论

这三种变体都使用外部构建的 DuckDB 进行比较。这三家公司都提供了三个依赖,而我几乎不费力地提供了他们已有的软件包。它们在指定依赖内容时会有细微差异,比如使用 INI 风格文件、YAML 或 JSON,但转换起来很方便。更大的区别在于它们如何让这些依赖可用,以及它们与 CMake 的集成程度。

说实话,我刚刚花了半小时甚至更久,浏览了这三款的文档(还有那个额外的文档)。我更广泛地使用了 Vcpkg 和 CMake Package Manager,所以上面提到的情况可能被花在它们上的时间太多而有所偏颇。我也从我能提供的最简单开发者体验的角度仔细审视过这个问题。

我还考虑过 CMake 预设与 VS Code 等 IDE 的集成改进。我只认为 Vcpkg 和 CMake Package Manager 能为开发者提供一个很棒的“开箱即用”体验,用户可以选择一个预设,导入包管理器并构建所有依赖,然后再构建项目。维护代码时,Vcpkg 还会更新对新源代码重建的依赖,这非常有优势。Conan 和 Spack 似乎有分离构建树的问题,你也可以用 Vcpkg,如果我漏掉了两个模式都能这样作,我会感兴趣。

我觉得 Vcpkg 的版本规格令人失望,只能要求 >=,但他们也提供了覆盖功能,可以精确指定。在 Vcpkg 中更深入地使用 git 让我更有信心,可以选择何时更新依赖,并且能在仓库中以原子的方式完成。讨论的四个选项都比我以前编写的“超级构建”更优越,满足了我们当时想要的软件包重复使用需求。

参考
https://cryos.net/2024/03/vcpkg-conan-or-spack-for-c-dependencies-in-a-cmake-project/

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/3 8:19:15

云手机 互联网 云端科技

云手机是云端科技在互联网环境下的具体应用,依托互联网与云端服务器相连,借助云端科技实现相关功能,三者紧密相关。互联网是连接用户与云手机的桥梁,用户通过互联网向云端服务器发送操作指令,如打开应用、播放视频等&a…

作者头像 李华
网站建设 2026/5/11 21:50:52

从待机功耗到峰值调度:智能Agent能源管理全流程详解

第一章:智能Agent能源管理的演进与挑战随着分布式计算和边缘智能的快速发展,智能Agent在能源管理系统中的角色日益关键。从早期基于规则的控制逻辑,到如今融合强化学习与联邦学习的自主决策系统,智能Agent已能动态响应电网负载、用…

作者头像 李华
网站建设 2026/5/9 5:13:18

Newtonsoft.Json 与 System.Text.Json 多态反序列化的安全性差异解析

多态反序列化是处理继承结构对象序列化的常见需求,但不同 JSON 序列化库的实现机制差异会带来显著的安全风险。微软 CA2326 规则明确警示:避免使用非安全的 JsonSerializerSettings 配置(如 Newtonsoft.Json 的 TypeNameHandling 非 None 值&…

作者头像 李华
网站建设 2026/5/10 0:29:16

基于Spring Boot的大数据商品推荐系统

是一个强大且智能的推荐工具,它充分利用大数据技术,广泛收集和整合海量的商品数据以及用户行为数据,旨在为用户提供个性化、精准的商品推荐服务。以下是对该系统的详细介绍: 一、系统架构 该系统采用前后端分离的架构模式。后端使…

作者头像 李华
网站建设 2026/5/11 9:51:30

基于Spring Boot的新农村自建房改造管理系统

基于Spring Boot的新农村自建房改造管理系统是一款专为新农村建设中自建房改造项目设计的高效管理工具。以下是对该系统的详细介绍: 一、系统背景与意义 随着国家对新农村建设的大力推进,农村自建房改造成为改善农村居住环境、提升农民生活质量的重要举措…

作者头像 李华
网站建设 2026/5/9 9:21:39

docker 获取 容器启动命令 简单实用

之前同事留存了个容器,要迁移,不知道容器怎么启动的,找到个简单实用的方式,简单实用效果佳!!使用 get_command_4_run_container步骤: 1.下载 docker pull cucker/get_command_4_run_container2.…

作者头像 李华