news 2026/4/18 10:54:36

【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/4/18 8:34:12

C++模板初阶

目录 1. 泛型编程 2.函数模板 2.1 函数模板概念 2.1 函数模板格式 2.2函数模板的原理 2.3函数模板的实例化 隐式实例化&#xff1a;让编译器根据实参推演模板参数的实际类型 显式实例化&#xff1a;在函数名后的<>中指定模板参数的实际类型 2.4模板参数的匹配原则…

作者头像 李华
网站建设 2026/4/18 8:42:01

基于微信小程序的校园生活服务小程序

Spring Boot基于微信小程序的校园生活服务小程序是一种创新的校园服务模式&#xff0c;它将Spring Boot框架与微信小程序相结合&#xff0c;为师生提供便捷、高效的校园生活服务。以下是对这种小程序的详细介绍&#xff1a; 一、技术背景与框架 开发语言&#xff1a;Java。Ja…

作者头像 李华
网站建设 2026/4/18 8:44:22

为什么你的边缘AI Agent推理这么慢?这7个隐藏因素必须排查

第一章&#xff1a;为什么你的边缘AI Agent推理这么慢&#xff1f;在边缘计算场景中&#xff0c;AI Agent 的推理性能直接影响用户体验和系统响应能力。尽管模型在云端表现优异&#xff0c;但部署到边缘设备后常出现延迟高、吞吐低的问题。这背后涉及硬件算力、模型结构、运行时…

作者头像 李华
网站建设 2026/4/18 8:50:31

选择网安培训的本质是选择“赛道

摘要 在长沙选择网络安全培训时&#xff0c;湖南网安基地与其他机构的差距不仅体现在资质和资源上&#xff0c;更在于其独特的“政‑企‑校”生态模式、实战化教学体系以及直达就业的闭环路径。本文将从资质权威性、教学实战性、就业资源壁垒等维度展开分析&#xff0c;结合真…

作者头像 李华