Rust入门(十):项目发布

发布配置

在 Rust 中 发布配置是预定义的、可定制的带有不同选项的配置,他们允许程序员更灵活地控制代码编译的多种选项。

运行 cargo build 发布时采用的 dev 配置,其更适合开发。

运行 cargo build --release 时采用 release 配置,其是更适合发布。

$ cargo build
    Finished dev [unoptimized + debuginfo] target(s) in 0.0s
$ cargo build --release
    Finished release [optimized] target(s) in 0.0s

当项目的 Cargo.toml 文件中没有任何 [profile.*] 部分的时候,Cargo 会对每一个配置都采用默认设置。通过增加任何希望定制的配置对应的 [profile.*] 部分,我们可以选择覆盖任意默认设置的子集。例如,如下是 devrelease 配置的 opt-level 设置的默认值:

[profile.dev]
opt-level = 0

[profile.release]
opt-level = 3

opt-level 设置控制 Rust 会对代码进行何种程度的优化,越高的优化级别需要更多的时间编译。我们可以选择通过在 Cargo.toml 增加不同的值来覆盖任何默认设置。

[profile.dev]
opt-level = 1

文档注释

Rust 也有特定的用于文档的注释类型,通常被称为文档注释(documentation comments),他们会生成 HTML 文档。文档注释使用三斜杠 /// 而不是两斜杆以支持 Markdown 注解来格式化文本。文档注释就位于需要文档的项的之前。示例 14-1 展示了一个 my_crate crate 中 add_one 函数的文档注释,

/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = my_crate::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}

运行 cargo doc --open 会构建当前 crate 文档的 HTML 并在浏览器中打开

Rust入门(十):项目发布_第1张图片

示例中使用了 # Examples Markdown 标题在 HTML 中创建了一个以 “Examples” 为标题的部分。其他一些 crate 作者经常在文档注释中使用的部分有:

  • Panics:这个函数可能会 panic! 的场景。并不希望程序崩溃的函数调用者应该确保他们不会在这些情况下调用此函数。
  • Errors:如果这个函数返回 Result,此部分描述可能会出现何种错误以及什么情况会造成这些错误,这有助于调用者编写代码来采用不同的方式处理不同的错误。
  • Safety:如果这个函数使用 unsafe 代码,这一部分应该会涉及到期望函数调用者支持的确保 unsafe 块中代码正常工作的不变条件(invariants)。

在文档注释中增加示例代码块是一个清楚的表明如何使用库的方法,这么做还有一个额外的好处:cargo test 也会像测试那样运行文档中的示例代码

Doc-tests my_crate

running 1 test
test src/lib.rs - add_one (line 5) ... ok

test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.27s

还有另一种风格的文档注释,//!,这是包含注释的项,通常为模块整体提供文档。

//! # My Crate
//!
//! `my_crate` is a collection of utilities to make performing certain
//! calculations more convenient.

/// Adds one to the number given.
// --snip--

如果运行 cargo doc --open,将会发现这些注释显示在 my_crate 文档的首页,位于 crate 中公有项列表之上,使用他们描述其容器整体的目的来帮助 crate 用户理解你的代码组织:

Rust入门(十):项目发布_第2张图片

pub use

鉴于你的项目结构可能是一个包含多个层级的分层结构,这对于用户来说并不方便。你可以选择使用 pub use 重导出(re-export)项来使公有结构不同于私有结构。如下:假设我们创建了一个描述美术信息的库 art。这个库中包含了一个有两个枚举 PrimaryColorSecondaryColor 的模块 kinds,以及一个包含函数 mix 的模块 utils

//! # 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 {
        // --snip--
    }
}

使用 art crate 代码的作者不得不搞清楚 PrimaryColor 位于 kinds 模块而 mix 位于 utils 模块。为了从公有 API 中去掉 crate 的内部组织,增加 pub use 语句来重导出项到顶层结构:

//! # Art
//!
//! A library for modeling artistic concepts.

pub use self::kinds::PrimaryColor;
pub use self::kinds::SecondaryColor;
pub use self::utils::mix;

pub mod kinds {
    // --snip--
}

pub mod utils {
    // --snip--
}

现在此 crate 由 cargo doc 生成的 API 文档会在首页列出重导出的项以及其链接,这使得 PrimaryColorSecondaryColor 类型和 mix 函数更易于查找,点击函数就可以直接跳转到对应属性或者函数的定义界面,使用 pub use 将类型重导出到顶级结构对于使用 crate 的人来说将会是大为不同的体验。

Rust入门(十):项目发布_第3张图片

发布crate

在你可以发布任何 crate 之前,需要在 crates.io 上注册账号并获取一个 API token,接着使用该 API token 运行 cargo login 命令,这个命令会通知 Cargo 你的 API token 并将其储存在本地的 ~/.cargo/credentials 文件中:

cargo login 你的token

你需要在 crate 的 Cargo.toml 文件的 [package] 部分增加一些本 crate 的元信息(metadata)。

  • 首先 crate 需要一个唯一的名称。一旦某个 crate 名称被使用,其他人就不能再发布这个名称的 crate 了。
  • license 是关于该 crate 用途的描述和用户可能在何种条款下使用该 crate 的 license。可以设置多个许可,他们使用 OR 隔开

