Rust 项目文件组织方式
2024-11-10 16:54:25

基本概念

Rust 语言在项目管理上整了一套自己的名词workspacepackagecratemodule。特别是crate,很多刚入门的人搞不清它们之间的关系。
如果用过 Visual Studio 开发过项目,那么就可以这么理解:

Visual Studio Rust 说明
Solution workspace 管理多个项目
Project package 一个项目
crate 可编译的单元
namespace module 组织代码


区别从crate这里开始,在 VS 中,一个Project对应一个可编译的单元(exe、dll、lib),但是在 Rust 中多出了一个crate的概念,它表示一个可编译的单元(exe、dll、lib、rlib),也就是说在 Rust 中一个项目可以编译出多个文件
但是有个限制,每个项目(package)可以有多个可执行文件(exe)的crate,但是最多只能有一个lib类型的crate

项目的目录结构

不如直接看看各种可能的目录结构。

单个可执行文件

当我们从cargo new命令创建项目(package)后,默认的目录结构是这样:

1
2
3
Cargo.toml
src/
└── main.rs

main.rs就是入口文件,最终生成一个可执行文件。

单个库文件

当我们从cargo new --lib命令创建项目(package)后,默认的目录结构是这样:

1
2
3
Cargo.toml
src/
└── lib.rs

库文件默认是.rlib格式,是 Rust 特有的格式,第三方包就是用这种格式。也可以改为静态库.lib或动态库.dll

一个可执行文件和一个库文件

1
2
3
4
Cargo.toml
src/
├── main.rs
└── lib.rs

这样最终会编译出一个.exe文件和一个.rlib文件。

多个可执行文件

Rust 规定,在src/bin这个目录下的每个文件都是一个可编译的可执行文件。

1
2
3
4
5
6
Cargo.toml
src/
├── main.rs
└── bin/
├── app2.rs
└── app3.rs

这样在编译后会生成出:

1
2
3
4
5
target/
└── debug/
├── app1.exe
├── app2.exe
└── app3.exe

第一个app1.exe就是顶层main.rs编译出的文件,默认用包名命名。
如果在src/bin目录下用一个和包名同名的文件会如何呢?会编译失败:

1
2
Caused by:
found duplicate binary name app, but all binary targets must have a unique name

多个库文件

在一个项目(package)中能编译多个库吗?不行,Rust 只会将lib.rs文件作为库编译,没有像src/bin这种特殊的约定。

workspace

上面提到,一个项目最多只能有一个库文件,但在实际中,一个项目肯定有很多库文件,那么就不能用一个package来管理项目了,需要使用workspace的概念。
就是新建一个根目录加一个Cargo.toml文件即可:

1
2
3
4
5
6
workspace/
├── Cargo.toml
├── app1/
├── app2/
├── lib1/
└── lib2/

这样就创建了两个可执行文件,两个库。根目录下创建Cargo.toml文件,内容如下

1
2
3
4
5
6
7
[workspace]
members = [
"app1",
"app2",
"lib1",
"lib2"
]

现在所有项目都会在根目录下生成二进制文件,

总结

  • package就是项目的概念,可以包含多个可编译的单元(crate)。其中可执行文件可以有任意多个,入口main.rs文件和src/bin目录下的所有文件。但库类型的编译只允许有一个,入口文件是lib.rs
  • 项目中如果需要多个库文件时,则要引入workspace的概念,对应 Visual Studio 中的解决方案。

相关阅读

工作空间 Workspace
What are packages, crates and modules?
Rust包和模块系统