Rust 学习笔记:发布一个 crate 到 crates.io

news2025/7/21 2:00:41

Rust 学习笔记:发布一个 crate 到 crates.io

  • Rust 学习笔记:发布一个 crate 到 crates.io
    • 提供有用的文档注释
      • 常用标题
      • 文档注释作为测试
      • 注释所包含的项目
    • 使用 pub use 导出一个方便的公共 API
    • 设置 crates.io 账户
    • 添加 metadata 到一个新的 crate
    • 发布到 crates.io
    • 发布现有 crate 的新版本
    • 使用 cargo yank 在 crates.io 上废弃 crate 特定的版本

Rust 学习笔记:发布一个 crate 到 crates.io

我们已经使用过来自 crates.io 的包作为我们项目的依赖项,但是你也可以通过发布你自己的包与其他人共享你的代码。在 crates.io 上的 crate 注册表分发包的源代码,因此它主要托管开源代码。

Rust 和 Cargo 的特性使得发布的包更容易被人们找到和使用。接下来我们将讨论其中的一些特性,然后解释如何发布一个包。

提供有用的文档注释

之前我们讨论了如何使用两个斜杠 // 注释 Rust 代码。

Rust 还为文档提供了一种特殊的注释,方便地称为文档注释,它将生成 HTML 文档,其中显示了公共 API 项的文档注释内容。

文档注释使用三个斜杠 ///,,并支持 Markdown 符号来格式化文本。将文档注释放在他们要记录的项目的前面。

下面代码显示了一个名为 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
}

在这里,我们将描述 add_one 函数的作用,以 Examples 开头的一节,然后提供演示如何使用 add_one 函数的代码。我们可以通过运行 cargo doc 从这个文档注释生成 HTML 文档。该命令运行随 Rust 分发的 rustdoc 工具,并将生成的 HTML 文档放在 target/doc 目录中。

为方便起见,运行 cargo doc --open 将为当前 crate 的文档(以及所有 crate 依赖项的文档)构建 HTML,并在 web 浏览器中打开结果。

在打开的文档中导航到 add_one 函数:

在这里插入图片描述

常用标题

我们使用 # Examples Markdown 标题在 HTML 中创建了一个标题为 “Examples” 的部分。以下是 crate 作者在他们的文档中经常使用的其他 Markdown 标题:

  • Panics:被记录的功能可能出现恐 panic 的场景。如果函数的调用者不希望他们的程序出现 panic,那么他们应该确保在这些情况下不调用该函数。

  • Errors:如果函数返回一个 Result,描述可能发生的错误类型以及可能导致这些错误返回的条件可能对调用者有帮助,以便他们可以编写代码以不同的方式处理不同类型的错误。

  • Safety:如果函数调用是不安全的,应该有一节解释为什么函数是不安全的,并涵盖函数期望调用者维护的不变量。

大多数文档注释不需要所有这些部分,但这是一个很好的清单,可以提醒代码的用户感兴趣的方面。

文档注释作为测试

在文档注释中添加示例代码块可以帮助演示如何使用库,这样做还有一个额外的好处:运行 cargo test 将把文档中的代码示例作为测试运行。

如果我们使用 add_one 函数的文档运行 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

如果我们更改函数或示例,使示例中的 assert_eq! 出现异常并再次运行 cargo test,我们将看到文档测试捕捉到示例和代码彼此不同步。

注释所包含的项目

注释 //! 将为包含它的项(crate 或者模块)添加文档,而不是单个函数。我们通常在 crate 根文件(按照惯例是 src/lib.js)或模块中使用这些文档注释来作为一个整体记录 crate 或模块。

例如,为了添加描述包含 add_one 函数的 my_crate 这一 crate 用途的文档,我们添加以 //! 开头的文档注释到 src/lib.rs 文件的开头。

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

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

以 //! 注释的这些行描述了整个 crate。

当我们运行 cargo doc --open 时,这些注释将显示在 my_crate 文档的首页上,位于 crate 中的公共项目列表上方:

在这里插入图片描述

项目中的文档注释对于描述 crate 和模块尤其有用。使用它们来解释 crate 的总体目的,以帮助用户理解 crate 的组织结构。

使用 pub use 导出一个方便的公共 API

发布 crate 时,公共 API 的结构是一个主要考虑因素。如果你的 crate 有一个大的模块层次结构,使用者可能很难找到他们想要使用的部分。

结构层次太多会影响使用。用户可能还会因为必须输入 use my_crate::some_module::another_module::UsefulType; 而不是使用 use my_crate::UsefulType;

之前我们介绍了如何使用 pub 关键字将项设为公共,以及如何使用 use 关键字将项引入作用域。如果结构不方便其他人从另一个库中使用,可以使用 pub use 重新导出项,以创建与私有结构不同的公共结构。重新导出在一个位置获取公共项,并使其在另一个位置公开,就好像它是在另一个位置定义的一样。

