本节内容只介绍Cargo的基本使用,以满足后面学习的需要。
使用cargo创建工程
Cargo是Rust语言的包管理器。Cargo下载Rust包的依赖项,编译包,生成可分发包,并将它们上传到crates.io(Rust社区的包仓库) 。
Rustup安装Rust环境时,就包含了cargo
,可以使用cargo -V
检测cargo是否可用。
Cargo使Rust中在工程层面区分了可执行文件和库,在使用Cargo创建crate时可以指定参数bin
或lib
以区分二者。crate是Rust中的package,他的概念类似js中的npm包或java中的maven包。lib类型的crate可以作为bin或者其它lib类型的依赖引入到项目中。
现在我们使用命令来分别创建这两种类型的crate:
shell
# 创建可执行类型的项目
cargo new oskwgbin --bin
# 创建库类型的项目
cargo new oskwglib --lib
两种类型的基础目录结构如下,
css
├─oskwgbin
│ │ .gitignore
│ │ Cargo.toml
│ └─src
│ main.rs
│
└─oskwglib
│ .gitignore
│ Cargo.toml
└─src
lib.rs
两种类型的项目唯一的区别是编译入口文件名不同,bin类型的是main.rs,lib类型的则是lib.rs。
真实项目目录结构不会这么简单,我们需要看一个完整案例的目录结构是如何安排的。
工程目录结构
下面是Rust推荐的目录结构:
css
.
├── build.rs
├── Cargo.lock
├── Cargo.toml
├── build.rs
├── 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是项目的配置文件,同时它必须位于项目的根目录下。
- build.rs 在构建源码前,先运行该程序。例如:代码生成。
- src是项目源码目录。其中的src/lib.rs是库项目特有的,src/main.rs是可执行文件项目特有的,如果有其它的可执行文件可以放到src/bin目录下面。
- benches 目录存放基准测试文件。
- examples 目录存放代码示例。
- tests 目录存放集成测试文件的目录。
Cargo配置文件
Cargo.toml文件在crate中是。
介绍toml格式
toml格式是一种配置文件,与json、xml、yaml等配置格式类似,它可以表示数字、字符串、数组等类型。
作者声称有如下特点:
- 语义明显易于阅读
- 能无歧义地映射为哈希表
- 易于解析成各种语言中的数据结构
对于一种声称配置文件格式的DSL,最值得我们关注的就是它如何表示基本类型。
toml
1. 注释
# 这是一条 TOML 注释
2. 字符串
# 基本字符串
str1 = "hello"
# 字面量
str2 = 'world'
# 多行基本字符串
str3 = """hello
world"""
# 多行字面量字符串
str4 = '''hello
world
'''
3. 数字
int1 = 1
hex1 = 0xABAB
float1 = 3.14
4. 数组
intArray = [1,2,3]
strArray = ['a','b','c']
5. 表与内联表
[name]
first = "Tom"
last = "Preston-Werner"
[point]
x = 1
y = 2
[animal]
type.name = "pug"
# 将上面的表使用等价的内联表表示
name = { first = "Tom", last = "Preston-Werner" }
point = { x = 1, y = 2 }
animal = { type.name = "pug" }
6. 表数组
[[fruits]]
name = "apple"
# 等价的JSON结构
{
"fruits": [
{
"name": "apple"
}
]
}
可以访问TOML中文网进阶学习 toml.io/cn/
常用配置选项
由于Cargo非常功能较多,因此配置也极为复杂,不过好在常用的配置项比较固定,下面我们只介绍常用的配置选项。
ini
[package]
name = "helloworld"
version = "0.1.0"
edition = "2021"
[dependencies]
pkg_name = "0.1.0"
每个crate都有一个package表,package下面常用的属性有 name表示crate的名称,version表示crate的版本,edition表示使用的Rust规范是哪个版本。dependencies表示crate依赖了哪些crate,在运行或构建项目时会从网络上下载依赖包,其中pkg_name就是依赖包名称,"0.1.0"就是依赖包的版本。三方依赖包通常托管在crates.io,我们可以从仓库中搜索需要的依赖在项目中使用。
常用的cargo子命令说明
除了cargo new
还有一些指令,方便我们操作项目。
shell
cargo new # 创建项目
cargo run # 运行项目
cargo build # 构建项目
cargo clean # 清理构建
cargo doc # 利用文档生成文件
cargo test # 运行单元测试和集成测试代码
构建后产生了什么
当我们执行cargo build
后,会在根目录下生成一个target文件夹。默认是debug模式下构建一个可执行文件或库,如果添加--release
则以release模式构建。我们以一个可执行文件为例,看一下项目构建后生成了哪些内容。
python
└─target
│ .rustc_info.json
│ CACHEDIR.TAG
│
├─debug
│ │ .cargo-lock
│ │ helloworld.d
│ │ helloworld.exe
│ │ helloworld.pdb
│ │
│ ├─.fingerprint
│ │ └─helloworld-1a74b84bc6952173
│ │ bin-helloworld
│ │ bin-helloworld.json
│ │ dep-bin-helloworld
│ │ invoked.timestamp
│ │
│ ├─build
│ ├─deps
│ │ helloworld.d
│ │ helloworld.exe
│ │ helloworld.pdb
│ │
│ ├─examples
│ └─incremental
│ └─helloworld-1a33b6wbbi9ss
│ │ s-gss72k21aw-10hgpc3.lock
│ │
│ └─s-gss72k21aw-10hgpc3-7mz55f0sfn6hhne4vxrtfg6bz
│ 1m145qd8oexia6nc.o
│ 33ejn18tv7hxpbbm.o
│ 3eq1bfsgiu76y9j4.o
│ 3pfsb6ncovzingc4.o
│ 4mkqlt86552igoa9.o
│ 53eh6dzk21xnjl9a.o
│ dep-graph.bin
│ query-cache.bin
│ work-products.bin
│
└─release
│ .cargo-lock
│ helloworld.d
│ helloworld.exe
│ helloworld.pdb
│
├─.fingerprint
│ ├─helloworld-1a74b84bc6952173
│ │ bin-helloworld
│ │ bin-helloworld.json
│ │ dep-bin-helloworld
│ │ invoked.timestamp
│ │
│ └─json-f2a97d7a00cb1931
│ dep-lib-json
│ invoked.timestamp
│ lib-json
│ lib-json.json
│
├─build
├─deps
│ helloworld.d
│ helloworld.exe
│ helloworld.pdb
│ json-f2a97d7a00cb1931.d
│ libjson-f2a97d7a00cb1931.rlib
│ libjson-f2a97d7a00cb1931.rmeta
│
├─examples
└─incremental
我们分别执行了cargo build
和cargo build --release
,在target目录下也产生了debug和release文件夹。构建命令会编译执行测试,用例,基准测试和依赖的其它crate等,并且每次执行都会增量编译,以提高编译速度。 在debug目录下生成了可执行文件,deps下是依赖的crate以及crate本身,examples是示例,incremental是增量编译目录。
关于Cargo还有很多内容可以说,不过上面这些内容已经足够应付日常开发和后续课程的理解,更多内容我希望在Cargo专题中在介绍。