【Rust】——采用发布配置自定义构建

Y小夜 2024-06-13 11:05:03 阅读 82

💻博主现有专栏:

                C51单片机(STC89C516),c语言,c++,离散数学,算法设计与分析,数据结构,Python,Java基础,MySQL,linux,基于HTML5的网页设计及应用,Rust(官方文档重点总结),jQuery,前端vue.js,Javaweb开发,Python机器学习等

🥏主页链接:

                Y小夜-CSDN博客

今日学习推荐:

        在当今这个飞速发展的信息时代,人工智能(AI)已经成为了一个不可或缺的技术力量,它正在逐步改变着我们的生活、工作乃至整个社会的运作方式。从智能语音助手到自动驾驶汽车,从精准医疗到智慧城市,人工智能的应用已经渗透到了我们生活的方方面面。因此,学习和掌握人工智能相关的知识和技能,对于任何希望在这个时代保持竞争力的个人来说,都已经变得至关重要。

        然而,人工智能是一个涉及数学、计算机科学、数据科学、机器学习、神经网络等多个领域的交叉学科,其学习曲线相对陡峭,对初学者来说可能会有一定的挑战性。幸运的是,随着互联网教育资源的丰富,现在有大量优秀的在线平台和网站提供了丰富的人工智能学习材料,包括视频教程、互动课程、实战项目等,这些资源无疑为学习者打开了一扇通往人工智能世界的大门。

        前些天发现了一个巨牛的人工智能学习网站:前言 – 人工智能教程通俗易懂,风趣幽默,忍不住分享一下给大家。

目录

🎯将crate发到Crate.io

🎃编写有用的文档注解

✨常用(文档注释)部分

✨文档注释作为测试

✨注释包含项的结构

🎃使用pub use 导出合适的共有API

🎃创建create.io账户

🎃向新crate添加元信息

🎃发布到Crate.io

🎃使用cargo yank 从Crate.io弃用版本


在 Rust 中 发布配置release profiles)文件是预定义和可定制的,它们包含不同的配置,允许程序员更灵活地控制代码编译的多种选项。每一个配置都相互独立。

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

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

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

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

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

[profile.dev]opt-level = 0[profile.release]opt-level = 3

  opt-level 设置控制 Rust 会对代码进行何种程度的优化。这个配置的值从 0 到 3。越高的优化级别需要更多的时间编译,所以如果你在进行开发并经常编译,可能会希望在牺牲一些代码性能的情况下减少优化以便编译得快一些。因此 dev 的 opt-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 设置为 1,Cargo 会比默认进行更多的优化,但是没有发布构建那么多。

🎯将crate发到Crate.io

Rust 和 Cargo 有一些帮助他人更方便地找到和使用你发布的包的功能。我们将介绍一些这样的功能,接着讲到如何发布一个包。

🎃编写有用的文档注解

        准确的包文档有助于其他用户理解如何以及何时使用它们,所以花一些时间编写文档是值得的。第三章中我们讨论了如何使用双斜杠 // 注释 Rust 代码。Rust 也有特定的用于文档的注释类型,通常被称为 文档注释documentation comments),它们会生成 HTML 文档。这些 HTML 展示公有 API 文档注释的内容,它们意在让对库感兴趣的程序员理解如何 使用 这个 crate,而不是它是如何被 实现 的。

        文档注释使用三斜杠 /// 而不是双斜杠以支持 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}

        这里,我们提供了一个 add_one 函数工作的描述,接着开始了一个标题为 Examples 的部分,和展示如何使用 add_one 函数的代码。可以运行 cargo doc 来生成这个文档注释的 HTML 文档。这个命令运行由 Rust 分发的工具 rustdoc 并将生成的 HTML 文档放入 target/doc 目录。

✨常用(文档注释)部分

 crate 作者经常在文档注释中使用的部分有:

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

大部分文档注释不需要所有这些部分,不过这是一个提醒你检查调用你代码的用户有兴趣了解的内容的列表。

✨文档注释作为测试

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

Doc-tests my_craterunning 1 testtest src/lib.rs - add_one (line 5) ... oktest result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.27s

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

