cargo 发布配置
release profile
release profile 发布配置,是预定义的,可自定义,可使用不同的配置,对代码编译拥有更多的控制。
每个 profile 的配置都独立于其它的 profile。
cargo 主要的两个 profile:
dev profile适用于开发,cargo buildrelease profile适用于发布,``cargo build --release`
例子:
随便找一个项目,执行 cargo build 控制台会打印 Finished dev [unoptimized + debuginfo] target(s) in 0.04s。执行 cargo build --release 控制台会打印 Finished release [optimized] target(s) in 1.74s。
自定义 profile
针对每个 profile,cargo 都提供了 xxx profile 的配置:可以在 Cargo.toml 里添加 [profile.xxxx] 区域,在里面覆盖默认配置的子集。
例子:
[package]
name = "minigrep"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
[profile.dev]
opt-level = 0
[profile.release]
opt-level = 3
opt-level 是指的优化程度,范围 0~3,dev 下是不进行优化的,release 的时候会进行优化。
对于每个配置的默认值和完整选项可以参考官方文档
发布 crate
crate 官方网站,我们可以通过发布包来共享代码,主要托管开源代码。
发布之前我们先里了解几个与发布相关的比较重要的内容。
文档注释
用于生成 HTML 文档,显示公共 API 的文档注释,使用 /// 标注,支持 Markdown,放置在被说明条目之前。
/// Adds one to the number given
///
/// # Examples
///
/// ```rust
/// let arg = 5;
/// let answer = minigrep::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}
可以使用 cargo doc 命令生成文档,使用 cargo doc --open 生成并使用浏览器打开文档。生成的文档放在 target/doc 路径下。
上面的 Examples 是一个常用章节,表示示例。其它常用章节:
Panics:函数可以发生panic的场景Error:如果函数返回Result,描述可能的错误种类,以及可导致错误的条件Safety:如果函数处于unsafe调用,就应该解释该函数unsafe调用的原因,以及调用者确保的使用前提
文档注释作为测试
使用 cargo test 会对文档注释中的例子进行测试。
为包含注释的项添加文档注释
使用 //! 符号。这类注释通常用来描述 crate 和模块,比如 crate root(按惯例 src/lib.rs)。
或者是在一个模块内,将 crate 或模块作为一个整体进行记录。
//! # Minigrep
//!
//! `some description`
// 省略后面的代码...
pub use
使用 pub use 导出方便使用的公共 API。
可能遇到的问题:crate 的程序结构在开发时对于开发者很合理,但对于它的使用者不够方便。开发者通常会把程序结构分为很多层,使用者想找到这种深层结构中的某个类型很费劲。
例如:my_crate::some_module::another_module::UsefulType。
解决办法:使用 pub use,这样不需要重新组织内部代码结构,又可以重新导出,创建一个与内部私有结构不同的对外公共结构。
创建并设置 Crates.io 账号
发布 crate 前,需要在 crates.io 创建账号并获得 API token。
进入 crate 官网之后首先需要进行登录,可以使用 github 账号登录,然后进入账号设置,取得 API token,然后使用 cargo login [API token] 进行登录。这个命令会通知 cargo 将你的 API token 存储在本地 ~/.cargo/credentials,API token 不要泄露给他人,如果泄露可以去官网进行撤销。另外,还需要设置一个有效的邮箱地址。
crate 发布
在发布 crate 之前,需要在 Cargo.toml 的 [package] 区域为 crate 添加一些元数据:
- name:crate 需要唯一的名称
- description:一两句话即可,会出现在 crate 的搜索结果中
- license:需要提供许可证标识值,例如:
MIT、Apache-2.0等。 可以到 spdx.org/licenses/ 查找。多个 license 之间用OR隔开 - version:版本
- author:作者
最后使用 cargo publish 命令进行发布。
crate 一旦发布,就是永久性的,该版本无法覆盖,代码无法删除,其目的就是保证依赖于该版本的项目可以正常工作。
对于发布已存在的 crate 的新版本,我们只需要修改 Cargo.toml 里面的 version 值,再重新发布即可。可以参考 semver.org/ 来语义版本。
撤回版本
使用 yank 命令可以从 crates.io 撤回版本。
撤回版本不等于删除版本(也不能删除),但可以防止其它项目把它当做新的依赖,已经存在项目可以继续将其作为依赖并可以下载。所有已经产生 Cargo.lock 的项目都不会中断,但是任何将来生成的 Cargo.lock 文件都不会使用被 yank 的版本。
命令举例:cargo yank --vers 1.0.1
取消撤回:cargo yank --vers 1.0.1 --undo
Cargo 工作空间(Workspaces)
cargo 工作空间就是帮助管理多个相互关联且需要协同开发的 crate。
cargo 工作空间是一套共享同一个 Cargo.lock 和输出文件夹的包。
使用一个实例来演示工作空间的创建等操作,实例包含 1 个二进制 crate,2 个库 crate,二进制 crate 的 main 函数,依赖于其它 2 个库 crate。其中一个库 crate 提供 add_one 函数,另一个库 crate 提供 add_two 函数。
创建工作空间
Step1
创建一个新的目录 ADD,在这个目录下创建一个文件 Cargo.toml。
Step2
配置工作空间并添加一个名为 adder 的成员,在 Cargo.toml 中添加:
[workspace]
members = [
"adder"
]
然后进入 ADD 目录去创建 adder 项目(二进制 crate):
cargo new adder
编译:
cargo build
编译之后会生成 Cargo.lock 和 target 目录,target 目录会存放所有成员的产出物,而 adder 下就没有 target 目录了,因为如果各个 crate 都有自己的 target 目录,那么有相互依赖关系的包就会出现反复编译的情况。
Step3
再添加一个成员 add-one,这是一个库 crate:
[workspace]
members = [
"adder",
"add-one",
]
创建:
cargo new add-one --lib
添加代码:
// lib.rs
pub fn add_one(x: i32) -> i32 {
x + 1
}
Step4
配置 adder 的 Cargo.toml,使 adder 依赖于 add-one:
[dependencies]
add-one = { path = "../add-one" }
修改 adder 的代码:
// main.rs
use add_one;
fn main() {
let num = 10;
println!(
"Hello, world! {} plus one is {}!",
num,
add_one::add_one(num)
);
}
编译
cargo build
运行 adder
cargo run -p adder
配置依赖外部 crate
工作空间只有一个 Cargo.lock 文件,在工作空间的顶层目录,这样可以保证工作空间内所有 crate 使用的依赖的版本都相同,也可以使工作空间内所有 crate 相互兼容。
Step5
现在我们把 adder 和 add-one 都加入 rand 这个外部依赖,adder 加入 rand = "0.3.14",add-one 加入 rand = "0.3.15",然后编译。
可以看到 Cargo.lock 中,他们对 rand 的版本统一成了 0.3.23:
[[package]]
name = "add-one"
version = "0.1.0"
dependencies = [
"rand 0.3.23",
]
[[package]]
name = "adder"
version = "0.1.0"
dependencies = [
"add-one",
"rand 0.3.23",
]
Step6
再添加一个成员 add-two,这是一个库 crate:
[workspace]
members = [
"adder",
"add-one",
"add-two",
]
创建:
cargo new add-two --lib
添加代码:
// lib.rs
use rand;
此时执行编译就会报错,因为我们没有将外部依赖 rand 添加到 add-two 的配置中去。
为工作空间添加测试
Step7
在 add-one 中添加测试代码:
// lib.rs
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(3, add_one(2));
}
}
执行测试 cargo test,从结果可以看出,我们执行了工作空间下的所有测试。
如果想要执行某一个 crate 的测试可以使用:cargo test -p add-one。
注意: 工作空间下的 crate,不能批量进行发布,必须手动切换到每个目录下,一个一个使用 cargo publish 进行发布。
安装二进制 crate
从 crates.io 安装二进制 crate,可以使用 cargo install xxx 命令。我们只能安装具有二进制目标(binary target)的 crate,这个二进制目标就是一个可执行程序,由拥有 src/main.rs 或其它被指定为二进制文件的 crate 生成。
通常 README 里面有关于 crate 的描述,比如:拥有哪些 library target;或者是否拥有 binary target。
cargo install 安装的二进制存放在根目录的 bin 文件夹下,如果你用 rustup 安装的 Rust,没有任何自定义配置,那么二进制存放目录是 $HOME/.cargo/bin,要是安装的程序能够执行运行就要确保该目录在 PATH 环境变量中已配置。
使用自定义命令扩展 cargo
cargo 被设计成可以使用子命令来扩展。例如:如果 PATH 中的某个二进制是 cargo-something,你可以像子命令一样运行:cargo something。
类似这样的命令可以通过 cargo --list 列出来。
这样的有点就是可以使用 cargo install 来安装扩展,像内置工具一样运行。