Cargo 的愿景
摘要
一篇博客文章,提出了改进 Cargo 的愿景,涵盖依赖管理、构建性能、适应性和维护等工作流程,并邀请社区提供意见。
<p><a href="https://lobste.rs/s/mgr9lc/vision_for_cargo">评论</a></p>
查看缓存全文
缓存时间: 2026/08/05 22:02
# Cargo 的愿景
来源:https://epage.github.io/blog/2026/08/cargo-vision/
根据 Stack Overflow 的调查,Cargo 是最受欢迎的开发工具(https://survey.stackoverflow.co/2025/technology#2-cloud-development)。许多人将选择 Rust 归功于 Cargo。我听到很多人说 Cargo 已经很好了,他们想不出还能如何改进。我想把目标定得更高一些。我也很想听听你们的想法:理想的工作流应该是什么样的,以及我们如何实现它。
下面只是我一直在思考的一些内容。我知道我无法了解所有工作流(https://epage.github.io/blog/2026/08/cargo-vision/#areas),而且其他人可能有更好的想法来解决这些问题(https://epage.github.io/blog/2026/08/cargo-vision/#ideas)。我们还需要你的帮助来实现这些目标。这些工作流不仅限于 Cargo,还涉及 Rust、crates.io 等。有很多机会可以深入参与并提供帮助。
## 需要改进的一些工作流
我想从高层视角来讨论工作流。我将把具体的痛点领域(例如构建脚本)作为改进思路的一部分来介绍(https://epage.github.io/blog/2026/08/cargo-vision/#ideas)。
`#[non_exhaustive]`
- 依赖管理(https://epage.github.io/blog/2026/08/cargo-vision/#dependency-management)
- 构建性能(https://epage.github.io/blog/2026/08/cargo-vision/#build-performance)
- 适应性(https://epage.github.io/blog/2026/08/cargo-vision/#adaptability)
- Cargo 维护(https://epage.github.io/blog/2026/08/cargo-vision/#cargo-maintenance)
另外,关于智能体开发的一点说明(https://epage.github.io/blog/2026/08/cargo-vision/#agentic-development)
#### 依赖管理
> “永远押注生态系统的力量。”
> ——电池包:来谈谈 crate 吧,宝贝(https://smallcultfollowing.com/babysteps/blog/2026/07/15/battery-packs/)
我坚信 crates.io 生态系统一直是 Rust 的超级力量之一,它使应用能够快速创建,并具备比没有这个生态系统时更强大的能力和更好的打磨程度。应用不仅可以利用现有功能,还可以受益于任何未来的功能和修复。例如,`ripgrep`(https://github.com/BurntSushi/ripgrep/)正在针对大型 monorepo 进行优化,而 `typos`(https://github.com/crate-ci/typos)因为复用了 `ignore`(https://crates.io/crates/ignore)而自动受益。全新的实现或 fork 则无法获得这样的好处。
这也使得共享审计成为可能。在你的应用中,你可以使用一两个也被其他人使用的序列化框架,也可以审计分散在配置系统、网络通信等中的十个定制方案。
依赖并非没有成本和风险,我们应该努力降低这些成本和风险。
**如何发现一个高质量的依赖?**
有一些“众所周知”的依赖可以使用,前提是你了解这些信息。生产力不应该取决于内部知识。当没有“众所周知”的依赖时,你只能自己寻找候选者,这并不总是容易的。为了比较它们,你需要寻找各种信号来判断它是否安全、是否适合你的用途、是否可以长期依赖。这些信号可能包括下载量、谁在依赖它、是否经过审查,以及作者其他软件包带来的信任。了解并汇总这些信息可能需要大量工作。
在理想世界中,所有依赖都会经过审查。我们并不生活在理想世界中,但如何更接近这个目标呢?在 Rust 中,我们有 `unsafe` 来隔离需要进一步检查的代码。我们需要更多类型的审计点,并扩大它们的可发现性。如果这些审计点在可能的情况下是选择加入的,且有一个不需要审计的备选方案(以性能或功能为代价),那就更好了。不过有时我们仍然想走捷径,信任他人的审查,而对自己或他人审查的跟踪应该与依赖的使用集成在一起。
**如何最小化升级开销?**
首先,我们需要改善维护者在 lint 和测试方面的现状,以减少 bug 和非预期的变更。假设我们讨论的是预期中的变更,简单的答案似乎是劝阻破坏性变更,但这对维护者来说意味着无法清除某些类型的技术债务,对用户来说则意味着功能、修复和构建性能受到限制。
我们应该鼓励记录变更并更好地展示这些变更。然而,这只是治标不治本的权宜之计。我们如何做得更好?一个灵感来源是 Rust 语言本身,它通过 Edition 提供了一种选择加入的破坏性变更形式。Rust 项目通过不稳定的特性和为用户提供迁移来准备一个 Edition。这应该被视为我们为维护者和用户提供的软件包体验的最低标准。
更进一步,我们可以更好地向用户展示这些变更,内联到他们的工作流中,并针对他们的具体情况提供指导。这在无法进行迁移时尤其重要。
作为今天就能做的一个实验,在 clap 中我采用了这样的实践:破坏性变更以并行特性的方式引入,在可能的情况下弃用旧行为并附上迁移说明。弃用被放在 `deprecated` 特性标志后面,因为很多人把警告(包括弃用警告)视为错误,默认开启它们会将升级与解决弃用问题耦合在一起,从而增加成本和风险。这大大简化了迁移指南(https://github.com/clap-rs/clap/blob/v4.6.4/CHANGELOG.md#migrating),变成了“启用一个特性,然后按照它说的做”。
在无法使用并行特性的情况下,我们使用 `unstable-vX` 特性,这样既不会因为最终的破坏性变更而阻塞开发,也更便于收集反馈。
我看到的问题:
- 对 `deprecated` 特性的感知不足
- 迁移指南的发现难度
- 迁移仍然是手动的
- `unstable-vX` 特性可能产生意想不到的效果,需要更多护栏才能大规模使用
- 这些只是我自创的约定;要维持这种文化,需要一条铺好的路来提高认知度并鼓励使用
#### 构建性能
改进构建性能不是为了快 2%,而是为了改变用户的工作方式,让 Rust 对更多用户有吸引力。用户的比较对象从 C++(在考虑预构建框架之前与 Rust 更相似)到脚本语言(无需构建)不等。
我们还需要超越 `rustc` 的性能,关注用户的工作流。用户希望在堆栈底部做小改动时获得即时反馈,但不幸的是,这会导致整个堆栈重新构建,即使对 `cargo check` 来说也需要一些时间。他们在迭代测试失败直到行为正确,要么在循环中运行所有 `cargo test --workspace`(“因为这很简单”),要么为每个失败手动构造一个命令,如 `cargo test -p application-library --test area -- some::test::name`,以更快的迭代时间为代价换来中断。
也许在处理上述两种情况时,他们基于 `main` 分支进行 rebase,现在因为依赖更新而整个堆栈都在重新构建。或者他们磁盘空间不足,不得不运行 `rm -rf target`。或者它无缘无故地重新构建了。或者,在处理上述情况时,Cargo 阻塞在并行调用上,无论这个调用来自 rust-analyzer、他们想共享缓存的另一个工作树,还是他们系统中想共享缓存的另一个项目。
有些用户会在等待 CI 完成时切换任务,以免在未合并的代码之上堆叠太多更改,从而增加代价高昂的合并冲突风险。CI 系统有缓存,但过度缓存会因网络传输和解压时间而抵消所有好处。对本地调试有利的默认设置会增加缓存大小并减慢构建速度。虽然构建结果会被缓存,但测试结果不会,整个测试套件会重新运行。
另请参阅我在 RustNL 2025 上的演讲:视频(https://www.youtube.com/watch?v=-jy4HaNEJCo&t=678s&pp=ygUOcnVzdG5sIGVkIHBhZ2U%3D)/ 幻灯片(https://epage.github.io/talks/2025/05/performance)
#### 适应性
Cargo 旨在有主见(https://doc.crates.io/contrib/design.html),但在主见和向后兼容之间,它可能难以适应不同的需求,无论是改进 docker 缓存(https://github.com/rust-lang/cargo/issues/2644)、复杂的应用需求(https://epage.github.io/blog/2023/08/are-we-gui-build-yet/),还是融入更大的企业环境。
在 git 中,操作被分为底层命令(plumbing)和上层命令(porcelain)(https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain)。Cargo 几乎全是上层命令,程序化使用非常有限。添加底层命令并扩展上层命令的程序化输出将大大有助于人们根据自身需求改造 Cargo。
#### Cargo 维护
任何关于改进 Cargo 的讨论都有一个前提:Cargo 团队需要有足够的精力在维持日常运营的同时支持这些工作。此前,Cargo 经历了数年的功能冻结(https://blog.rust-lang.org/inside-rust/2022/03/31/cargo-team-changes/),原因是团队人手不足。我担心我们离重蹈覆辙有多近。
在那次功能冻结期间及之后的一段时间里,我们专注于改进流程和工具,以提高维护 Cargo 的效率。例如,我们开发并迁移到了一个满足我们需求的快照测试库(snapbox(https://docs.rs/snapbox/),参见 #14039(https://github.com/rust-lang/cargo/issues/14039)),从而更容易进行大规模的 UX 变更。
现在,我认为拖慢我们脚步最多、限制我们变更范围的,是 Cargo 的架构。Cargo 很古老,拥有定制的框架、对并发操作的限制、在使用 Rust 库可以替代时仍使用 C 库,并且没有清晰的边界,做出或审查变更时需要全局知识。
不是每个人都能资助这样的工作,而我们培养新的设计和代码审查者的速度也是有限的。外部贡献者最能帮助 Cargo 团队的地方不是代码,而是思考。思考的一个主要推动因素是将所有上下文集中在一处——收集线程中的所有相关信息并进行总结,以便于消化。例如,我有一个在其他项目上的 PR 进展缓慢,当我回头查看时,我必须重新阅读整个 Issue 线程来刷新自己对该 PR 旨在实现的行为的记忆。这是大量的工作,而且使得我需要专门的“专注时间”来审查它,让它永远停留在“某一天”的类别中。
这听起来可能是智能体的理想工作。但验证信息来源和思考其分析仍然需要时间。
另请参阅 D-SUMMARIZE(https://epage.github.io/dev/pr-style/#d-summarize)。
#### 关于智能体开发的一点说明
Rust 成功的很大一部分在于努力像对待人一样与人交流(https://hachyderm.io/@ekuber/116970121496881903)。这偶然地也让 Rust 在智能体开发中受益,因为许多需求是重叠的。我认为从长远来看,继续关注人类将是最好的策略,前提是假设智能体会不断进步。
研究智能体开发的需求之所以有价值,是因为你会看到人类面临的相同问题,但规模大到足以让我们摆脱对“够用就好”的 10% 改进的自满。
在我看来,人类和智能体重叠的三个支柱是:
**信号质量:**
Rust 适合智能体开发的一个原因是它提供的反馈。我们需要通过不再那么冗长来澄清 Cargo 的现有信号。我们还需要通过 lint、审计点(比如 `unsafe`)等工具提供更多信号。
**依赖管理:**
我们还需要考虑用于选择和审计依赖的信号,以及降低依赖成本。
**构建性能:**
虽然很多智能体开发是在后台进行的,但智能体运行的命令的性能很重要,尤其是如果你想获得更紧密的反馈循环(例如,bun 跳过了其 Rust 移植第一遍中的 `cargo check`(https://bun.com/blog/bun-in-rust#false-starts))。操作越快,就越接近内循环使用,结果质量也就越好。
## 通往未来的潜在步骤
虽然这个列表很长,但它并非详尽无遗。我写累了。而且有些主题我没有资格多说,或者经验不够。我经常看到一种观点:最近 Rust 中没有什么值得提高 MSRV 的合并。看看这个列表,我看到了很多令人兴奋的东西。
`#[non_exhaustive]`
- 可维护性
- Cargo 的 `async` 化(https://epage.github.io/blog/2026/08/cargo-vision/#asyncify-cargo)
- 迁移离开 `libgit2`(https://epage.github.io/blog/2026/08/cargo-vision/#libgit2)
- 使用 PubGrub 进行解析(https://epage.github.io/blog/2026/08/cargo-vision/#pubgrub)
- 生成 shell 补全(https://epage.github.io/blog/2026/08/cargo-vision/#generated-completions)
- 底层命令(https://epage.github.io/blog/2026/08/cargo-vision/#plumbing-commands)
- 结构化日志(https://epage.github.io/blog/2026/08/cargo-vision/#structured-logging)
- 开放命名空间(https://epage.github.io/blog/2026/08/cargo-vision/#open-namespaces)
- 注册表命名空间(https://epage.github.io/blog/2026/08/cargo-vision/#registry-namespaces)
- 公共依赖(https://epage.github.io/blog/2026/08/cargo-vision/#public-dependencies)
- 电池包
- 软件包分发(https://epage.github.io/blog/2026/08/cargo-vision/#package-distributions)
- 模块模板(https://epage.github.io/blog/2026/08/cargo-vision/#mod-templates)
- 审计
- crate 来源追溯(https://epage.github.io/blog/2026/08/cargo-vision/#crate-provenance)
- 内置依赖(https://epage.github.io/blog/2026/08/cargo-vision/#builtin-dependencies)
- `lang:unsafe`(https://epage.github.io/blog/2026/08/cargo-vision/#lang-unsafe)
- 声明式 derive 宏(https://epage.github.io/blog/2026/08/cargo-vision/#declarative-derive-macros)
- 过程宏和构建脚本的访问控制(https://epage.github.io/blog/2026/08/cargo-vision/#access-controls)
- 减少对构建脚本的需求(https://epage.github.io/blog/2026/08/cargo-vision/#remove-build-scripts)
- 减少用户构建脚本(https://epage.github.io/blog/2026/08/cargo-vision/#build-script-delegation)
- 过程宏和构建脚本的白名单(https://epage.github.io/blog/2026/08/cargo-vision/#build-script-allowlist)
- Cargo lint(https://epage.github.io/blog/2026/08/cargo-vision/#cargo-lints)
- 测试覆盖率(https://epage.github.io/blog/2026/08/cargo-vision/#test-coverage)
- API 演进
- 特性生命周期(https://epage.github.io/blog/2026/08/cargo-vision/#feature-lifecycle)
- API 生命周期(https://epage.github.io/blog/2026/08/cargo-vision/#api-lifecycle)
- 源码内联(https://epage.github.io/blog/2026/08/cargo-vision/#source-inlining)
- 审计 API 变更(https://epage.github.io/blog/2026/08/cargo-vision/#auditing-api-changes)
- 性能
- 改进分解(https://epage.github.io/blog/2026/08/cargo-vision/#improved-decomposition)
- 消除不必要的重建(https://epage.github.io/blog/2026/08/cargo-vision/#
相似文章
@charliermarsh:我一直在为 cargo-fixit 贡献代码:这是一个更快、可直接替代 `clippy --fix` 的工具。这里有一个极端的例子……
Charlie Marsh 宣布了 cargo-fixit,一个更快的、可直接替代 clippy --fix 的工具,在 Codex 仓库上实现了 120 倍的加速。
@zebassembly:疯狂的想法,但如果 CI 不是一场由 YAML 堆砌的噩梦呢?
一条推文提出 CI 不必是 YAML 噩梦,并重点介绍了 Cloudflare 在 Workflows 上的新 CI,该 CI 与 Artifacts 存储和部署相结合。
Cargo-nextest: 比 cargo test 快 3 倍,每个测试隔离,一流的 CI 支持
Cargo-nextest 是 Rust 的下一代测试运行器,提供高达 3 倍的测试执行速度、每个测试的隔离以及一流的 CI 支持。
Cargo-Geiger
cargo-geiger 是一个 Rust cargo 插件,用于列出 crate 及其依赖中不安全代码使用的统计信息,为审计提供输入。
我开发了 Rust 的 Cargo 的克隆版,但是针对 C++
CRow 是一个新的 C/C++ 开源构建系统和依赖管理器,模仿了 Rust 的 Cargo 的简单性。