有了唯一的名称、版本号、由 cargo new 新建项目时增加的作者信息、描述和所选择的 license,已经准备好发布的项目的 Cargo.toml 文件可能看起来像这样:

[package]
name = "guessing_game"
version = "0.1.0"
edition = "2021"
description = "A fun game where you guess what number the computer has chosen."
license = "MIT OR Apache-2.0"
[dependencies]

发布 crate是永久性的。对应版本不可能被覆盖,其代码也不可能被删除,运行 cargo publish 命令可以完成你的发布:

cargo publish
    Updating crates.io index
   Packaging guessing_game v0.1.0 (file:///projects/guessing_game)
   Verifying guessing_game v0.1.0 (file:///projects/guessing_game)
   Compiling guessing_game v0.1.0
(file:///projects/guessing_game/target/package/guessing_game-0.1.0)
    Finished dev [unoptimized + debuginfo] target(s) in 0.19s
   Uploading guessing_game v0.1.0 (file:///projects/guessing_game)

至此,发布完成了,其他用户可以在社区下载刚刚发布的内容。

撤回版本

撤回某个版本会阻止新项目开始依赖此版本,不过所有现存此依赖的项目仍然能够下载和依赖这个版本。可以运行 cargo yank 并指定希望撤回的版本来完成这个操作:

$ cargo yank --vers 1.0.1

工作空间

Cargo 提供了一个叫工作空间(workspaces)的功能,它可以帮助我们管理多个相关的协同开发的包。

想要使用工作空间需要进行使用 Cargo.toml 文件进行配置,首先创建add 目录中,之后创建 Cargo.toml 文件,这个 Cargo.toml 文件配置了整个工作空,它以 [workspace] 部分作为开始

[workspace]

members = [
    "adder",
    "add_one",
]

add 目录运行 cargo new 新建 adder 二进制 crate,接着新生成一个叫做 add_one 的库

$ cargo new adder
     Created binary (application) `adder` package
$ cargo new add_one --lib
     Created library `add_one` package

现在当前目录的情况应该是

├── Cargo.lock
├── Cargo.toml
├── add_one
│   ├── Cargo.toml
│   └── src
│       └── lib.rs
├── adder
│   ├── Cargo.toml
│   └── src
│       └── main.rs
└── target

add_one/src/lib.rs 文件中,增加一个 add_one 函数:

pub fn add_one(x: i32) -> i32 {
    x + 1
}

现在工作空间中有了一个库 crate,让 adder 依赖库 crate add_one。首先需要在 adder/Cargo.toml 文件中增加 add_one 作为路径依赖

[dependencies]
add_one = { path = "../add_one" }

接下来,在 adder crate 中使用 add_one crate 的函数 add_one。打开 adder/src/main.rs 在顶部增加一行 use 将新 add_one 库 crate 引入作用域。

use add_one;

fn main() {
    let num = 10;
    println!(
        "Hello, world! {} plus one is {}!",
        num,
        add_one::add_one(num)
    );
}

add 目录中运行 cargo build 来构建工作空间

$ cargo build
   Compiling add_one v0.1.0 (file:///projects/add/add_one)
   Compiling adder v0.1.0 (file:///projects/add/adder)
    Finished dev [unoptimized + debuginfo] target(s) in 0.68s

为了在顶层 add 目录运行二进制 crate,可以通过 -p 参数和包名称来 cargo run 指定工作空间中我们希望使用的包

$ cargo run -p adder
    Finished dev [unoptimized + debuginfo] target(s) in 0.0s
     Running `target/debug/adder`
Hello, world! 10 plus one is 11!

这样就可以做到运行 adder/src/main.rs 中的代码,其依赖 add_one crate。工作空间只在根目录有一个 Cargo.lock,而不是在每一个 crate 目录都有 Cargo.lock,这确保了所有的 crate 都使用完全相同版本的依赖。

[dependencies]
rand = "0.8.3"

cargo install

cargo install 命令用于在本地安装和使用二进制 crate。它并不打算替换系统中的包;它意在作为一个方便 Rust 开发者们安装其他人已经在 crates.io 上共享的工具的手段。只有拥有二进制目标文件的包能够被安装。所有来自 cargo install 的二进制文件都安装到 Rust 安装根目录的 bin 文件夹中。

$ cargo install ripgrep
    Updating crates.io index
  Downloaded ripgrep v11.0.2
  Downloaded 1 crate (243.3 KB) in 0.88s
  Installing ripgrep v11.0.2
--snip--
   Compiling ripgrep v11.0.2
    Finished release [optimized + debuginfo] target(s) in 3m 10s
  Installing ~/.cargo/bin/rg
   Installed package `ripgrep v11.0.2` (executable `rg`)

之后你就可以运行 rg --help 并开始使用一个更快更 Rust 的工具来搜索文件了

你可能感兴趣的:(rust入门,rust,开发语言,后端)