C/C++ 也想有自己的 Cargo:开源工具 Craft 试图把“折腾构建”变成过去式

C/C++ 世界里,最累人的往往不是写代码
如果你写过 Rust,大概率会怀念 cargo build 那种顺手到几乎不需要思考的体验;如果你长期写 C 或 C++,那你更可能对另一个画面熟悉得多:和 CMakeLists.txt 较劲,跟编译器选项吵架,修依赖修到怀疑人生。某种程度上,C/C++ 的门槛从来不只是语言本身,而是语言周边那一整套“祖传工具链”。
最近,GitHub 上一个名为 Craft 的开源项目开始受到关注。它的野心写得很直白:做一个轻量级的 C/C++ 构建与工作流工具,“像 Cargo,但服务于 C/C++”。开发者只需要在 craft.toml 里描述项目,Craft 会自动生成 CMakeLists.txt、拉取依赖、调用 CMake 在背后完成编译。这个思路并不新鲜,但它抓住了一个很现实的痛点:今天仍有大量开发者依赖 CMake,却不一定喜欢直接写 CMake。
Craft 让人眼前一亮的地方,不是它发明了什么全新的构建理论,而是它承认现实。C/C++ 生态不可能像 Rust 那样一夜之间重新来过,既有项目、历史包袱、跨平台编译需求,全都摆在那里。与其另起炉灶,不如给 CMake 套上一层更现代、也更人性化的壳。这种态度,反而显得聪明。
它没有“革命”CMake,而是在给 CMake 做一层减压阀
Craft 的使用方式很容易理解:创建项目、添加依赖、构建、运行,命令行接口都尽量贴近现代开发者熟悉的节奏。你可以 craft project my_app 新建项目,用 craft add 添加本地或 Git 依赖,再 craft build 和 craft run 完成编译与执行。整个过程的核心,是一个简单的 craft.toml 配置文件。
这件事为什么重要?因为 C/C++ 的真正麻烦,往往不是编译这一步本身,而是“让编译这件事变得可维护”。很多团队都有类似经验:项目最初只有一个 main.cpp,CMakeLists.txt 只有几十行,看起来岁月静好;一年后引入第三方库、拆分模块、兼容 Linux、macOS 和 Windows,构建脚本就开始迅速膨胀,最后变成一种没人想碰、但谁都离不开的神秘遗迹。
Craft 的策略是把这部分复杂度尽可能转移到工具内部。开发者维护单一事实来源 craft.toml,工具自动生成 CMake 配置。如果需要逃生口,它也保留了 CMakeLists.extra.cmake 让用户注入自定义逻辑。这一点很关键。很多“想取代 CMake”的项目最终折戟,不是理念不够美,而是现实不够宽容。Craft 没有逼你彻底告别旧世界,而是允许你带着旧包袱逐步迁移。这种兼容式创新,通常比纯粹主义更容易活下来。
真正戳中痛点的,是依赖管理和老项目迁移
Craft 最像 Cargo 的部分,是它试图把依赖管理也一起收编。开发者可以通过 craft add --git 直接拉 Git 仓库,也可以引用本地 Craft 项目作为依赖。工具会自动把仓库克隆到 .craft/deps/,并处理 CMake 的连接关系。对于很多 C/C++ 开发者来说,这几乎就是“终于有人来收拾这个房间了”。
因为在过去很长时间里,C/C++ 的依赖管理实在太碎了。你可以用系统包管理器装库,也可以用 vcpkg、conan、hunter、FetchContent、git submodule,或者最传统也最常见的方法:把源码扔进项目目录,再配一段祖传脚本。每一种方式都能工作,但每一种方式都可能在跨平台、版本锁定和团队协作时留下坑。Craft 试图做的是把这些高频操作收束成统一命令,这对中小项目尤其友好。
它另一个很有现实感的设计,是 craft init 可以扫描现有项目,自动生成 craft.toml,并备份原有 CMakeLists.txt。这是一个非常“记者看了会点头”的细节:真正有机会进入生产环境的工具,往往不是从零开始最好用,而是接手烂摊子时也不至于把人吓跑。大量 C/C++ 项目不是新建的,而是已经跑了很多年、经历多人维护的老代码库。如果一个工具只适合“开新坑”,那它的实际影响力通常会很有限。
当然,Craft 现在也有明显边界。它对非 Craft 项目的依赖,仍然需要用户手动指定 links 之类的 CMake 目标;对于特别复杂的工程结构,用户大概率还是得回到 CMake 的“额外脚本”里解决问题。这意味着 Craft 并不是万能钥匙,更像是把 80% 的日常痛苦先抹平,再把剩下 20% 的复杂性交还给高级用户。
为什么偏偏是现在,大家又开始重新想做 C/C++ 工具链了
从时间点上看,Craft 的出现并不偶然。过去几年,开发者工具链正在经历一轮很明显的“体验重做”。Rust 用 Cargo 建立了新的心理预期,Go 也早早把标准化工作流做得足够顺滑,JavaScript 世界虽然混乱,但 npm、pnpm、bun 这些工具至少把“安装依赖、启动项目”变成了理所当然的一键操作。反过来看 C/C++,它在性能、控制力和工程寿命上仍然无可替代,但开发体验却长期停留在“强者生存”的阶段。
更现实的背景是,AI 基础设施、游戏开发、嵌入式系统、机器人、数据库和高性能计算,都还离不开 C/C++。这些领域并没有变小,反而因为算力竞赛和端侧计算再次变得重要。行业一边高喊效率,一边却让很多工程师把大量时间花在构建脚本和依赖地狱里,这本身就是一种浪费。谁能把这部分摩擦降下来,谁就有机会得到开发者的好感。
但这里也有一个值得思考的问题:C/C++ 真的还需要一个新的“入口工具”吗?或者说,开发者愿不愿意再学一层新抽象?这恰恰是 Craft 面临的最大挑战。C/C++ 生态的保守,不只是因为工具老,也因为大家对“再来一个新工具”已经有点疲惫了。过去几年,从 Meson 到 Bazel,从 Conan 到 vcpkg,几乎每个方向都有人试图改善体验,但很少有谁能一统江湖。Craft 如果想走得远,光有易用性还不够,它还需要建立信任:出了问题能不能 debug,复杂项目能不能接,团队环境能不能稳定复现,Windows 下会不会翻车。
一个好工具,不一定要成为标准,也可能先成为“默认推荐”
从产品判断上,我觉得 Craft 最有希望的场景,不是立刻挑战 Conan、vcpkg 或 CMake 本身,而是成为个人开发者、小团队、教学场景以及中型开源项目的“新手友好层”。它给 C/C++ 带来的,不只是少写几行配置,而是一种心理上的松弛感:终于不必在项目刚开始时,就先面对一堵构建系统的墙。
这件事听上去可能不够宏大,但往往真正改变生态的,恰恰是这种“让更多普通人敢上手”的工具。Cargo 之所以重要,不只是因为它强,而是因为它把 Rust 的工程实践变成了统一常识。C/C++ 很难彻底复制这条路径,可只要能让新项目从第一天起少掉一半构建摩擦,它就已经很有价值。
我个人对 Craft 的态度,算是谨慎乐观。乐观在于它路线对头:不和 CMake 硬碰硬,而是站在 CMake 肩膀上做体验层升级;谨慎在于 C/C++ 的真实世界远比 README 复杂,任何号称“简单”的方案,最后都得去面对那些跨平台、混合依赖、历史项目和奇怪工具链的泥潭。
不过,哪怕最后 Craft 不能成为行业标准,它的出现本身也说明了一件事:C/C++ 开发者已经越来越不愿意把“折腾构建”视作一种理所当然的修行。大家想要性能,也想要体面。这种期待一旦形成,就不会轻易退回去。