✨注释包含项的结构

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

//! # My Crate//!//! `my_crate` is a collection of utilities to make performing certain//! calculations more convenient./// Adds one to the number given.// --snip--

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

🎃使用pub use 导出合适的共有API

        公有 API 的结构是你发布 crate 时主要需要考虑的。crate 用户没有你那么熟悉其结构,并且如果模块层级过大他们可能会难以找到所需的部分。

        你的结构可能是一个包含多个层级的分层结构,不过这对于用户来说并不方便。这是因为想要使用被定义在很深层级中的类型的人可能很难发现这些类型的存在。他们也可能会厌烦要使用 use my_crate::some_module::another_module::UsefulType; 而不是 use my_crate::UsefulType; 来使用类型。

        好消息是,即使文件结构对于用户来说 不是 很方便,你也无需重新安排内部组织:你可以选择使用 pub use 重导出(re-export)项来使公有结构不同于私有结构。重导出获取位于一个位置的公有项并将其公开到另一个位置,好像它就定义在这个新位置一样。

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

        注意 PrimaryColor 和 SecondaryColor 类型、以及 mix 函数都没有在首页中列出。我们必须点击 kinds 或 utils 才能看到它们。

        另一个依赖这个库的 crate 需要 use 语句来导入 art 中的项,这包含指定其当前定义的模块结构。示例展示了一个使用 art crate 中 PrimaryColor 和 mix 项的 crate 的例子:

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 模块。art crate 的模块结构相比使用它的开发者来说对编写它的开发者更有意义。其内部结构并没有对尝试理解如何使用 art crate 的人提供任何有价值的信息,相反因为不得不搞清楚所需的内容在何处和必须在 use 语句中指定模块名称而显得混乱。

🎃创建create.io账户

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

$ cargo login abcdefghijklmnopqrstuvwxyz012345

        这个命令会通知 Cargo 你的 API token 并将其储存在本地的 ~/.cargo/credentials 文件中。注意这个 token 是一个 秘密secret)且不应该与其他人共享。如果因为任何原因与他人共享了这个信息,应该立即到 crates.io 撤销并重新生成一个 token。

🎃向新crate添加元信息

        比如说你已经有一个希望发布的 crate。在发布之前,你需要在 crate 的 Cargo.toml 文件的 [package] 部分增加一些本 crate 的元信息(metadata)。

        首先 crate 需要一个唯一的名称。虽然在本地开发 crate 时,可以使用任何你喜欢的名称。不过 crates.io 上的 crate 名称遵守先到先得的分配原则。一旦某个 crate 名称被使用,其他人就不能再发布这个名称的 crate 了。请搜索你希望使用的名称来找出它是否已被使用。如果没有,修改 Cargo.toml 中 [package] 里的名称为你希望用于发布的名称,像这样:

[package]name = "guessing_game"

        即使你选择了一个唯一的名称,如果此时尝试运行 cargo publish 发布该 crate 的话,会得到一个警告接着是一个错误:

$ cargo publish Updating crates.io indexwarning: 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.ioCaused 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 用途的描述和用户可能在何种条款下使用该 crate 的 license。在 Cargo.toml 中添加通常是一两句话的描述,因为它将在搜索结果中和你的 crate 一起显示。对于 license 字段,你需要一个 license 标识符值license identifier value)。Linux 基金会的 Software Package Data Exchange (SPDX) 列出了可以使用的标识符。例如,为了指定 crate 使用 MIT License,增加 MIT 标识符:

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

        如果你希望使用不存在于 SPDX 的 license,则需要将 license 文本放入一个文件,将该文件包含进项目中,接着使用 license-file 来指定文件名而不是使用 license 字段。

🎃发布到Crate.io

        现在我们创建了一个账号,保存了 API token,为 crate 选择了一个名字,并指定了所需的元数据,你已经准备好发布了!发布 crate 会上传特定版本的 crate 到 crates.io 以供他人使用。

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

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

$ 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 从Crate.io弃用版本

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

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

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

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

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

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

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



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。