将 Crate 发布到 Crates.io
我们使用了 crates.io 的软件包作为 依赖项,但您也可以与其他人共享您的代码 通过发布您自己的包。crates.io 的 crate 注册表分发了 您的软件包,因此它主要托管开源代码。
Rust 和 Cargo 具有使您发布的软件包对用户来说更轻松的功能 查找并使用。接下来,我们将讨论其中的一些功能,然后进行解释 如何发布包。
制作有用的文档注释
准确记录您的包将有助于其他用户知道如何以及何时
使用它们,因此值得花时间编写文档。In Chapter
3、我们讨论了如何使用两个斜杠 .Rust 还具有
一种特定类型的文档注释,方便地称为文档注释,它将生成 HTML 文档。The HTML
显示预期的公共 API 项的文档注释内容
对于有兴趣知道如何使用 crate 而不是如何使用 crate 的程序员
您的 crate 已实现。//
文档注释使用三个斜杠 ,而不是两个斜杠和支持
用于格式化文本的 Markdown 表示法。仅放置文档注释
在他们正在记录的项目之前。示例 14-1 显示了文档注释
对于名为 .///
add_one
my_crate
在这里,我们描述了该函数的作用,启动一个
部分替换为标题,然后提供用于演示
如何使用该功能。我们可以从
此文档通过运行 .此命令运行随 Rust 分发的工具,并将生成的 HTML 文档
在 target/doc 目录中。add_one
Examples
add_one
cargo doc
rustdoc
为方便起见,运行 将为您的
当前 crate 的文档(以及您所有
crate 的依赖项)并在 Web 浏览器中打开结果。导航到该函数,您将看到文档注释中的文本是怎样的
rendered,如图 14-1 所示:cargo doc --open
add_one
常用部分
我们使用示例 14-1 中的 Markdown 标题来创建一个部分
在 HTML 中,标题为 “Examples”。以下是其他一些 crate 的部分
作者通常在他们的文档中使用:# Examples
- Panics:被记录的函数可能 恐慌。不希望其程序 panic 的函数调用者应该 确保他们在这些情况下不调用该函数。
- 错误:如果函数返回一个 ,描述
可能发生的错误以及可能导致这些错误的条件
returned 对调用方有帮助,以便他们可以编写代码来处理
以不同的方式出现不同类型的错误。
Result
- 安全性:如果函数要调用 (我们在
第 19 章),应该有一个部分解释为什么该函数不安全
并涵盖函数期望调用者维护的不变量。
unsafe
大多数文档注释不需要所有这些部分,但这是一个 好的清单可以提醒您代码用户将要注意的方面 有兴趣了解。
作为测试的文档注释
在文档注释中添加示例代码块有助于演示
如何使用您的库,这样做还有一个额外的好处:running 会将文档中的代码示例作为测试运行!没有什么是
比带有示例的文档更好。但没有什么比例子更糟糕的了
这不起作用,因为自文档以来代码已更改
写。如果我们使用示例 14-1 中的函数文档运行,我们将在测试结果中看到如下部分:cargo test
cargo test
add_one
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
现在,如果我们更改函数或示例,则在
example panic 并再次运行,我们将看到 doc tests 捕获
示例和代码彼此不同步!assert_eq!
cargo test
注释包含的项目
doc comment 的样式将文档添加到包含
comments 而不是 comments 后面的项目。我们通常使用
这些 doc 注释在 crate 根文件(按照约定是 src/lib.rs)或
来记录 crate 或整个模块。//!
例如,要添加描述包含该函数的 crate 用途的文档,我们添加了
start with 到 src/lib.rs 文件的开头,如 清单 所示
14-2:my_crate
add_one
//!
请注意,在最后一行以 .因为
我们从 而不是 开始注释,我们正在记录该项目
,而不是此注释后面的项。在
在本例中,该项目是 src/lib.rs 文件,它是 crate 根。这些
comments 描述了整个 crate。//!
//!
///
当我们运行 时,这些注释将显示在前面
文档页面上的
crate,如图 14-2 所示:cargo doc --open
my_crate
项中的文档注释可用于描述 crate 和 特别是模块。使用它们来解释容器的总体用途 帮助您的用户了解 crate 的组织。
使用 pub
导出方便的公共 API
在发布 板条箱。使用你的 crate 的人对结构的熟悉程度不如你 如果您的板条箱 具有大型模块层次结构。
在第 7 章中,我们介绍了如何使用关键字将项目设为公共,并且
使用 关键字将项目引入 scope。但是,结构
对您来说有意义,当您开发 crate 时可能不是很方便
为您的用户。您可能希望在层次结构中组织结构
包含多个级别,但随后想要使用您已有的类型
在层次结构的深处定义可能难以发现该类型是否存在。
他们也可能因为不得不进入而不是 而感到恼火。pub
use
use
my_crate::some_module::another_module::UsefulType;
use
my_crate::UsefulType;
好消息是,如果结构不方便其他人使用
从另一个库,您不必重新排列内部组织:
相反,您可以重新导出项目以创建一个不同的公共结构
使用 .重新导出需要一个公共的
item 在一个位置,并在另一个位置将其设为公共,就像它是
定义。pub use
例如,假设我们创建了一个名为 for modeling 艺术概念的库。
此库中有两个模块:一个包含两个枚举的模块
named 和 fragment 以及一个包含
函数名称为 ,如示例 14-3 所示:art
kinds
PrimaryColor
SecondaryColor
utils
mix
图 14-3 显示了这个 crate 的文档首页是什么
生成 将如下所示:cargo doc
请注意,和 类型未列在
front page 的 THE PAGE 的 THE FUNCTION 也不是。我们必须点击并
看看他们。PrimaryColor
SecondaryColor
mix
kinds
utils
另一个依赖于此库的 crate 需要
将项从 bring the items from into scope 中,指定 Module 结构,即
currently defined.示例 14-4 显示了一个使用 crate 中的 and 项的 crate 示例:use
art
PrimaryColor
mix
art
示例 14-4 中代码的作者使用了 crate,它必须
弄清楚 在 Module 和 在 Module 中。crate 的模块结构与
在 crate 上工作的开发人员比使用它的人更重要。内部的
结构不包含任何有用的信息,供尝试
了解如何使用 crate,但反而会引起混淆,因为
使用它的开发人员必须弄清楚在哪里查找,并且必须指定
模块名称。art
PrimaryColor
kinds
mix
utils
art
art
art
use
要从公共 API 中删除内部组织,我们可以修改示例 14-3 中的 crate 代码,添加语句以重新导出
items 的 s,如示例 14-5 所示:art
pub use
为此 crate 生成的 API 文档现在将列出
和 link 重新导出,如图 14-4 所示,使得 and 类型和函数更容易找到。cargo doc
PrimaryColor
SecondaryColor
mix
crate 用户仍然可以查看和使用来自 清单 的内部结构
14-3 中,如示例 14-4 所示,或者他们可以使用更方便的
结构,如示例 14-6 所示:art
在有许多嵌套模块的情况下,重新导出顶部的类型
级别 对
使用板条箱的人。另一个常见的用途是再导出
当前 crate 中依赖项的定义,以使该 crate 的
definitions 是 crate 的公共 API 的一部分。pub use
pub use
创建有用的公共 API 结构与其说是一门科学,不如说是一门艺术,并且
您可以迭代以查找最适合您的用户的 API。选择 使您可以灵活地在内部构建 crate,并且
将该内部结构与您向用户呈现的内容分离。看
你安装的一些 crate 代码,看看它们的内部结构是否
不同于他们的公共 API。pub use
设置 Crates.io 帐户
在发布任何 crate 之前,您需要在 crates.io 上创建一个账户并获取 API 令牌。为此,
访问 crates.io 和 Log 的主页
in 通过 GitHub 帐户。(GitHub 帐户目前是必需的,但
该网站将来可能支持其他创建帐户的方式。一次
您已登录,在 https://crates.io/me/ 访问您的帐户设置并检索您的
API 密钥。然后运行命令并在出现提示时粘贴您的 API 密钥,如下所示:cargo login
$ cargo login
abcdefghijklmnopqrstuvwxyz012345
此命令将通知 Cargo 您的 API 令牌并将其存储在本地 ~/.cargo/credentials 中。请注意,此令牌是机密:请勿共享 和其他人一起。如果您出于任何原因与任何人分享它,您应该 撤销它并在 crates.io 上生成新 Token。
将元数据添加到新 crate
假设您有一个要发布的 crate。在发布之前,您需要
在 crate 的 Cargo.toml 文件部分中添加一些元数据。[package]
您的 crate 需要一个唯一的名称。当您在本地处理 crate 时,
你可以随心所欲地给 crate 命名。但是,crates.io 上的 crate 名称是按照先到先得的方式分配的。
先到先得。一旦 crate 名称被占用,其他人就无法发布 crate
替换为该名称。在尝试发布 crate 之前,请搜索
想要使用。如果该名称已被使用,您将需要找到另一个名称,并且
将 Cargo.toml 文件中 section 下的字段编辑为
使用新名称进行发布,如下所示:name
[package]
文件名: Cargo.toml
[package]
name = "guessing_game"
即使您选择了唯一的名称,当您运行以发布
此时,您将收到警告,然后是错误:cargo publish
$ cargo publish
Updating crates.io index
warning: manifest has no description, license, license-file, documentation, homepage or repository.
See https://doc.rust-lang.org/cargo/reference/manifest.html#package-metadata for more info.
--snip--
error: failed to publish to registry at https://crates.io
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
这个错误是因为你错过了一些关键信息:描述 和
需要许可证,这样人们就会知道你的 crate 做什么以及在什么下
他们可以使用的术语。在 Cargo.toml 中,添加一个描述,该描述只是一个
一两个句子,因为它会与你的 crate 一起出现在搜索结果中。为
字段中,您需要提供 License identifier 值。Linux 的
Foundation 的软件包 Data Exchange (SPDX) 列出了标识符
您可以用于此值。例如,要指定您已为您的
crate 中使用 MIT 许可证,添加标识符:license
MIT
文件名: Cargo.toml
[package]
name = "guessing_game"
license = "MIT"
如果您想使用未出现在 SPDX 中的许可证,则需要将
该文件中的许可证文本,将该文件包含在您的项目中,然后
用于指定该文件的名称,而不是使用密钥。license-file
license
关于哪种许可证适合您的项目的说明超出了范围
这本书的。Rust 社区中的许多人在
与 Rust 相同,使用 .这种做法
表明您还可以指定多个许可证标识符
by 为您的项目提供多个许可证。MIT OR Apache-2.0
OR
添加唯一名称、版本、描述和许可证后,准备发布的项目的 Cargo.toml 文件可能如下所示:
文件名: 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]
Cargo 的文档描述了其他 元数据,以确保其他人可以更多地发现和使用您的 crate 容易。
发布到 Crates.io
现在,您已经创建了一个账户,保存了 API 令牌,并为 的 crate 并指定了所需的元数据,即可发布! 发布 crate 会将特定版本上传到 crates.io 以供其他人使用。
请小心,因为发布是永久性的。版本永远不能是 overwritten,并且代码无法删除。crates.io 的一个主要目标是充当永久档案 的代码,以便所有依赖于 crates.io 的 crate 的项目构建将继续工作。允许 版本删除将使该目标无法实现。然而,有 您可以发布的 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)
祝贺!您现在已经与 Rust 社区共享了您的代码,并且 任何人都可以轻松地将你的 crate 添加为他们项目的依赖项。
发布现有 crate 的新版本
当您对 crate 进行了更改并准备发布新版本时,
更改 Cargo.toml 文件中指定的值,然后
再版。使用语义版本控制规则来决定
适当的 Next Version Number (下一个版本号) 基于您所做的更改类型。
然后运行以上传新版本。version
cargo publish
弃用 cargo yank
的 Crates.io 版本
虽然您无法删除 crate 的先前版本,但您可以阻止任何 将来的项目,将它们添加为新的依赖项。这在 crate 版本由于某种原因而损坏。在这种情况下,Cargo 支持拉动 crate 版本。
拉出版本可以防止新项目依赖于该版本,而 允许所有依赖它的现有项目继续。本质上,一个 yank 意味着所有带有 Cargo.lock 的项目都不会中断,并且任何未来生成的 Cargo.lock 文件都不会使用 yanked 版本。
要拉扯 crate 的某个版本,请在您拥有
以前发布,运行并指定要发布的版本
美国 佬。例如,如果我们发布了一个名为 version
1.0.1 中,我们想把它拉出来,在 we d
跑:cargo yank
guessing_game
guessing_game
$ cargo yank --vers 1.0.1
Updating crates.io index
Yank guessing_game@1.0.1
通过添加到命令,您还可以撤消 yank 并允许项目
要再次开始依赖版本:--undo
$ cargo yank --vers 1.0.1 --undo
Updating crates.io index
Unyank guessing_game@1.0.1
抽搐不会删除任何代码。例如,它不能意外删除 上传的密钥。如果发生这种情况,您必须立即重置这些密钥。
本文档由官方文档翻译而来,如有差异请以官方英文文档(https://doc.rust-lang.org/)为准