例如,假设我们创建了一个名为 art 的库,用于建模艺术概念。在这个库中有两个模块:一个 types 模块包含两个枚举 PrimaryColor 和 SecondaryColor,一个 utils 模块包含一个名为 mix 的函数。

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

运行 cargo doc,生成 crate 文档:

在这里插入图片描述

注意,PrimaryColor 和 SecondaryColor 类型没有在首页上列出,mix 函数也没有。我们必须点击 kinds 和 utils 来查看它们。

另一个依赖于此库的 crate 则需要使用语句将 art 中的项目带入范围,并指定当前定义的模块结构。例如:

use art::kinds::PrimaryColor;
use art::utils::mix;

fn main() {
    let red = PrimaryColor::Red;
    let yellow = PrimaryColor::Yellow;
    mix(red, yellow);
}

使用 art crate 的开发者必须弄清楚 PrimaryColor 在 kinds 模块中,mix 在 utils 模块中。然而,内部结构并不包含任何有用的信息,只会徒增麻烦。

为了从公共 API 中移除内部组织,我们可以修改 art 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--
}

cargo doc 为这个 crate 生成的 API 文档现在将在首页列出和链接重新导出(re-exports)的条目,使得 PrimaryColor 和 SecondaryColor 类型以及 mix 函数更容易找到。

在这里插入图片描述

这样一来,使用者可以使用更方便的导入语句:

use art::PrimaryColor;
use art::mix;

fn main() {
    // --snip--
}

在有许多嵌套模块的情况下,使用 pub 在顶层重新导出类型可以对使用 crate 的人的体验产生重大影响。pub 用法的另一种常见用法是重新导出当前 crate 中依赖项的定义,使该 crate 的定义成为当前 crate 的公共 API 的一部分。

创建有用的公共 API 结构与其说是一门科学,不如说是一门艺术。选择 pub 可以让你在内部结构上更加灵活,并将内部结构与你呈现给用户的内容分离开来。

设置 crates.io 账户

在发布任何 crate 之前,您需要在 crates.io 上创建一个帐户并获得一个 API 令牌。要做到这一点,请访问 crates.io 的主页。登录后,访问 https://crates.io/me/ 的帐户设置并检索 API 密钥。然后运行 cargo login 命令并在提示时粘贴 API 密钥,如下所示:

$ cargo login
abcdefghijklmnopqrstuvwxyz012345

此命令将向 Cargo 告知你的 API 令牌,并将其本地存储在 ~/.cargo/credentials 中。请注意,这个令牌不要与其他人共享。

添加 metadata 到一个新的 crate

假设你有一个想要发布的 crate,在发布之前,您需要在 crate 的 Cargo.toml 的 [package] 部分中添加一些元数据。

crate 需要一个唯一的名称。当你在本地开发一个 crate 时,你可以给它起任何你喜欢的名字。然而,crates.io 上的 crate 名称按先到先得原则分配。在尝试发布 crate 之前,搜索想要使用的名称。如果使用了该名称,则需要找到另一个名称并编辑 Cargo.toml 文件 [package] 中的名称字段,如下所示:

[package]
name = "guessing_game"

即使选择了一个唯一的名称,当运行 cargo publish 来发布此时的 crate 时,还会报错:

$ 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 (status 400 Bad Request): missing or empty metadata fields: description, license. Please see https://doc.rust-lang.org/cargo/reference/manifest.html for more information on configuring these fields

因为遗漏了一些关键信息:需要描述和许可,以便人们知道这个 crate 是做什么的,以及他们可以在什么条件下使用它。在 Cargo.toml 中添加一到两句话的描述,因为它会和你的 crate 一起出现在搜索结果中。对于 license 字段,你需要提供一个许可证标识符值。Linux 基金会列出了可以用于此值的标识符。例如,要指定你已经使用 MIT 许可证授权了你的 crate,请添加 MIT 标识符:

[package]
name = "guessing_game"
license = "MIT"

如果希望使用 Linux 基金会中没有出现的许可证,则需要将该许可证的文本放在一个文件中,将该文件包含在项目中,然后使用 license-file 来指定该文件的名称,而不是使用许可证密钥。

Rust 社区中的许多人以与 Rust 相同的方式使用 MIT OR Apache-2.0 的双重许可来许可他们的项目。

你可以为你的项目指定用 OR 分隔的多个许可证标识符,从而拥有多个许可证。

有了唯一的名称、版本、描述,以及添加的许可证,准备发布的项目的 Cargo.toml 文件可能如下所示:

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

[dependencies]

参考文档:https://doc.rust-lang.org/cargo/

