Cargo 开发周期:1.83

2024 年 10 月 31 日 · Ed Page 代表 Cargo 团队

Cargo 开发周期:1.83

这是过去 6 周左右 Cargo 开发的总结,大约是 Rust 1.83 的合并窗口。

本周期插件

Cargo 不可能满足每个人的需求,原因之一是它必须维护兼容性保证。插件在 Cargo 生态系统中扮演着重要的角色,我们希望赞扬它们。

我们本周期的插件是 cargo-bloat,它显示了你的二进制文件中哪些部分占用了空间。

感谢 epage 的建议!

请提交你对下一篇文章的建议。

实现

MSRV 感知的 Cargo

来自 1.82 的更新

为了准备编写 MSRV 感知的依赖解析器的文档,epage 修改了依赖解析文档(#14620#14662),并记录了从 RFC 流程中学习到的选择 MSRV 的经验教训(#14636)。

之前,我们讨论了在工作区中解析具有多个不同 MSRV 的依赖项时出现的次优结果。我们为工作区中最低的 MSRV 进行解析。对于具有任何其他 MSRV 的工作区成员,他们要么获得比需要的更旧的版本,要么获得太新的版本。我们建议解析为与工作区中大多数 MSRV 的兼容性。我们改进了报告,以更好地传达这一点。然而,仍然有关于新用户无意中陷入这种情况并感到困惑的担忧。根据我们在 #14636 中提出的 MSRV 策略建议,我们正在引导用户远离这种情况。在与当前状态和拟议状态的剩余问题进行比较后,我们认为平衡已经转向有利于拟议状态,并将其合并到 #14569 中。

此时,epage 发布了 #14639 以稳定并记录 MSRV 感知的解析器。FCP 在 1.83 结束前没有关闭,因此预计在 1.84 中会实现。

我们还在 14568 中讨论并进一步改进了依赖项更改输出。

Shell 补全

来自 1.82 的更新

随着 clap 的新补全系统集成到 nightly Cargo 中(#14493),shannmu 添加了自定义补全器,以努力与手动维护的补全脚本保持一致,包括:

在测试过程中,epage

  • 修复了 bash 的一个 bug (#5731)
  • 使其与 cargo +nightly 一起工作 (clap#5733),随后修复了因此而中断的 rustup 的 --target 补全 (#14564)
  • 使补全在不提供任何补全的情况下出错,而不是补全文件名 (clap#5763)
  • 调整了显示顺序 (clap#5739, clap#5741, clap#5743)
  • 删除了冗余的补全 (clap#5740)

出现的一个问题是,cargo check --bin <TAB> 同时显示二进制文件的名称以及所有 check 选项。像 --bin 这样的选项被定义为可以选择性地接受一个值(即 --bin [NAME]num_args(0..=1)),以便没有补全的用户可以运行 cargo check --bin<ENTER> 并查看他们可以选择的名称列表。由于新的补全器是根据 CLI 的定义工作的,它既为接受值也为不接受值而补全 --bin,不知道实际上需要该值,并且它应该只补全值。理想的解决方案是将“可能的值”报告委托给 clap,这样用户既可以获得更友好的错误报告,又可以获得高质量的补全。我们正在 #14606 中跟踪这个问题。

#14592 中,epage 使分析自定义补全器变得更容易,因为 Cargo 的开销对于此功能的可用性至关重要。

有关如何试用此功能,请参阅文档

公共/私有依赖

来自 1.77 的更新

虽然对公共/私有依赖项的支持进行了一些改进(#14504#14507),但此功能已因 Rustc lint 中的 bug 而受阻(rust#71043rust#119428)。这阻碍了其他可以建立在知道哪些依赖项是私有的或不是的改进,包括:

  • cargo-semver-checks 能够识别何时公共依赖项的主要版本被提升,这对于继承工作区依赖项变得很重要,因为远距离动作可能是一个破坏性的更改
  • 通过跳过无法访问的传递依赖项来加速 cargo doc#2025
  • cargo doc --no-deps 的替代方案,它将为与 API 相关的所有包生成文档
  • 更智能的 cargo add 启发式方法,用于为依赖项选择版本要求
  • 一种保持版本要求同步的方法

zulip 上,epage 提出了在没有 Rustc lint 的情况下稳定 Cargo 中支持的想法。或者,我们可以将 Rustc lint 的范围限制为宁愿产生误报也不要产生漏报。这需要与编译器团队进行更多的计划和协调。

优化 Cargo

来自 1.81 的更新

zulip 上,一些工具作者正在与 Cargo 团队讨论如何优化 cargo metadata

提出的一个问题是 json 的序列化/反序列化时间。在考虑支持另一种格式时,必须与 json 有足够的差异才值得付出努力,它必须有一个良好的兼容性故事,并且我们应该考虑该格式的互操作性。例如,提到了 CBOR。虽然它有一个 IETF RFC,但 Rust 的实现之间存在一些不兼容之处,并且反序列化时间似乎与 json 相当(来源),尽管需要使用 cargo metadata 进行实际基准测试才能判断它是否会产生影响。

在其他性能方面,x-hgg-x 一直在优化依赖项解析器(#14663#14665#14692)。他们还建议我们更改 Cargo 中使用的分配器(#14691)。这正在 zulip 上进行讨论。

设计讨论

Target 和 target

来自 1.82 的更新

我们之前讨论过想要一个 --all-targets-and-doctests 标志。虽然这个名称对于开发来说已经足够好,但我们可能不希望在稳定后使用它。如果我们有一个“targets”的替代名称,我们可以将其称为 --all-<something> 并弃用 --all-targets。这并不是第一次提出重命名“cargo target”或“build target”。

在 Cargo 中,单词 “target” 可以指:

  • 一个独立的构建产物
  • 构建产物的定义和来源(请参阅 Cargo targets
  • build.target-dir,其中存储了构建产物及其构建状态,在交叉编译时按平台三元组组织
  • build.target,它是正在构建的平台三元组
  • Manifest [target]config [target] 表,表面上是针对平台三元组的,但允许几乎任何 cfg 表达式

在 CLI 上,这看起来像:

  • --all-targets
  • --target-dir <PATH>
  • --target <TRIPLE>

该语言变得更加混乱,因为“构建目标”是给定 Cargo.toml 文件的顶级构建产物,而“构建单元”或 “crate” 包括顶级构建产物、相关的构建产物(例如构建脚本、文档测试和单元测试)以及构建所需的任何依赖项。更令人困惑的是,虽然 Cargo 和 Rustc 使用“crate”的定义,但更常见的定义是与 [package] 关联的定义,如 cargo publish 和 crates.io 所使用的那样。

虽然一些用户可能会仔细检查文档或已经非常熟悉 Cargo 的这些角落,但我们仍然应该考虑对刚接触 Cargo 或尚未有理由深入研究这些角落的用户的影响。仅仅谈论这些主题,就需要注意消除这些术语的使用歧义。

特别关注于消除歧义,“target”、build.target[target](大致相当于平台三元组)在 Cargo 和社区中根深蒂固,尝试将其替换的成本会很高。在 1.82 版本中,我们讨论过出于其他原因替换 build.target-dir (#14125) 和 --all-targets (#6669)。这只剩下文档中 “build target”(实际上是 “Cargo target”)的使用,使其成为最容易更改的 “target” 一词的用法。

#14125 中,我们正在考虑将 build.target-dir 的一个替代方案定为 build.artifacts-dir。类似地,当覆盖依赖项的 Cargo.toml 中访问的“build target”时,我们将其称为 artifact dependency(产物依赖)。我们自然倾向于使用术语 “artifact” 来表示 “build target”。然而,这显示了每个术语的使用方式之间存在轻微的脱节。

  • Cargo 仅将二进制文件、动态库以及在命令行上显式请求的静态库复制到 build.artifacts-dir 中,而不是所有 “build target”,尽管有 请求要求实现这种行为。
  • 一个单独的 “build target” 可以有多个输出文件,例如调试文件。我们可能可以忽略这一点。
  • “build target” 还可以指定义和源代码,尽管这有点用词不当,因为它是将 “build target” 作为定义的转喻而产生的。

其他出现过的名称包括

  • 组件 (component)
  • 产品 (product)
  • 输出 (output)

关于此的讨论正在 Internals 上继续进行。

代码检查 (Linting)

来自 1.80 的更新

Urgau 正在考虑扩展 rustc 中的 check-cfg 代码检查系统,使其应用于 Cargo 的 target.<cfg> 表 (#14581)。虽然有一些 Cargo 的新方面需要解决(或推迟),但我们讨论的一个特别问题是代码检查级别和配置应该位于哪个命名空间下。

当前的建议是重用 Cargo 中的 Rustc 代码检查,例如

[lints.rust]
unexpected_cfgs = { level = "warn", check-cfg = ['cfg(foo)'] }

但是,这可能会应用于我们可能希望在 Cargo 中使用的其他类似 Rust 的代码检查和组,包括

通过将它们放在 lints.cargo 中,用户将需要重复他们的 unexpected_cfgs 配置。但是,他们可能希望在 Cargo 和 Rust 之间单独控制其他代码检查,如 deprecatednon_snake_case

通过将它们放在 lints.rust 中,

  • 我们需要弄清楚谁负责 unknown_lints 的代码检查,它既了解 Cargo 又了解 Rust 的 rust:: 代码检查,并确保每个实例只发送一条消息
  • 我们需要弄清楚 Cargo 扩展命名空间以添加新代码检查的流程(例如,是否需要 T-compiler 同意添加 rust::non_kebab_case
  • Cargo 将需要在处理代码检查组之后计算出有效的代码检查级别
  • 我们需要决定 RUSTFLAGS 是否也可以影响 Cargo 的代码检查,因为用户习惯于将其应用于 rust 命名空间

这不仅仅是针对 rust 命名空间。关于 Cargo 是否应该有一个显式的代码检查命令来扮演类似 clippy 的角色,以及是否应该以某种方式成为 cargo clippy 的一部分,仍然存在一个悬而未决的问题。如果是这样,那么 Cargo 也将在 clippy 命名空间中拥有代码检查。

这正在 zulip 上讨论。

构建脚本 API (Build Script API)

Cargo 团队一直在讨论为与 Cargo 交互创建更正式的 API,例如为构建脚本作者提供的 API (#12432)。

在这些讨论中,我们忽略了 RFC 3119,该 RFC 确立了关于 Rust 项目拥有的软件包的政策。在 #14599 中,我们使用了我们的 团队章程 来覆盖添加新软件包的默认流程。然后,我们在 14600 中使用了这个新流程,正式声明了 Cargo 仓库中每个软件包的支持策略。

完成之后,我们在 #12432 中使用了该流程,正式接受了一个构建脚本 API 软件包。

其他 (Misc)

  • 每日报告Eh2406 提供,关于 PugGrub 版本解决算法的 Rust 实现进度
  • Flowrey 完成了他们为 cargo install 添加 --dry-run 标志的工作 (#14280)
  • ahaoboy--timings 添加了暗黑模式 (#14588)
  • Xaeroxe 添加了使用校验和而不是修改时间来确定何时重建的不稳定支持 (#14137)
  • epage 发布了 RFC 3692,该 RFC 源于人们在 RustConf 与 Cargo 团队进行的几次对话
  • 为了回应 #14555,Cargo 团队决定暂时将混合编程和人工输出的责任交给包装工具

没有进展的重点领域 (Focus areas without progress)

这些是 Cargo 团队成员感兴趣的领域,在本开发周期中没有可报告的进展。

准备开发 (Ready-to-develop)

需要设计和/或实验 (Needs design and/or experimentation)

规划 (Planning)

如何提供帮助 (How you can help)

如果您有改进 cargo 的想法,我们建议您首先查看 我们的积压工作,然后在 Internals 上探索这个想法。

如果您希望解决这里没有讨论的特定问题,您可以采取一些步骤来帮助推动它,包括

  • 总结现有的对话(例如:更好地支持 Docker 层缓存Cargo.lock 策略的变更MSRV 感知的解析器
  • 记录来自其他生态系统的现有技术,以便我们可以在他人已完成的工作的基础上构建,并在有意义的地方使用户熟悉的内容
  • 记录 Cargo 中相关的问题和解决方案,以便我们了解我们是否在正确的抽象层面上进行解决
  • 基于这些帖子,提出一个考虑到上述信息和 cargo 兼容性要求的解决方案(示例

我们可以在 zulip 上为 S-accepted issues 提供指导,您可以在 贡献者办公时间 与我们实时交谈。如果您想帮助解决这里提到的较大项目之一,并且您刚开始,修复一些问题 将有助于您熟悉流程和期望,使事情进展得更顺利。如果您想解决 没有导师的问题,那么您需要自己完成的工作的期望会更高。