blog
blog copied to clipboard
Cargo
概述
Cargo 做了4件事情:
- 引入两个包含项目的各种信息元数据文件
- 拉取、构建项目的依赖(默认从crates.io上拉)
- 构建项目,使用正确的参数调用
rustc
或其它构建工具 - 生成约定俗成的文件目录,以便轻松入门 Rust 项目
cargo new hello_test --bin # --bin 意思是 binary,即二进制项目,比如库文件
cd hello_test
tree .
cargo build # 获取依赖及其子依赖,编译它们,更新 Cargo.lock
./target/debug/hello_test # hello_test 是个二进制文件
cargo run # 和以上2条命令等价。会自动检测-如果已编译过&文件未改变,则就不重新编译了
cargo build --release # 会放在文件夹 ./target/release 下
cargo check # 快速(检查)编译,但不生成可执行文件
cargo update # 更新所有依赖
cargo update -p rand # 仅更新"rand"依赖
eg.
-
Cargo.toml
描述项目的依赖 -
Cargo.lock
由Cargo自动生成,不用手动修改- 如果构建其它项目依赖的库,那可将
Cargo.lock
放在.gitignore
里 - 如果构建一个可执行的应用程序或者命令行工具,记得把
Cargo.lock
放在git
的版本仓库里
- 如果构建其它项目依赖的库,那可将
eg. 来自 crates.io
-
semver
语义的版本解析和比较 -
semver-parser
解析semver规范 -
rustc_version
查询已安装的rustc编译器版本 -
libc
类型和绑定到本地C函数的库,通常是在libc或其他通用平台的库中
eg. 生成的目录结构
-
Cargo.toml
和Cargo.lock
在项目的根目录 -
src
放源码-
src/lib.rs
默认的库文件 -
src/main.rc
默认的可执行文件 -
src/bin/*.rs
其它的可执行文件
-
-
test
-
examples
-
benches
eg. 关于测试的
cargo test # 会寻找两个地方,每个`src`文件和`tests/`目录
cargo test foo # 将会运行名字里带有foo的所有测试
# 更多见 https://doc.rust-lang.org/book/testing.html
命令“cargo test”运行测试用例,寻找两个地方的:
- 每个
src
文件,单元测试 - 在
tests/
目录下的,集成测试- 可以用 Travis CI,
.travis.yml
- 也可以用 GitLab CI,
.gitlab-ci.yml
- 可以用 Travis CI,
eg.构建缓存
- 在单个工作区里,Cargo 会在诸多包之间共享构建工件
- 在不同的工作区里,Cargo不共享
- 若还想共享,则可以用第三方工具sccache
https://doc.rust-lang.org/cargo/guide/index.html
补充
- 绝大多数 Rust 项目都使用 Cargo。当项目变大时,需要控制各个方面,单纯的
rustc
编译就不方便了 - cargo 还有个好处,可以抹平不同操作系统的差异,都用一样的命令
cargo build # 开发-快速构建
cargo build --realease # 发布-快速运行
.toml
, Tom's Obvious, Minimal Language, 作者是 Tom Preston-Werner toml
依赖的来源
- crates.io
- git 仓库
- 覆盖依赖,eg.调试bug,临时覆盖依赖项的位置
- 覆盖仓库的url,eg.发布之前
- 本地文件夹,路径依赖,路径相对于
Cargo.toml
eg.
[dependencies]
time = "0.1.12"
rand = { git = "https://github.com/rust-lang-nursery/rand" }
## 先把那个crate的仓库clone到本地。比如 uuid
[patch.crates-io]
uuid = { path = "../path/to/uuid" }
[patch."https://github.com/your/repository"]
my-library = { path = "../my-library/path" }
-
[patch.crates-io]
声明我们用新的依赖项修补源crates-io
,这将把uuid添加到本项目的crates.io注册表中 - 签出的>=之前指定的就行:本地签出的版本号很重要,将会影响是否使用patch(不定)
- 运行
cargo build
则会看到file://...
说明则已经用了本地的副本了 - 否则,需要运行
cargo update -p uuid --precise $version
$version是本地签出的版本
- 运行
eg. 本地文件夹,用.cargo/config而不是Cargo.toml
paths = ["/path/to/uuid"]
版本指定
比如 ~ * >= <= = 等,符合 semver 要求,详见 Caret requirements
灵活适配
# 针对不同平台,[target.]
[target.'cfg(windows)'.dependencies]
winhttp = "0.4.0"
[target.'cfg(unix)'.dependencies]
openssl = "1.0.1"
[target.'cfg(target_arch = "x86")'.dependencies]
native = { path = "native/i686" }
[target.'cfg(target_arch = "x86_64")'.dependencies]
native = { path = "native/x86_64" }
[target.x86_64-pc-windows-gnu.dependencies]
winhttp = "0.4.0"
[target.i686-unknown-linux-gnu.dependencies]
openssl = "1.0.1"
# 开发依赖
[dev-dependencies]
tempdir = "0.3"
# 构建依赖
[build-dependencies]
cc = "1.0.3"
# 选择功能 [features],如果依赖的包提供条件功能
[dependencies.awesome]
version = "1.3.5"
default-features = false
features = ["secure-password", "civet"]
指定依赖项:https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html
Manifest 格式
- [package] 基本信息
-
build
根目录下的文件,构建项目的构建脚本。详见 Build Scripts -
publish
可防止包被错误地发布到包注册表,比如 crates.io -
workspace
配置 workspace。若没指定,则会向上找,直到找到第一个 Cargo.toml
-
- [lib]
-
name
要生成的库名称- 所有的破折号
-
都会替换成下划线_
- 必须是有效的 Rust 标识符,因为
extern crate
引用的就是它
- 所有的破折号
-
path
即 crate 所在的位置,相对于 Cargo.toml -
doctest
布尔值,是否启动文档测试- 仅适用于库,对其它部分(section)没影响
- 当
cargo test
时,会用它
-
- [features]
- 条件编译选项,会用到
cfg
属性 - 可选的依赖项
- 条件编译选项,会用到
https://doc.rust-lang.org/cargo/reference/manifest.html