资讯动态

Cargo 为什么存在:从 `rustc` 到 Rust 包管理器的演进之路

发布时间:2026/9/22 19:11:11 来源:尧图企业网站定制
开发工具包管理器CLI构建工具【免费下载链接】cargoThe Rust package manager项目地址https://gitcode.com/gh_mirrors/car/cargo点击查看免费下载Cargo 是 Rust 的官方包管理器package manager本指南将带你理解它诞生的根本原因直接用rustc手工编译真实项目为何不可行以及 Cargo 如何通过两个元数据文件 自动获取依赖 统一构建调用 目录约定四件事让 Rust 包的构建变得可重复、可共享、可预测。读完本文你将掌握 crate / package / package manager 的核心概念理解Cargo.toml与Cargo.lock的分工并能在 Cargo 指南 的引导下开始你的第一个 Cargo 项目。预备知识crate 与rustc的直接调用在 Rust 中一个库或可执行程序被称为crate箱。crate 使用 Rust 编译器rustc编译。大多数 Rust 初学者接触到的第一段源码就是经典的 hello world 程序他们通过直接调用rustc来编译$ rustc hello.rs $ ./hello Hello, world!注意上面的命令要求你显式指定文件名。如果你想直接用rustc编译另一个程序就需要另一条完全不同的命令行调用如果你还需要指定某些编译器标志compiler flags或引入外部依赖那么所需的命令会变得更加特殊、更加复杂。从源码结构看crate 是 Cargo 世界中最基础的编译单元glossary 中明确指出crate 可能指目标target的源代码也可能指目标编译后产生的产物还可能指从注册表registry获取的压缩包。而artifact构建产物 则是编译过程产生的文件集合包括可链接的库、可执行二进制和生成的文档。更进一步大多数非平凡的程序都会依赖外部库因此还会传递性地依赖这些库的依赖。如果完全靠手工获取所有必要依赖的正确版本并保持它们更新将是困难且极易出错的。与其只和 crate 及rustc打交道你可以通过引入一个更高层的抽象——package包——并借助一个package manager包管理器 来避开上述手工操作的困难。Cargo 登场Rust 的包管理器Cargo就是 Rust 的包管理器。它是一个工具允许 Rustpackages声明它们的各种依赖并确保你总能得到一个可重复的构建repeatable build。为实现这一目标Cargo 主要做四件事引入两个元数据文件携带各种包信息即Cargo.toml与Cargo.lock获取并构建你的包的依赖以正确的参数调用rustc或其他构建工具来构建你的包引入约定conventions让 Rust 包的协作变得更加容易。从 glossary 的 Package manager 条目 可以看到包管理器是软件生态中自动完成获取、安装和升级产物的程序在编程语言生态中其核心功能是从中央仓库下载库产物及其依赖并常常与执行构建调用语言编译器的能力结合。Cargo 正是 Rust 生态中的那个角色它下载你的包依赖即称为 crate 的产物、编译你的包、制作可分发的包并可选择性地将它们上传到 crates.io——Rust 社区的package registry包注册表。统一构建命令一条命令构建所有项目Cargo 在很大程度上规范化了构建给定程序或库所需的命令——这就是上面提到的约定的一个侧面。正如后面会展示的同一条命令可以用来构建不同的artifacts产物无论它们的名字是什么。与其直接调用rustc你可以调用一个通用的命令例如cargo build让 Cargo 去操心如何构造正确的rustc调用。此外Cargo 会自动从registry注册表 获取你为产物定义的任何依赖并按需把它们加入构建。可以毫不夸张地说一旦你知道如何构建一个基于 Cargo 的项目你就知道如何构建所有基于 Cargo 的项目。实战验证从cargo new到cargo run用 Cargo 新建一个包并构建它只需三步详见 入门指南 与 创建新包$ cargo new hello_world --bin--bin表示创建一个二进制程序如果要创建库则传--lib。默认情况下该命令还会初始化一个 git 仓库若不需要可加--vcs none。生成的结构如下. ├── Cargo.toml └── src └── main.rsCargo.toml被称为manifest清单包含 Cargo 编译你的包所需的全部元数据采用 TOML 格式[package] name hello_world version 0.1.0 edition 2024 [dependencies]src/main.rs中是一个二进制 cratefn main() { println!(Hello, world!); }然后编译并运行$ cargo build Compiling hello_world v0.1.0 (file:///path/to/package/hello_world) $ ./target/debug/hello_world Hello, world!或者用cargo run一步完成编译加运行。发布时则使用cargo build --release优化产物会输出到target/release而非target/debug——这正是同一命令、不同目标产物的体现。构建结束后你会注意到多了一个Cargo.lock文件它记录依赖的精确信息。两个元数据文件Cargo.toml与Cargo.lockCargo 引入的两个元数据文件各有明确分工详见 Cargo.toml vs Cargo.lockCargo.toml宽泛地描述你的依赖由你编写。Cargo.lock包含依赖的精确信息由 Cargo 维护不应手工编辑。拿不定主意时请把Cargo.lock提交进版本控制系统如 Git关于原因与替代方案可参考 FAQ为什么要把 Cargo.lock 纳入版本控制并建议配合 持续集成中验证最新依赖 一起使用。为什么需要Cargo.lock可重复构建的关键假设你在Cargo.toml中声明了一个 Git 依赖[package] name hello_world version 0.1.0 [dependencies] regex { git https://github.com/rust-lang/regex.git }由于没有指定其他信息Cargo 会假定你使用默认分支上的最新提交来构建。问题在于你今天构建这个包然后把副本发给别人别人明天构建——期间regex可能又多了新提交于是构建结果就不同了。这违背了可重复构建的初衷。你也可以在Cargo.toml里写死rev[dependencies] regex { git https://github.com/rust-lang/regex.git, rev 9f9f693 }这样构建是一致的但代价是你必须每次手动维护 SHA-1——既繁琐又容易出错。Cargo.lock正是为此而生首次构建时Cargo 会把最新提交的精确信息写入Cargo.lock例如[[package]] name hello_world version 0.1.0 dependencies [ regex 1.5.0 (githttps://github.com/rust-lang/regex.git#9f9f693768c584971a4d53bc3c586c33ed3a6831), ] [[package]] name regex version 1.5.0 source githttps://github.com/rust-lang/regex.git#9f9f693768c584971a4d53bc3c586c33ed3a6831可见其中的信息远比 manifest 丰富包括你构建时使用的精确 revision。这样你把包交给别人时对方会使用完全相同的 SHA即使你没有在Cargo.toml中指定它。当你准备好升级到库的新版本时Cargo 可以帮你重新计算依赖并更新$ cargo update # 更新所有依赖 $ cargo update regex # 只更新 regex这会写出带新版本信息的Cargo.lock。注意cargo update的参数实际上是 Package ID Specification包 ID 规范regex只是它的一个简短形式。自动获取与传递依赖注册表的作用crates.io 是 Rust 社区的中央包注册表cargo默认配置为从中查找所需的包。要依赖 crates.io 上托管的库只需在Cargo.toml的[dependencies]段列出 crate 名称和版本[dependencies] time 0.1.12 regex 0.1.41版本字符串是 SemVer 版本要求。重新运行cargo buildCargo 会获取新依赖及其所有传递依赖、编译它们并更新Cargo.lock$ cargo build Updating crates.io index Downloading memchr v0.1.5 Downloading libc v0.1.10 Downloading regex-syntax v0.2.1 Downloading aho-corasick v0.3.0 Downloading regex v0.1.41 Compiling memchr v0.1.5 Compiling libc v0.1.10 Compiling regex-syntax v0.2.1 Compiling aho-corasick v0.3.0 Compiling regex v0.1.41 Compiling hello_world v0.1.0 (file:///path/to/package/hello_world)此后即使regex发布了新版本你仍会按Cargo.lock中的同一 revision 构建直到你主动运行cargo update。你可以在源码中直接使用该库use regex::Regex; fn main() { let re Regex::new(r^\d{4}-\d{2}-\d{2}$).unwrap(); println!(Did our date match? {}, re.is_match(2014-01-01)); }从 glossary 的 Registry 条目 可以看出注册表是一个包含可下载 crate 集合的服务默认注册表是 crates.io它带有一个 index索引列出所有 crate 并告诉 Cargo 如何下载所需内容。除注册表外Rust 生态还有本地注册表源、目录源、路径源如路径依赖和 Git 源如 Git 依赖等多种 source源。约定让项目一眼可读Cargo 使用文件放置约定让你能快速进入一个陌生的 Cargo 包详见 包布局. ├── Cargo.lock ├── Cargo.toml ├── src/ │ ├── lib.rs │ ├── main.rs │ └── bin/ │ ├── named-executable.rs │ ├── another-executable.rs │ └── multi-file-executable/ │ ├── main.rs │ └── some_module.rs ├── benches/ │ ├── large-input.rs │ └── multi-file-bench/ │ ├── main.rs │ └── bench_module.rs ├── examples/ │ ├── simple.rs │ └── multi-file-example/ │ ├── main.rs │ └── ex_module.rs └── tests/ ├── some-integration-tests.rs └── multi-file-test/ ├── main.rs └── test_module.rs约定要点Cargo.toml和Cargo.lock存放在包的根目录package root。源代码放在src目录默认库文件是src/lib.rs默认可执行文件是src/main.rs其他可执行文件可放在src/bin/。基准测试放benches、示例放examples、集成测试放tests。如果二进制、示例、基准或集成测试由多个源文件组成则在src/bin、examples、benches或tests的子目录中放置main.rs与其他模块可执行文件名取目录名。按惯例binaries、examples、benches 与 integration tests 采用kebab-case命名除非存在兼容性原因其中的模块则按 Rust 标准采用snake_case。配合 Cargo 指南目录 中的后续章节依赖、测试、持续集成、在 crates.io 上发布、Cargo Home、优化构建性能等你会发现从为何存在到如何用好Cargo 始终围绕同一个目标让 Rust 包的声明、获取、构建与分享标准化。小结Cargo 之所以存在是因为真实的 Rust 项目远不止一个文件、一条rustc命令那么简单rustc直接调用需要为每个程序、每组标志、每份依赖手工定制命令无法规模化依赖及其传递依赖的版本管理是手工几乎不可能完成的任务Cargo 用Cargo.toml你写的声明与Cargo.lockCargo 维护的精确快照两个元数据文件实现了可重复构建Cargo 通过自动获取依赖、以正确参数调用rustc或构建工具以及统一的目录约定把构建过程规范化为cargo build/cargo run这样的通用命令。这正是那句略带夸张却不失真谛的总结一旦你学会构建一个 Cargo 项目你就学会构建所有的 Cargo 项目。赞分享开发工具包管理器CLI构建工具【免费下载链接】cargoThe Rust package manager项目地址https://gitcode.com/gh_mirrors/car/cargo点击查看免费下载相关推荐N_m3u8DL-RE跨平台流媒体下载器5分钟搞定加密视频下载与直播录制N_m3u8DL RE跨平台流媒体下载器5分钟搞定加密视频下载与直播录制 N_m3u8DL RE 是一款免费开源的流媒体下载工具能把网页上以 MPD、M3UCLI音视频Rust Cargo包管理终极指南从依赖管理到生态系统演进Rust语言以其出色的包管理系统Cargo而闻名它为开发者提供了简单高效的依赖管理和项目构建体验。作为Rust生态系统的重要组成部分Cargo的持续改进通过文档TypeScript定义管理器从TSD到Typings的演进之路TypeScript定义管理器从TSD到Typings的演进之路 痛点TypeScript类型定义的混乱时代 你是否曾经在TypeScript项目中遇到过这上一篇KindEditor解决企业级富文本编辑需求的5大核心方案下一篇3分钟掌握Windows安卓应用安装器告别模拟器的终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价