标题
- 一、采用发布配置自定义构建
- 1.1 默认配置
- 1.2 修改配置项
- 二、将crate发布到Crates.io
- 2.1 编写文档注释
- 2.2 常用(文档注释)部分
- 2.3 文档注释作用测试
- 2.4 为包含注释的项添加文档注释
- 2.5 使用pub use导出公有API
- 2.6 创建Crates.io账号
- 2.7 发布
- 2.8 版本撤回
- 三、Cargo工作空间
- 3.1 创建工作空间
- 3.2 在工作空间中依赖外部crate
- 3.3 为工作空间增加测试
- 四、其它
- 4.1 从Crates.io安装二进制文件
- 4.2 自定义扩展命令
一、采用发布配置自定义构建
1.1 默认配置
- 可以通过**发布配置(release profiles)**定制带有不同选项的配置,且每个配置都彼此相互独立;
- Cargo有两个主要配置:运行cargo build时采用的
dev配置
和cargo build --release的release配置
(如下图); - dev配置是开发时的默认配置,release配置则是发布构建的默认配置;
1.2 修改配置项
- 在
Cargo.toml
可以通过[profile.*]
对应项中修改默认值;
[profile.dev]
opt-level = 0
[profile.release]
opt-level = 3
opt-level
控制编译器对源码的优化程序,其值域为[0,3]
,越高的优化级别需要更多的时间编译;dev
的默认级别为0,release
的默认级别为3;- 更多的相关配置项请参阅文档;
二、将crate发布到Crates.io
- 可以通过发布包来共享自己的代码;
- crate的注册表在https://crates.io,它托管代码并分发已经注册的包的源代码;
2.1 编写文档注释
- 文档注释可以直接生成HTML文档;
- 文档注释使用
三斜杠
注释; - 文档注释支持使用Markdown语法;
- 文档注释位于被说明条目之前;
以下面的代码采用文档注释 (放于lib.rs中)
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = minigrep::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
x + 1
}
- 使用命令cargo doc --open会构建当前文档以及所有crate依赖的文档并在浏览器中打开;
- 生成的文档会存在到本地的target/doc目录下;
- 点击add_one就可以看到编写的注释,里面显示的Markdown注释的部分
2.2 常用(文档注释)部分
# Examples
是Markdown中创建了标题部分,其他在文档注释中常见的还有
- Panic:函数可能会panic! 的场景;
- Errors:如果这个函数返回 Result,此部分描述可能会出现何种错误以及什么情况会造成这些错误;
- Safety:如果这个函数使用unsafe 代码,就该解决函数unsafe的原因,以及调用者确保的使用前提;
2.3 文档注释作用测试
cargo test也能运行文档中的示例代码
- 运行命令
cargo test
会看到Doc-tests
的运行结果。
2.4 为包含注释的项添加文档注释
- 使用
//!
为外层条目添加注释; - 通常用于crate根文件(通常是src/lib.rs)或模块的根文件,为create或模块整体提供文档;
- 在刚刚的文件最上边添加下面几行;
//! # minigrep Crate
//!
//! `minigrep` is a collection of utilities to make performing certain
//! calculations more convenient.
- 然后执行
cargo doc --open
,可以看到网页有了变化;
2.5 使用pub use导出公有API
前面说明了
- 使用mod关键字将代码组织到模块中;
- 使用pub关键字将项变为公有;
- 使用use关键字将项引入作用域;
问题
- crate的程序结构在开发时方便,在它的使用者使用时不方便(比如层数过深)
- 诸如
my_crate::some_module::another_module::UsefulType;
而不是use my_crate::UsefulType;
解决方案
- 使用
pub use
进行重导出(re-export)项; - 重导出获取位于一个位置的公有项并将其公开到另一个位置;
举例
下面描述了描述美术信息的art库
src/lib.rs
//! # Art
//!
//! A library for modeling artistic concepts.
pub mod kinds {
/// The primary colors according to the RYB color model.
pub enum PrimaryColor {
Red,
Yellow,
Blue,
}
/// The secondary colors according to the RYB color model.
pub enum SecondaryColor {
Orange,
Green,
Purple,
}
}
pub mod utils {
use crate::kinds::*;
/// Combines two primary colors in equal amounts to create
/// a secondary color.
pub fn mix(c1: PrimaryColor, c2: PrimaryColor) -> SecondaryColor {
SecondaryColor::Orange
}
}
main.rs
use art::kinds::PrimaryColor;
use art::utils::mix;
fn main() {
let red = PrimaryColor::Red;
let yellow = PrimaryColor::Yellow;
mix(red, yellow);
}
问题
- 查看它的文档首页中,枚举类型并没有出现,必须要点击下面的
kinds
才会显示;
main.rs
中依赖这个库的crate需要use语句来导入art中的项;- 使用者必须知道
PrimaryColor
和mix
的具体位置才能导入,而具体位置对使用者来说是没有意义的;
解决方案
- 在
src/lib.rs
中的最上面增加pub use
语句来重导出到顶层结构
//! # Art
//!
//! A library for modeling artistic concepts.
pub use self::utils::mix;
pub use self::kinds::PrimaryColor;
pub use self::kinds::SecondaryColor;
- 如此一来,对于
main.rs
的使用也可以改为
// use art::kinds::PrimaryColor;
// use art::utils::mix;
use art::PrimaryColor;
use art::mix;
- 重新生成一下文档,可以看到枚举类型出现在了主页;
2.6 创建Crates.io账号
- 在crates.io上注册账号并获取一个API token;
- 网站需要用Github账户登录;
- 登录成功后进入Account Settings页面;
- 选择左边的
API Tokens
,然后选择New Token
。
- 填入信息后单击"Generate Token“
- 然后复制这一串生成的token;
- 使用
cargo login 复制的token
将token存储在本地;
注意:前面如果换了源则这里可能不成功,需要先将之前的文件换个名称或删除 (文件位置:C:\Users\xxx.cargo\config.toml) ,下面就是删除前后的登录结果;
2.7 发布
- 在发布新crate之前需要在Cargo.toml文件的
[package]
中添加一些元信息;
[package]
name = "唯一的名称"
version = "0.1.0"
authors = ["Your Name <you@example.com>"]
edition = "2018"
description = "一句话描述"
license = "MIT OR Apache-2.0"
- 使用
cargo publish
命令发布,根据错误信息修改; - 一旦发布就是永久性的,版本无法覆盖,代码无法删除;
- 要重新发布则修改Cargo.toml中version的值,再重新发布;
2.8 版本撤回
- 撤回功能并不会删除任何代码;
- 使用
cargo yank
可以撤回需要的版本,如cargo yank --vers 1.0.1
; - 也可以取消撤回,如
cargo yank --vers 1.0.1 --undo
; - 是为了防止新项目依赖于该版本;
- 已经存在的项目可继续将其作为依赖并可下载;
三、Cargo工作空间
- 工作空间的作用是帮助管理多个相互关联且需要协同开发的crate;
- cargo工作空间是一套共享同一个Cargo.lock和输出文件夹的包;
3.1 创建工作空间
当前的工作空间中有一个二进制和两个库crate;
- 创建文件夹add并进入;
- 在add目录中创建Cargo.toml文件,它以
[workspace]
部分作为开始; - 假设要加入一个二进制crate,其名称为
adder
,则Cargo.toml的内容为
[workspace]
members = [
"adder",
]
- 然后在add目录下执行
cargo new adder
命令,则最终的目录结构如下
- 现在可以在add目录下使用
cargo build
构建工作空间; - 再新建一个库crate,名称为
add-one
, 则Cargo.toml的内容变为
[workspace]
members = [
"adder",
"add-one",
]
- 再在add目录下执行
cargo new add-one --lib
命令创建,此时目录结构变为
- 将
add-one/src/lib.rs
的内容变为
pub fn add_one(x: i32) -> i32 {
x + 1
}
- 让adder依赖于库add-one,需要在
adder/Cargo.toml
文件中添加依赖路径;
[dependencies]
add-one = {path = "../add-one"}
- 要在adder中使用add-one中的add_one函数,则将adder/src/main.rs文件修改为
use add_one;
fn main() {
let num = 10;
println!("Hello, world! {} plus one is {}!", num, add_one::add_one(num));
}
- 然后使用
cargo build
可以正确的构建工作空间; - 在顶层add目录运行二进制crate,需要通过-p加包名称来运行,
cargo run -p adder
;
3.2 在工作空间中依赖外部crate
- 工作空间只有根目录有一个Cargo.lock;
- 不同的crate中添加同一个包的不同版本,会被最终解析成同一版本并记录到Cargo.lock中;
- 不同crate要使用同一个包,必须在当前crate中的Cargo.toml中声明;
3.3 为工作空间增加测试
- 为add_one函数增加测试
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn it_works() {
assert_eq!(3, add_one(2));
}
}
- 在顶级add目录中运行
cargo test
会运行工作空间中所有crate的测试;
- 可以在根目录使用-p参数指定crate名称
- 如果发布工作空间中的crate,则工作空间中的每一个crate都要单独发布;
- 因此必须进入每一个crate目录并运行
cargo publish
发布每一个crate;
四、其它
4.1 从Crates.io安装二进制文件
cargo install
用于在本地安装和使用二进制crate;- 所有安装的文件都放到安装
根目录的bin文件夹
或$HOME/.cargo/bin
中; - 如安装搜索文件的grep的Rust实现
cargo install ripgrep
4.2 自定义扩展命令
- cargo可以使用子命令扩展;
- 如果某个二进制是cargo-sth,则可以
cargo sth
运行; - 使用
cargo --list
列出所有自定义命令; - 这样就可以使用cargo install安装扩展,像内置工具一样运行;