昨天我们用iterator
优化了我们的minigrep
小工具
今天往下学~
Cargo
以及Crates.io
目前我们仅是会一些基础的指令,比如run/build/test
,我们将在这一章学到一些较深入的cargo
相关的知识。
比如:
release profiles
)来自定义构建。crates.io
中。workspaces
)来组织大型项目。crates.io
中下载库。cargo
拓展自定义的指令。Cargo
的官方链接:
Introduction - The Cargo Bookdoc.rust-lang.org/cargo/
release profiles
是需要在构建之前配置的,我们可以配置多个文件来使用不同的配置项.
比如前端工程化有dev
和prod
两种模式.
而在rust
中也差不多,有dev
和release
两种.
当我们运行cargo build
的时候就是dev
模式,而执行cargo build --release
则是release
模式.
这俩模式其实cargo
已经有一套较好的默认值了,这也就是为什么我们不需要配置cargo.toml
就可以执行上面两个指令的原因.
可以看到构建输出的内容是会展示是dev
还是release
的.
现在我们来看下如何单独配置它们的项
首先找到我们的Cargo.toml
文件,所有的配置都是放在这个文件中的,而要单独配置某种mode
只需要单独开个sections
也就是区域就行了,比如下面这样
默认配置的opt-level
也是这样的
opt-level
的范围是0 ~ 3
,表示编译器准备采取什么等级来优化代码.
等级越高则相对的编译需要的时间就越长,毕竟需要优化的东西更多.
开发模式我们只是看下效果,并不需要考虑优化之类的,所以给个0
就好.
而发布模式由于代码是准备上线了,上线后也不会怎么去改动了,所以只需要编译一次,能优化自然就优化掉.
当然这只是推荐的,如果你想在开发模式就看到最终效果,那你也可以把profile.dev
的opt-level
改为3
.
就介绍到这里,想要什么配置可以看下官方提供的文档
Profiles - The Cargo Bookdoc.rust-lang.org/cargo/reference/profiles.html
crate
到crates.io
中和我们发布库到npm
挺像的.
不过在发布前,我们得有要发布的东西才行.
我们先创建一个项目,就放一些用于计算的方法吧
在lib.rs
中
然后我们来测试下
也是正常之后我们就可以准备给我们的代码加上注释了
一个库中的代码应该是得有文档注释的,比如标准库里的
以args
方法为例子,可以看到有一堆的注释,而这些注释是用///
三斜杠来标注的.
rust
将他们称为: 文档注释,它们可以帮助是用这些个方法的开发者知道这个方法要怎么用,是干嘛的.
而这些注释里的例子也就是cargo test
时出现在最底部的那个
是的,注释里的东西也是可以被test
感知的.
我们直接来试一下
然后我们可以运行cargo doc --open
将文档以html
的形式输出到浏览器中
是不是非常的方便~
实际上cargo
是创建了一个target/doc
的文件夹
这个文档注释是支持markdown
的语法的,所以为了好看些可以加一些markdown
的东西,来调整下结构.
另外官方还提供了几个sections
用来区分场景,比如我们前面写的# Exmaples
# Panics
: 这个方法可能会引起panic
,如果你想确保你的代码不会因为这个方法而panic
,那么请在xxx
场景下不要使用该方法# Errors
: 这个方法返回的是一个Result
的类型,而这个E
在什么场景下是什么类型,什么情况下会出现# Safety
: 如果这个方法是unsafe
的,那么就需要说清楚为什么是不安全的,以及提供替代方案.大部分情况下我们都不会使用,不过有需要时还是尽量加上,因为对于用户来说体验感会好很多
另外我们还可以用//!
在文件头注释这个crate
里有哪些module
,毕竟在入口就有指引是一件很舒服的事情.
不过需要注意//!
注释得和代码之间隔一个空行.
先不说rust
,说一个开发库的常态.
以前端为例子
我们开发者开发一个库,为了可维护性,我们会把这个库里的文件按各种不同点拆分,拆分成十几个文件等.
这对于开发者来说可维护性就上去了, 但是对于用代码的人来说就是个灾难: 入口有好几个, 方法一个套一个.
这也就是为什么大多数库都以一个index
文件作为入口, 其实都是为了使用者可以方便的使用.
他们一般会把各种入口都import
到index
文件中,然后export
出去.
回到rust
中,想一下如果不这么做我们要怎么写,大概率会是这样
lib.rs
中
main.rs
中
很冗长,所以rust
团队提供了重导的方式,关键词pub use
lib.rs
中
main.rs
中
这样就简写了很多.
另外这一点也是会暴露在文档里的
我们可以直接点击c
进入c
这个mod
中.
Cargo.toml
文件和配置package.json
差不多,在发布前,我们得配置下这个库的名字作者以及开源协议等.
具体有哪些metadata
可以看这里: Introduction - The Cargo Book
既然我们代码有了,注释也有了,配置文件也配置完了并且测试正常,那这个时候就可以准备发布了.
不过在这之前,我们得有一个自己的账号.
我们用github
账号登录即可.
然后配置下自己的邮箱
https://crates.io/settings/email-notifications
验证完邮箱之后就可以拿我们的token
了
https://crates.io/settings/tokens
拿到token
之后我们到终端登陆下
当然,如果你的crates.io
没有更新会先帮你更新,记得换源或者登梯子.
crates.io
上登录成功后我们还是不要急着发布.
我们先到crates.io
官网看下我们的包是否重名了
并没有,那么就可以放心发布了
不过我还是遇到了一个错误
我的代码中有改动没有同步到git
上,但是我这个项目压根没有git
仓库,所以我直接--allow-dirty
跳过了
然后到官网搜索一下
这样就成功啦~
如果到时候需要更新,直接改下Cargo.toml
里的version
然后重新cargo publish
即可.
rust
并不允许我们直接把库给废弃删除,我们只能废弃之前的版本,这样其它开发者就不会去使用这个版本.
我们直接废弃到我们目前的calc_tool
,由于这个包只是个demo
,所以并不打算要.
可以看到被0.1.0
废弃了
如果反悔了,可以在终端输入
这样就会恢复了
Cargo Workspaces
一些大型的框架都会有多个子包比如vue
的core
[12]包,这是一种国外很火的概念,叫monorepo
,就是多包管理.前端可以使用yarn + lerna
[13]或者pnpm
[14]来管理.
而在rust
中,Cargo
提供了管理多包的方式,叫workspaces
.
workspaces
我们先创建一个add
文件夹
然后我们在add
文件夹中直接创建一个Cargo.toml
文件
这个Cargo.toml
将作用于整个包
然后我们创建一个member
创建完之后我们直接终端输入cargo build
可以看到adder
里并没有target
,即使是跑到adder
里面去执行build
指令也是只有add
里有target
.
为什么要统一输出呢?因为这些个包之间大概率是存在关联引用关系的,如果每个包里都有自己的target
,那么就有可能存在重复打包的问题.
workspace
中创建第二个包先改下add/Cargo.toml
然后终端
我们创建了一个library crate
现在的结构变成了这样
然后我们给add_one
加点料之后在adder
里面引用它
接着要在adder
里实现引用它
我们先去到adder/Cargo.toml
中,add_one
此时对于adder
来说就是一个library crate
,和通过crates.io
引用的其实没什么差别
然后我们就可以在main.rs
中使用add_one
这个方法了(当然得先use
)
终端正常输出
当然,如果你只想输出adder
这个binary crate
包的内容,可以使用cargo run -p adder
,用p
指令来指定某一个binary crates
编译运行.
还记得我们的目录么?
我们只有一个Cargo.lock
文件,这也就是意味着所有外部引入的包都会共用同一个版本.
这样做可以避免多个版本带来的兼容性问题.
我们来试下把rand
这个crate
引入到add_one
或者adder
里面
然后我们在文件中使用
接着cargo run
一下
也是没问题,来看下Cargo.lock
文件中的记录
不过有一点需要注意,那就是只有在其中一个包中引入了才能使用这个包.
比如我们在adder
的包中引入了,但是没有在add_one
中引入,这时如果在add_one
中直接使用就会报错.
所以如果想在add_one
中使用,那么也需要在add_one/Cargo.toml
文件中引入才行.
至于直接加在全局的Cargo.toml
这样的操作是不行的,会报错.
其实add_one/lib.rs
已经有测试代码了,毕竟我们是new add_one --lib
的方式创建的.
那么我们直接cargo test
,它将把所有包中的测试代码都执行一遍.
当然,如果你只是想测试某个包中的测试代码,也可以用p
指令指明是哪个包,这里就不演示了,和上面cargo run -p xxx
的用法一致.
这个指令同样适用于发布creates
的时候,需要注意发布的时候要每个包单独发布才行.
install
指令下载binary crates
库我们试过了,准确来说是依赖,我们可以通过Cargo.toml
文件中[dependencies]
引入.
而binary crates
我们就没遇到过了.
其实binary crates
并不是用在我们的代码中的.
比如ripgrep
[20],它只是一个工具,可以用来匹配而已.
我们来下载下,下载完之后默认是放到user/.cargo/bin
里面
可以看到是正常下载了.
Cargo
拓展自定义指令其实和npx
一样,你可以直接通过package.json
中配置bin
选项来自定义指令.
官方没有给个例子....
所以这里只能简单的说下
如果你通过install
下载的binary crates
命名是cargo-xxx
,那么你就可以直接在终端cargo xxx
跑这个指令调动这个binary
.
比如
然后我们直接cargo --list
查找当前可用指令,发现这个cargo-miri
可以直接使用cargo miri
来调用.
今天的量也是挺多的,不过并不是晦涩难懂的特性概念等.
发布一个自己的包还是很有趣很有成就的.
发布于 2022-12-29 18:01・IP 属地广东