项目结构解析
本教程共 78 篇 · 第 6 篇 · 更新于 2026-08-08 · 约 7 分钟阅读
本节目标:看清 cargo 生成的项目里每个文件和目录是干嘛的,尤其是 Cargo.toml 的配置项和 target 目录的作用。
上一章用 cargo new 一键生成了项目,你大概没细看里面到底有什么。这一章我们把它拆开,搞清楚每个部件的用途。搞明白结构,以后遇到编译产物去哪了、依赖怎么声明,你就不会发懵。
6-1 顶层长什么样
hello_cargo 目录里默认有两样东西:
hello_cargo/
├── Cargo.toml
└── src/
└── main.rs
Cargo.toml 是项目的”说明书”——名字、版本、依赖都写在这。 src/ 是放源码的地方,入口文件 main.rs 已经躺在里面。cargo 约定:所有 .rs 源文件都放在 src 下,根目录只放配置和文档。
Note为什么把源码塞进
src?这是 cargo 的约定优于配置思想:大家都这么摆,工具链和别人一眼就懂。别把.rs文件随便丢在根目录,cargo 不会主动去编译它。
6-2 读懂 Cargo.toml
打开 Cargo.toml,内容大概这样:
[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2024"
[dependencies]
[package] 这一段描述你的项目自身:
name:crate 名,发布到仓库时别人靠它找到你。version:语义化版本号,初始通常是0.1.0。edition:用的 Rust Edition,本教程统一2024。这就是第一章说的”语法方言版本”,写在这就定下了。
[dependencies] 这一段目前是空的,专门用来列你依赖的第三方 crate。以后要用人家的库,就写在这里,比如:
[dependencies]
serde = "1.0"
cargo 会自动去官方仓库 crates.io 下载并管理版本。这就是 Rust 的包管理,比你手动下载 .h / .lib 文件省事太多。
6-3 src 目录与 main.rs
src/main.rs 就是程序入口,里面是 cargo 预先写好的:
fn main() {
println!("Hello, world!");
}
你现在可以打开它改改文字,再 cargo run,就能看到自己的改动生效。这是你和项目互动的最直接入口。
如果你想写库(给别人用、自己不含 main 函数),入口文件叫 src/lib.rs,cargo new --lib 会生成它。bin 项目和 lib 项目在 src 下的入口文件名不同,记住这点即可。
6-4 target 目录:构建产物的家
每次你 cargo build / cargo run,cargo 都会把编译出来的东西放进 target/ 目录。它长这样:
target/
└── debug/
├── hello_cargo (可执行文件)
├── hello_cargo.exe (Windows 上)
└── ...一堆中间文件
debug 是调试构建;加了 --release 会多出一个 target/release/,里面是优化后的成品。
这个目录通常很大、文件很多,而且完全能靠源码重新生成。所以——
Warning
target/千万别手动改里面的文件,也别提交进版本库(git)。它纯粹是编译的副产品,删了重编就会再生。正经项目都会把target/写进.gitignore。你只需知道”产物在这”,不必关心里面的细节。
6-5 Cargo.lock:依赖的锁文件
第一次构建后,根目录还会出现一个 Cargo.lock。它记录了这一次实际用到的每个依赖的精确版本号。
它的作用是”锁版本”:你和同事各 clone 一次项目,即使期间某个依赖发了新版本,Cargo.lock 也能保证两人编出来的结果一致,避免”我这边能跑你那边崩”的惨剧。
- 对二进制应用项目:应该把
Cargo.lock提交进 git,锁定所有人的构建。 - 对**库(lib)**项目:通常不提交,因为库的使用者会自己解析依赖。
Tip刚上手你不用纠结这条规矩。记住
Cargo.lock是 cargo 自动维护的、别手改它,就够了。
6-6 自己加源码文件怎么被编译
你在 src 下新建 src/foo.rs 并写点函数,它不会自动被编进程序。Rust 用 mod 声明模块关系。最简单的办法:在 main.rs 里写 mod foo;,告诉编译器”我有个 foo 模块”。具体的模块机制属于进阶内容,这里先留个印象:源码文件要在 main.rs(或 lib.rs)里通过 mod 串联起来,cargo 才会编译它。
6-7 整体心智模型
把项目想成一家小工厂:Cargo.toml 是营业执照和采购单,src/ 是生产车间(你写代码的地方),target/ 是仓库(堆成品),Cargo.lock 是入库台账。cargo 这个厂长,按 Cargo.toml 的指示,把 src 里的原料加工成 target 里的成品。
理解了这套结构,你再看任何 Rust 开源项目都不会迷路。下一章我们正式进入语言本身,从”变量”这个最基础的概念讲起。
6-8 修改 Cargo.toml 后会发生什么
讲了项目结构,自然要问:当你在 Cargo.toml 的 [dependencies] 里加了一个库,再 cargo build 会发生什么?cargo 会去官方仓库 crates.io 查这个库、下载它及其依赖、编译、写进 Cargo.lock。整个过程自动完成,你不用手动下任何文件。
[dependencies]
rand = "0.8"
加这一行后首次 cargo build,cargo 会拉取 rand 这个随机数库。之后 Cargo.lock 记下精确版本,再构建直接读缓存,又快又稳。target/ 里会多出 rand 的编译产物——你同样不用管它。
Warning版本号
"0.8"是”兼容区间”写法,cargo 会允许0.8.x里的小更新(按语义化版本规则,只更最后一位是兼容的)。想锁死某版本,写成rand = "=0.8.5"(加等号)。新手暂用默认写法即可,知道 cargo 会自动帮你管理依赖版本就行。
Tip想手动更新某个依赖到新版本,用
cargo update -p 库名。它只更新Cargo.lock里的版本,不动你的Cargo.toml。这个项目结构里的每个文件,都是为”自动化依赖管理”服务的。
6-9 最小可运行项目清单
一个”最小可运行项目”到底需要什么?其实就三样:Cargo.toml(告诉 cargo 项目叫啥、啥版本)、src/main.rs(程序入口,含 fn main)、以及一个目录把它们装起来。其余的 target/、Cargo.lock 都是跑起来后自动生成的,你从不需要手写。
Note刚开始你完全不需要理解
Cargo.toml里每个字段。只要知道”名字、版本、edition”这三行是啥意思,其余的等用到依赖时自然会加。Rust 的设计哲学是”最小可用起步,按需扩展”,别被一堆配置吓住。
6-10 工作区与多包预览
当项目变大、拆成多个相关的库时,cargo 还有个”工作区(workspace)“概念:一个顶层目录管多个 crate,共享一个 target/ 和 Cargo.lock,依赖只下载一份。这对中大型项目能显著省时省空间。入门阶段你用不到,但知道 cargo 能从小项目平滑扩展到工作区,心里有底。
Tip你现在写的都是单 crate 小项目,完全不用碰工作区。如果以后看到一个仓库根目录有
Cargo.toml且里面有[workspace]段、下面多个子目录各是独立 crate,那就是工作区结构。理解了”单项目 → 工作区”的演进,你看开源大项目时不慌。
6-11 小结
项目结构里:Cargo.toml 是配置与依赖清单,src/ 放源码、target/ 放构建产物(别提交进 git),Cargo.lock 锁版本。加依赖后 cargo 自动从 crates.io 拉取并编译。理解这套结构,你看任何 Rust 项目都不迷路。下一章进入语言本身,从变量讲起。