进阶篇-进一步认识 Cargo 和 Crates.io

  • 木头
  • 更新于 2023-03-14 15:40
  • 阅读 3010

文档注释,发布crate包

目前为止我们只使用过 Cargo 构建、运行和测试代码这些最基本的功能,不过它还可以做到更多官方文档

Cargo 自定义构建

Rust发布配置(release profiles)是预定义的、可定制的带有不同选项的配置,他们允许程序员更灵活地控制代码编译的多种选项。每一个配置都彼此相互独立。

Cargo 有两个主要的配置:运行 cargo build时采用的dev 配置和运行cargo build --releaserelease 配置。dev 配置被定义为开发时的好的默认配置,release配置则有着良好的发布构建的默认配置。

这些配置名称可能很眼熟,因为它们出现在构建的输出中:

$ cargo build
   Compiling cargo1 v0.1.0 (/rsut/cargo1)
    Finished dev [unoptimized + debuginfo] target(s) in 0.67s
$ cargo build --release
   Compiling cargo1 v0.1.0 (/rsut/cargo1)
    Finished release [optimized] target(s) in 0.11s

构建输出中的 devrelease表明编译器在使用不同的配置。

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

[profile.dev]
opt-level = 0

[profile.release]
opt-level = 3

opt-level 设置控制 Rust 会对代码进行何种程度的优化。这个配置的值从 03。越高的优化级别需要更多的时间编译,所以如果你在进行开发并经常编译,可能会希望在牺牲一些代码性能的情况下减少优化以便编译得快一些。因此 devopt-level 默认为0。当你准备发布时,花费更多时间在编译上则更好。只需要在发布模式编译一次,而编译出来的程序则会运行很多次,所以发布模式用更长的编译时间换取运行更快的代码。这正是为什么 release 配置的 opt-level 默认为 3

我们可以选择通过在 Cargo.toml增加不同的值来覆盖任何默认设置。比如,如果我们想要在开发配置中使用级别 1 的优化,则可以在 Cargo.toml 中增加这两行:

[profile.dev]
opt-level = 1

这会覆盖默认的设置 0。现在运行cargo build 时,Cargo将会使用 dev 的默认配置加上定制的opt-level。因为 opt-level 设置为1Cargo 会比默认进行更多的优化,但是没有发布构建那么多。

文档注释

文档注释使用三斜杠///而不是两斜杆以支持 Markdown 注解来格式化文本。文档注释就位于需要文档的项的之前,新建项目:

$ cargo new learn_cratel
$ cd learn_cratel
$ cargo new mylib --lib

打开myliblib.rs给默认的add函数增加文档注释:

/// 两个usize相加
pub fn add(left: usize, right: usize) -> usize {
    left + right
}

可以运行cargo doc来生成这个文档注释的 HTML文档。这个命令运行由Rust分发的工具 rustdoc并将生成的HTML文档放入 target/doc 目录。

为了方便起见,运行 cargo doc --open 会构建当前 crate 文档(同时还有所有 crate依赖的文档)的 HTML并在浏览器中打开。导航到 add函数将会发现文档注释的文本是如何渲染的:

$ cd mylib
$ cargo doc --open

image.png 现在我们只是简单加了一个标题,还可以继续丰富一下文档注释:

/// Add two numbers together
/// # Example
/// ```
/// let left = 1;
/// let right = 2;
/// assert_eq!(3, mylib(left,right));
/// ```
pub fn add(left: usize, right: usize) -> usize {
    left + right
}

这里,我们提供了一个 add 函数工作的描述,接着开始了一个标题为 Example 的部分,和展示如何使用 add 函数的代码。 image.png

文档注释作为测试

在文档注释中增加示例代码块是一个清楚的表明如何使用库的方法,这么做还有一个额外的好处:cargo test也会像测试那样运行文档中的示例代码!没有什么比有例子的文档更好的了,但最糟糕的莫过于写完文档后改动了代码,而导致例子不能正常工作。尝试 cargo test运行add_ 函数的文档;应该在测试结果中看到像这样的部分:

Doc-tests mylib

running 1 test
test src/lib.rs - add (line 3) ... ok

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

现在尝试改变函数或例子来使例子中的 assert_eq! 产生 panic。再次运行 cargo test,你将会看到文档测试捕获到了例子与代码不再同步!

注释包含项的结构

文档注释风格 //! 为包含注释的项,而不是位于注释之后的项增加文档。这通常用于crate 根文件(通常是 src/lib.rs)或模块的根文件为 crate 或模块整体提供文档:

//! # My Crate
//!
//! `learn_cratel` is a collection of utilites to make

/// Add two numbers together
/// # Example
/// ```
/// let left = 1;
/// let right = 2;
/// assert_eq!(3, mylib::add(left,right));
/// ```
pub fn add(left: usize, right: usize) -> usize {
    left + right
}

