news 2026/1/19 13:07:19

【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进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/19 20:47:51

新手如何入门电影解说?账号布局+AI量产,这套组合拳太狠了!

新手解说如何霸屏全网?账号布局AI量产干货教学很多新手有个误区:觉得做影视解说最难的是剪辑。其实最难的是持续的产能! 特别是在你决定一稿多发布局全网的时候,如果还在纯手搓,根本供不上那么多平台的胃口。今天依旧是…

作者头像 李华
网站建设 2026/1/19 12:18:03

巨 椰 云手机离线多开

云手机离线多开是指通过云手机技术,在云端创建多个虚拟手机环境,即使本地设备离线、关机或息屏,这些虚拟手机仍能继续运行游戏或应用程序,实现 24 小时不间断工作或挂机。巨 椰云手机可节省本地设备资源,无需高性能设备…

作者头像 李华
网站建设 2026/1/10 12:53:48

ESP32 Arduino模拟SPI实战指南:主机与从机通信实现

目录 一、模拟SPI核心原理(模式0) 二、前期准备 1. 硬件材料 2. 软件环境 三、核心实现:代码编写与解析 1. 通用引脚定义(主机与从机一致) 2. 主机代码实现 3. 从机代码实现 四、硬件连接步骤 五、测试与调试…

作者头像 李华
网站建设 2025/12/25 18:11:35

除了Web安全,还有哪些适合零基础入门者探索的网络安全细分方向?

除了Web安全,零基础者确实还有其他不错的入门选择。下面这个表格梳理了三个主要方向的核心特点,帮你快速了解。方向名称核心工作内容适合人群主要工具/技术入门周期参考安全运维​日常安全监控、漏洞扫描、系统加固、应急响应,像企业的“安全…

作者头像 李华
网站建设 2026/1/10 19:59:37

西门子OPCenter创建SWAC组件所需JSON格式

Siemens Web Application Collaboration (SWAC) 库是一种 JavaScript 库,旨在简化和标准化 Siemens “mash-up” Web 应 用程序的开发。 SWAC 有助于集成第三方 SWAC 组件。 SWAC组件JSON格式如下: {"mver": "1.2.0","swac&quo…

作者头像 李华