Rust入门(十):项目发布

news2024/11/29 16:36:44

发布配置

在 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 并在浏览器中打开

 的  函数所渲染的文档注释 HTML

示例中使用了 # 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 用户理解你的代码组织:

crate 整体注释所渲染的 HTML 文档

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 的人来说将会是大为不同的体验。

Rendered documentation for the  crate with the re-exports on the front page

发布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 的工具来搜索文件了

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

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

相关文章

Linux常用命令——netstat命令

在线Linux命令查询工具(http://www.lzltool.com/LinuxCommand) netstat 查看Linux中网络系统状态信息 补充说明 netstat命令用来打印Linux中网络系统的状态信息,可让你得知整个Linux系统的网络情况。 语法 netstat(选项)选项 -a或--all:显示所有连…

ASP.NET Core 3.1系列(23)——使用AutoMapper实现实体之间的相互转换

1、前言 在之前的博客中,我们通过EFCore的Scaffold-DbContext命令一键生成数据库实体类。但在实际业务中,实体类并不能很好地应对所有情况。例如前端页面只需要展示某张表中部分字段的信息,这时如果直接将实体类集合返回给前端界面&#xff…

【C进阶】指针和数组综合题

家人们欢迎来到小姜的世界&#xff0c;<<点此>>传送门 这里有详细的关于C/C/Linux等的解析课程&#xff0c;家人们赶紧冲鸭&#xff01;&#xff01;&#xff01; 客官&#xff0c;码字不易&#xff0c;来个三连支持一下吧&#xff01;&#xff01;&#xff01;关注…

设计模式-工厂模式(Java)

工厂方法模式 工厂方法模式&#xff1a;Factory Method 事物是发展的&#xff0c;随着事物的不断发展&#xff0c;原有的对象会随着发展不断变化&#xff0c;或增或减。 工厂方法模式提供的一种封装机制&#xff0c;隔离出了那些易变动的对象。这个时候需求的变动不再影响之前…

Mybatis-Plus中的条件查询-DQL编程

条件构造器 | MyBatis-Plus 当需要进行一些复杂的条件查询时&#xff0c;则需使用wrapper&#xff0c;来编辑这些条件 1、条件查询 ①allEq() 即是where后面的等于"",该方法的后的所有参数都会被以"and"的形式进行连接 QueryWrapper qw1 new QueryWra…

Go语言设计与实现 -- 栈空间管理

寄存器 图片来自于面向信仰编程 Go 语言的汇编代码包含 BP 和 SP 两个栈寄存器&#xff0c;它们分别存储了栈的基址指针和栈顶的地址&#xff0c;栈内存与函数调用的关系非常紧密&#xff0c;我们在函数调用一节中曾经介绍过栈区&#xff0c;BP 和 SP 之间的内存就是当前函数的…

数智化转型进入“精装时代”,容联云助力千行百业加速上云用数赋智

随着产业数字化向前推进&#xff0c;企业引入数字技术的需求和热情十分充足&#xff0c;但要把技术下沉到市场中&#xff0c;还存在一个关键的矛盾&#xff1a;交付能力。千行百业&#xff0c;尤其是传统实体经济从业者&#xff0c;对数智化所需要的5G、IOT、AI、大数据、云计算…

canvas入门教学(5)运动小球屏保特效与下雪特效渲染

本节我们来学习两个例子,第一个例子是如下图这样的,全屏各色各样的小球随机运动,碰撞到屏幕边缘再反弹回来的特效,我们一步一步带着大家来学习这个canvas应用。 首先呢,基于上一个教程的例子,我们需要基础的构建圆, 上节教程在这里 并且呢我们要重复的多次的构建半径…

OVN实验----L2互通

概述 尽量少贴概念&#xff0c;只同步一些必要的名词。 central: 可以看做中心节点&#xff0c;central节点组件包括OVN/CMS plugin、OVN Northbound DB、ovn-northd、OVN Southbound DB。 hypervisor: 可以看做工作节点&#xff0c;hypervisor节点组件包括ovn-controller、ov…

Target 塔吉特的4种商品编码

Target塔吉特共有4种商品编码&#xff1a;TCIN、DPCI、UPC、SKU&#xff0c;其中DPCI、UPC和TCIN在Target系统中是唯一的ID。在target.com中查看商品时&#xff0c;在任一个商品中下拉进入到商品详情页&#xff08;Item/Detail/Specifications&#xff09;中都可以看到该商品的…

13_5、Java的IO流之转换流的使用

一、转换流涉及到的类&#xff1a;都是字符流InputStreamReader&#xff1a;将输入的字节流转换为输入的字符流。解码&#xff1a;字节、字节数组 ————>字符串、字符数组OutputStreamWrite&#xff1a;将输出的字符流转换为输出的字节流。编码&#xff1a;字符串、字符数…

Linux 网络探测和安全审核工具 nmap 应用实践

对于 nmap&#xff0c;相信很多安全运维人员并不陌生&#xff0c;它曾经在电影《黑客帝国》中出现过&#xff0c; 是黑客和网络安全人员经常用到的工具&#xff0c;本文重点介绍下此工具的实现原理和使用技巧。 nmap 和 Zenmap 简介 nmap 是一款开源免费的网络发现工具&#…

2023兔年大吉HTML,兔兔动态代码「兔了个兔」

文章目录一.2023兔年大吉HTML&#xff0c;兔兔动态代码「兔了个兔」1.1 资源获取和效果预览二.代码讲解&#xff08;主要代码&#xff09;1.1 背景加圆圈圈1.2.兔兔和提示字1.3 JavaScript控制动态一.2023兔年大吉HTML&#xff0c;兔兔动态代码「兔了个兔」 1.1 资源获取和效果…

如何在游戏中实现飘花和落叶效果

本文首发于微信公众号&#xff1a; 小蚂蚁教你做游戏。欢迎关注领取更多学习做游戏的原创教程资料&#xff0c;每天学点儿游戏开发知识。嗨&#xff01;大家好&#xff0c;我是小蚂蚁。今天这篇文章分享一下如何在游戏中实现飘花和落叶的效果&#xff0c;在游戏背景中加入它们&…

FPGA:数字电路简介

文章目录数字电路的历史电子管时代晶体管时代半导体集成电路IC 时代IC的发展阶段EDA (Electronics Design Automation) 技术数字集成电路的分类数字集成电路的集成度分类从器件导电类型不同从器件类型不同数字电路的历史 数字电路是数字计算机和自动控制系统的基础&#xff0c…

[JavaEE初阶] 线程安全问题之内存可见性问题----volatile

读书要趁黑发早,白首不悔少当时 文章目录1. 什么是内存可见性问题2. 避免内存可见性问题-----volatile(易变的)3. 需要注意的点总结1. 什么是内存可见性问题 在线程A在读一个变量的时候,另一个线程B在修改这个变量,所以,线程A读到的值不是修改之后的,是一个未更新的值,读到的值…

先行“蜀道”, 四川农信核心系统分布式转型

作者&#xff1a;四川省农村信用社联合社 张朝辉 桂俊鸿 来源:《金融电子化》 随着四川省联社党委提出“合规银行、智慧银行、主力军银行”三大银行战略。作为四川省业务规模最大的银行业金融机构、全国农信系统“排头兵”的四川农信积极响应&#xff0c;率先于 2018 年 9 月完…

mysql磁盘io

1、磁盘的一些概念 1.1、盘片、片面 和 磁头 硬盘中一般会有多个盘片组成&#xff0c;每个盘片包含两个面&#xff0c;每个盘面都对应地有一个读/写磁头。受到硬盘整体体积和生产成本的限制&#xff0c;盘片数量都受到限制&#xff0c;一般都在5片以内。盘片的编号自下向上从…

Viper渗透框架

文章目录Viper 简介Viper 安装脚本安装手动安装切换到 root 用户执行命令Kali 安装 docker (我已经安装过了&#xff0c;不做演示&#xff0c;命令依次执行即可)安装 docker-compose设置安装目录生成安装目录&#xff0c;并进入安装目录生成 docker-compose.yml设置登录密码写入…

【C++常用算法】STL基础语法学习 | 拷贝算法替换算法

目录 ●copy ●replace ●replace_if ●swap ●copy 1.功能描述&#xff1a; 将容器内指定范围的元素拷贝到另一容器中 2.查看copy定义下底层代码的函数原型&#xff1a; 3.向deque容器中插入10~50五个数&#xff0c;将这五个数拷贝到另一个指定容器中并输出。 #include&…