13 进一步认识Cargo和crate.io
13.1 修改Cargo.toml默认配置
在我们平时执行cargo build
或者cargo build --release
时(第一个命令开发时使用,第二个用于生产环境),其实Cargo.toml
里面已经替我们使用了默认配置,比如我们执行cargo build
时,Cargo.toml
里面默认执行:
rust
// Cargo.toml
[profile.dev]
opt-level=0
opt-level
的值范围时0-3,值越大表示Rust
为你做的优化越多,也越费时间,当然我们开发是不需要关注打包优化的,只需要编译越快越好,所以它的默认值是0,但是当我们使用--release
时,因为是要构建线上产物,所以它会替我们做最高优化所以opt-level
默认为3。其他的默认配置可以通过这里查询。
13.2 用更好的方式注释
在我们之前,我们对于文档的注释使用//
,但是这样的注释也仅仅是对于包细节的描述,接下我们讲两种其他的注释方式。他们都可以以markdown
语法的方式解析。
13.2.1 //
//~
表示的是对于整个包模块的注释。我们可以在src
下面建立一个lib.rs
文件,然后在文件顶部,写入:
rust
//! # My Crate
//! 仅供学习和参考
然后执行cargo doc --open
我们会发现生成了包名以及这个包的注释
13.2.2 ///
当我们想对于模块中的某个函数或者块进行备注时,我们可以使用///
,它同样可以使用markdown
语法进行解析,并且最厉害的一点是,里面写的用例会被用作单元测试用,当你执行cargo test
时,所有///
里面的用例都会执行。在lib.rs
中,我们来举个例子:
rust
/// 传入值加一
///
/// # 用例
///
/// ```
/// use hello_world::add_one;
/// let y = 2;
/// let result = add_one(1);
/// assert_eq!(result, y)
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}
markdown
里面含有代码块的地方,在执行cargo test
后会被用作测试用例执行,并且执行通过。
13.3 使用pub use导出公共api
在我们之前的学习中,我们可以使用pub
关键字去导出函数、枚举、结构体、模块,但是当别人想想引用包深处的一个函数、枚举、结构体时,需要use crate::xx::xxx::xxx::xx::test
,在我们的文档中,用户很难去找到自己所需要的,这个时候,我们可以使用pub use
将关键的函数等暴露在root
处,用户可以直接看到并且使用,如:
rust
//! # My Crate
//! 仅供学习和参考
pub use self::kinds::Color;
pub mod kinds {
pub enum Color {
Red,
Green,
Blue,
}
}
在我们使用pub use
后,导出的文档会在文档顶部显示。并且,我们在代码中使用时,可以直接use crate::Color
就能使用了。但是这样导出也会有个问题就是,可能会出现同名的类型,这个时候就需要开发者自己控制这种问题的出现。
13.4 将包发布在crates.io
这一小节我们主要讲讲怎么讲我们写好的包发到crates.io上面分享给其他的开发者使用。
13.4.1 在crates.io上面登录获取API Token
首先,我们需要在crates.io登录账号,目前它只支持github账号登录,登陆成功后,在头像处,我们进入,Account Setting,然后生成一个API TOKEN,接下来我们先创建一个包。
13.4.2 配置一个发布包
我们先生成一个新的库包,使用命令cargo new learn-rust-publish
,然后我们在github上面建立一个仓库,然后在我们的项目中执行git init -y
,然后使用git remote add origin 你的仓库地址
将项目和远程地址管理起来,将代码初始化到仓库中,后续在发布前也需要将代码更新到仓库中,再执行发布流程。
13.4.2.1 为包添加元数据
打开项目,进入到Cargo.toml
中,在[package]
中配置元数据信息,如下:
rust
[package]
# 创建项目默认添加
name = "learn-rust-publish"
version = "0.1.0"
edition = "2021"
# 需要添加
email = "your email"
description = "learn how to publish rust library"
license = "MIT OR Apache-2.0"
repository = "https://github.com/1847016090/learn-rust-publish"
其中前三项是创建项目时默认生成的,我们只需要添加后面几项即可。
13.4.2.2 登录 & 发布
然后我们先来执行cargo login
命令执行登录,然后将我们刚才生成的API TOKEN填入即可登录成功。我们接着再执行cargo publish
,发现如下报错:
rust
the remote server responded with an error: A verified email address is required to publish crates to crates.io. Visit https://crates.io/settings/profile to set and verify your email address.
我们需要跟随着链接去验证一下我们的邮箱即可。验证完后,再执行cargo publish
就能成功发布我们的包了(我发布的包)。
13.4.2.3 撤销或重新发布新版本包
当我们发布了一个版本的包之后,我们就不能再次覆盖这个包了。但是我们使用cargo yank --vers 0.1.0
撤销当前版本的包(只针对新包。如果有项目已经安装了当前版本的包,Cargo.lock文件已经存在当前版本,他依旧可以继续使用当前版本的包)。
当然,如果我们想取消撤销,我们执行cargo yank --vers 0.1.0 --undo
就行。
如果我们想发布新的版本,我们只需要修改我们Cargo.toml
文件中的version
字段即可
13.5 使用工作空间管理多个包
如果我们有多个包需要管理,那我们应该怎么去管理呢?这就涉及到工作空间了。
13.5.1 创建一个新的工作空间目录
我们首先心建立一个空文件夹mkdir rust-workspace-library && cd mkdir rust-workspace-library
,然后我们按照刚才的步骤将它和远程仓库关联地址
13.5.2 创建工作空间并且创建一个二进制包和一个库包
我们在空的文件夹中先创建一个Cargo.toml
文件,并且在里面填写:
rust
[workspace]
members=['adder', 'add_one']
这时候已经建立了工作空间了。然后我们使用cargo new adder
和cargo new add_one --lib
命令分别创建二进制包和库包。 这个时候我们的基本目录已经创建完成。
13.5.3 改造代码
然后我们进入add_one
中lib.rs
文件将写一个简单函数以及他的测试函数:
rust
pub fn add_one(num: i32) -> i32 {
num + 1
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
let result = add_one(2);
assert_eq!(result, 3);
}
}
然后我们进入adder
中Cargo.toml
文件中将add_one
引入进来:
rust
[dependencies]
add_one = { path = '../add_one' }
然后再进入main.rs
使用add_one
里面的函数:
rust
use add_one::add_one;
fn main() {
let num = add_one(10);
println!("result = {}", num);
}
然后使用cargo run -p adder
执行,成功打印!这里-p
的意思是,指定某个目录去单独执行。我们也可以但是测试某个包,比如:cargo test -p add_one
,我们会发现我们刚刚添加的测试用例也跑过了。
注意: 使用工作空间建立包,某个包都需要单独发布,不能一起发布。