该文档描述了你可以指定的其他元数据,以确保其他人可以更轻松地发现和使用你的 crate。

发布到 crates.io

现在你已经创建了一个帐户,保存了 API 令牌,为 crate 选择了一个名称,并指定了所需的元数据,现在就可以发布了!发布一个 crate 会向 crates.io 上传一个特定的版本,供他人使用。

发布是永久性的。版本永远不能被覆盖,代码也不能被删除。creates.io 的一个主要目标是充当代码的永久存档,以便依赖于 creates.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` profile [unoptimized + debuginfo] target(s) in 0.19s
   Uploading guessing_game v0.1.0 (file:///projects/guessing_game)

现在你已经与 Rust 社区共享了你的代码,任何人都可以轻松地将你的 crate 添加为其项目的依赖项。

发布现有 crate 的新版本

对 crate 进行更改并准备发布新版本时,可以更改 Cargo 中指定的版本值。重新归档并重新发布。使用 Semantic Versioning 规则根据所做的更改类型来决定合适的下一个版本号。然后运行 cargo publish 来上传新版本。

使用 cargo yank 在 crates.io 上废弃 crate 特定的版本

虽然不能删除旧版本的 crate,但可以阻止任何未来的项目将它们添加为新的依赖项。

cargo yank 可以防止新项目依赖于该版本,同时允许所有依赖于该版本的现有项目继续进行。本质上,yank 意味着所有具有 Cargo.lock 的项目都不会中断,并且将来生成的任何 Cargo.lock 文件都不会使用被 yank 的版本。

运行 cargo yank,并指定版本:

$ cargo yank --vers 1.0.1
    Updating crates.io index
        Yank guessing_game@1.0.1

通过在命令中添加 --undo,还可以撤销一个 yank 命令,并允许项目根据版本重新启动:

$ cargo yank --vers 1.0.1 --undo
    Updating crates.io index
      Unyank guessing_game@1.0.1

注意,yank 并不能删除任何代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2396070.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vert.x学习笔记-EventLoop与Context的关系

Vert.x学习笔记 1. EventLoop 的核心作用2. Context 的核心作用3. EventLoop 与 Context 的关系1. 事件循环(EventLoop)的核心职责2. 上下文(Context)的核心职责3. 事件循环与上下文的关系(1)一对一绑定&am…

2025030给荣品PRO-RK3566开发板单独升级Android13的boot.img

./build.sh init ./build.sh -K ./build.sh kernel 【导入配置文件】 Z:\Android13.0\rockdev\Image-rk3566_t\config.cfg 【更新的内核】 Z:\Android13.0\rockdev\Image-rk3566_t\boot.img 【导入分区表,使用原始的config.cfg会出错的^_】 Z:\Android13.0\rockdev\…

由enctype-引出post与get的关系,最后深究至请求/响应报文

本篇载自我的笔记,本次为第二次复习。我觉得我有能力理一下思路了。 --- 笔记截图。 enctype HTML 表单的 enctype(Encode Type,编码类型)属性用于控制表单数据在提交到服务器时的编码方式,不同取值的详细解析如下&a…

搭建基于VsCode的ESP32的开发环境教程

一、VsCode搜索ESP-IDF插件 根据插件处搜索找到ESP-IDF并安装 安装完成 二、配置安装ESP-IDF 配置IDF 按照如下配置,点击安装 安装完成 三、使用案例程序 创建一个闪光灯的例子程序,演示程序编译下载。 选择blink例子,闪烁LED的程序 选…

【MFC】初识MFC

目录 01 模态和非模态对话框 02 静态文本 static text 01 模态和非模态对话框 首先我们需要知道模态对话框和非模态对话框的区别: 模态对话框是一种阻塞时对话框,它会阻止用户与应用程序的其他部分进行交互,直到用户与该对话框进行交互并关…

如何通过数据分析优化项目决策

通过数据分析优化项目决策需从明确数据分析目标、选择适当的数据分析工具、确保数据质量、建立数据驱动文化等方面入手,其中,明确数据分析目标是优化决策过程的基础,只有清晰明确的数据分析目标才能指导有效的数据采集与分析,避免…

2024年数维杯国际大学生数学建模挑战赛B题空间变量协同估计方法研究解题全过程论文及程序

2024年数维杯国际大学生数学建模挑战赛 B题 空间变量协同估计方法研究 原题再现: 在数理统计学中,简单采样通常假设来自相同总体的采样点彼此独立。与数理统计相反,空间统计假设空间变量的采样点是相依的,并在其值中表现出某些趋…

leetcode hot100刷题日记——34.将有序数组转换为二叉搜索树

First Blood:什么是平衡二叉搜索树? 二叉搜索树(BST)的性质 左小右大:每个节点的左子树中所有节点的值都小于该节点的值,右子树中所有节点的值都大于该节点的值。 子树也是BST:左子树和右子树也…

网页自动化部署(webhook方法)

实现步骤: 宝塔安装宝塔WebHook 2.5插件。 github 上配置网页仓库(或可在服务器的网页根目录clone)。 配置宝塔WebHook 2.5 添加hook脚本; 编辑添加syncJC脚本; #!/bin/bash # 定义网站根目录 WEBROOT"/www…

AU6825集成音频DSP的2x32W数字型ClaSSD音频功率放大器(替代TAS5825)

1.特性 ● 输出配置 - 立体声 2.0: 2 x 32W (8Ω,24V,THD N 10%) - 立体声 2.0: 2 x 26W (8Ω,21V,THD N 1%) ● 供电电压范围 - PVDD:4.5V -26.4V - DVDD: 1.8V 或者 3.3V ● 静态功耗 - 37mA at PVDD12V ● 音频性能指标 - THDN ≤ 0.02% at 1W,1kHz - SNR ≥ 107dB (A-wei…

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1商用服务体验全流程

华为云 Flexus 与 DeepSeek-V3/R1 的深度整合,构建了一套 “弹性算力 智能引擎” 的协同体系。 Flexus 系列云服务器基于柔性计算技术,通过动态资源调度(如 Flexus X 实例)实现 CPU / 内存的实时弹性分配,尤其适合大模…

C# NX二次开发-查找连续倒圆角面

在QQ群里有人问怎么通过一个选择一个倒圆角面来自动选中一组倒圆角面。 可以通过ufun函数 UF_MODL_ask_face_type 和 UF_MODL_ask_face_props 可判断处理选择相应的一组圆角面。 代码: Tag[] 查找连续倒圆角面(Tag faceTag) {theUf.Modl.AskFaceType(faceTag, out int typ…

今天遇到的bug

先呈现一下BUG现象。 这主要是一个传参问题,参数一直传不过去。后来我才发现,问题所在。 我们这里用的RquestBody接收参数,所有请求的参数需要用在body体中接收,但是我们用postman,用的是字符串查询方式传参&#x…

长安链智能合约命令解析(全集)

创建命令解析 ./cmc client contract user create \ --contract-namefact \ --runtime-typeWASMER \ --byte-code-path./testdata/claim-wasm-demo/rust-fact-2.0.0.wasm \ --version1.0 \ --sdk-conf-path./testdata/sdk_config.yml \ --admin-key-file-paths./testdata/cryp…

一、OpenCV的基本操作

目录 1、OpenCV的模块 2、OpenCV的基础操作 2.1图像的IO操作 2.2绘制几何图形 2.3获取并修改图像中的像素点 2.4 获取图像的属性 2.5图像通道的拆分与合并 2.6色彩空间的改变 3、OpenCV的算数操作 3.1图像的加法 3.2图像的混合 3.3总结 1、OpenCV的模块 2、OpenCV的基…

裂缝仪在线监测装置:工程安全领域的“实时守卫者”

在基础设施运维领域,裂缝扩展是威胁建筑结构安全的核心隐患之一。传统人工巡检方式存在效率低、时效性差、数据主观性强等局限,而裂缝仪在线监测装置通过技术迭代,实现了对结构裂缝的自动化、持续性追踪,为工程安全评估提供科学依…

【论文精读】2024 ECCV--MGLD-VSR现实世界视频超分辨率(RealWorld VSR)

文章目录 一、摘要二、问题三、Method3.1 Latent Diffusion Model3.2 Motion-guided Diffusion Sampling3.3 Temporal-aware Decoder Fine-tuning 四、实验设置4.1 训练阶段4.2 训练数据 贡献总结 论文全称: Motion-Guided Latent Diffusion for Temporally Consis…

SpringBoot简单体验

1 Helloworld 打开:https://start.spring.io/ 选择maven配置。增加SpringWeb的依赖。 Generate之后解压,代码大致如下: hpDESKTOP-430500P:~/springboot2/demo$ tree ├── HELP.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── s…

2025年通用 Linux 服务器操作系统该如何选择?

2025年通用 Linux 服务器操作系统该如何选择? 服务器操作系统的选择对一个企业IT和云服务影响很大,主推的操作系统在后期更换的成本很高,而且也有很大的迁移风险,所以企业在选择服务器操作系统时要尤为重视。 之前最流行的服务器…

Azure devops 系统之五-部署ASP.NET web app

今天介绍如何通过vscode 来创建一个asp.net web app,并部署到azure 上。 创建 ASP.NET Web 应用 在您的计算机上打开一个终端窗口并进入工作目录。使用 dotnet new webapp 命令创建一个新的 .NET Web 应用,然后将目录切换到新创建的应用。 dotnet new webapp -n MyFirstAzu…