注意//! 的最后一行之后没有任何代码。因为他们以 //!开头而不是 ///,这是属于包含此注释的项而不是注释之后项的文档。在这个情况下时 src/lib.rs文件,也就是 crate 根文件。这些注释描述了整个 crate

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

将 crate 发布到 Crates.io

我们曾经在项目中使用 crates.io上的包作为依赖,不过你也可以通过发布自己的包来向他人分享代码。crates.io用来分发包的源代码,所以它主要托管开源代码。

创建 Crates.io 账号

在你可以发布任何 crate 之前,需要在crates.io 上注册账号并获取一个API token。为此,访问位于 crates.io 的首页并使用 GitHub 账号登录。(目前 GitHub 账号是必须的,不过将来该网站可能会支持其他创建账号的方法)一旦登录之后,查看位于 https://crates.io/me/ 的账户设置页面并获取 API token。接着使用该API token 运行 cargo login 命令,像这样:

$ cargo login sdfswfdwerwfd3erasdsa31564rewfdew

这个命令会通知 Cargo你的 API token并将其储存在本地的 ~/.cargo/credentials 文件中。注意这个 token 是一个秘密(secret)且不应该与其他人共享。

发布到 Crates.io

现在我们创建了一个账号,保存了API token。发布 crate 会上传特定版本的 cratecrates.io以供他人使用。

发布 crate 时请多加小心,因为发布是永久性的(permanent)。对应版本不可能被覆盖,其代码也不可能被删除。crates.io 的一个主要目标是作为一个存储代码的永久文档服务器,这样所有依赖 crates.io 中的 crate 的项目都能一直正常工作。而允许删除版本没办法达成这个目标。然而,可以被发布的版本号却没有限制。

运行 cargo publish命令。我们会得到一个错误:

Caused by:
  the remote server responded with an error: missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for how to upload metadata

这个错误是因为我们缺少一些关键信息:descriptionlicense修改Cargo.toml增加配置:

description = "This is a test project"
license = "MIT OR Apache-2.0"

再次运行cargo publish命令。这次它应该会成功:

$ cargo publish
    Updating crates.io index
warning: manifest has no documentation, homepage or repository.
See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
   Packaging mylib-hekang v0.1.0 (/rsut/learn_cratel/mylib)
   Verifying mylib-hekang v0.1.0 (/rsut/learn_cratel/mylib)
   Compiling mylib-hekang v0.1.0 (/rsut/learn_cratel/mylib/target/package/mylib-hekang-0.1.0)
    Finished dev [unoptimized + debuginfo] target(s) in 0.84s
    Packaged 3 files, 1.3KiB (901.0B compressed)
   Uploading mylib-hekang v0.1.0 (/rsut/learn_cratel/mylib)
    Updating crates.io index
     Waiting on `mylib-hekang` to propagate to crates.io index (ctrl-c to wait asynchronously)
    Updating crates.io index
    Updating crates.io index
    Updating crates.io index
    Updating crates.io index
    Updating crates.io index

恭喜!你现在向 Rust 社区分享了代码,而且任何人都可以轻松的将你的 crate加入他们项目的依赖。

发布现存 crate 的新版本

当你修改了 crate 并准备好发布新版本时,改变Cargo.tomlversion所指定的值。请使用 语义化版本规则 来根据修改的类型决定下一个版本号。接着运行cargo publish 来上传新版本。

使用 cargo yank 从 Crates.io 弃用版本

虽然你不能删除之前版本的 crate,但是可以阻止任何将来的项目将他们加入到依赖中。这在某个版本因为这样或那样的原因被破坏的情况很有用。对于这种情况,Cargo支持 撤回(yanking)某个版本。

撤回某个版本会阻止新项目依赖此版本,不过所有现存此依赖的项目仍然能够下载和依赖这个版本。从本质上说,撤回意味着所有带有 Cargo.lock 的项目的依赖不会被破坏,同时任何新生成的 Cargo.lock 将不能使用被撤回的版本。

为了撤回一个版本的 crate,在之前发布crate的目录运行 cargo yank并指定希望撤回的版本。例如,如果我们发布了一个名为 mylib-hekangcrate0.1.0 版本并希望撤回它,在 mylib-hekang 项目目录运行:

$ cargo yank --vers 0.1.0
    Updating crates.io index
        Yank mylib-hekang@0.1.0

也可以撤销撤回操作,并允许项目可以再次开始依赖某个版本,通过在命令上增加 --undo

$ cargo yank --vers 0.1.0 --undo
    Updating crates.io index
      Unyank mylib-hekang@0.1.0

撤回并没有删除任何代码。举例来说,撤回功能并不能删除不小心上传的秘密信息。如果出现了这种情况,请立即重新设置这些秘密信息。

  • 原创
  • 学分: 2
  • 分类: Rust
  • 标签:
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。
125 订阅 31 篇文章

0 条评论

请先 登录 后评论
木头
木头
0xC020...10cf
江湖只有他的大名,没有他的介绍。