前言
上一篇我们讲了Cargo运行测试
Cargo运行实例
Cargo工作空间
当然,Cargo也能够进行扩展,合并外部工具以增强开发体验,在设计上,其可扩展性已经达到非常丰富和恰当的程度。Cargo可以通过简单的二进制名称(binary-name)语法调用开发人员所创建的命令行工具。
在这一节中,我们就来看看其中的一些经常用得上的工具来帮助我们提升代码的编写效率和可读性。
那么本篇内容涉及子命令定制与安装
用 Clippy来 Linting 代码
子命令定制与安装
为Cargo定制化命令行工具在结构上归为Cargo的子命令(subcommands)范畴。这些工具通常是二进制文件,主要来自于GitHub,或者本地项目目录,都可以通过cargo install 或者进行安装。
下面我们看一个实例cargo-watch tool。
cargo-watch
这里的watch肯定不是手表,显然是岗哨观察的意思。
每当对代码进行更改时,通过在后台自动生成项目,cargo-watch可以有助于缩短修复、编译和运行周期。
默认情况下,该工具只运行Rust的类型检查器(cargo check命令),而不进行代码生成阶段(这需要时间),便缩短了编译时间;还可以使用-x flag 提供一个定制命令来代替cargo check。
我们可以通过运行cargo install cargo-watch来安装cargo-watch,
然后在任何cargo项目中,都可以通过调用cargo watch来运行它。
现在,无论何时我们对项目进行更改,cargo-watch都会在后台运行cargo check并为我们重新编译项目。
在下面的代码中,做了一个拼写错误:(如图所示,将之写过pow函数的返回值类型做成i6)
cargo watch提示有问题:
在我们进行了纠正之后,Cargo watch重新编译了这个项目:
这一点非常类似于Node.js生态系统中的watchman或nodemon包。
cargo-edit
Cargo -edit子命令可以用于自动添加Cargo.toml文件的依赖项,原则上可以添加所有类型的依赖项,包括dev依赖项和build依赖项,还可以添加任何依赖项的特定版本。
该工具可以通过运行cargo install cargo-edit来安装,主要提供四个命令:cargo add
cargo rm
cargo edit
cargo upgrade
cargo-deb
这是另一个有用的社区开发的子命令,可以用来创建Debian包(.deb),以便在Debian Linux,比如Ubuntu上轻松发布Rust可执行文件;
可以通过运行cargo install cargo-deb来安装。我们将在本章末尾使用这个工具之前构建的imgtool命令行可执行文件打包成.deb包。
cargo-outdated
此命令行工具可以显示Cargo项目中过期的crate依赖项;可以通过运行cargo install cargo-outdated来安装。安装完毕后,可以通过在项目目录中运行cargo outdated来查看有哪些crate已经“老”了。
现在,这些子命令与Cargo无缝协作的方式表现为:开发人员使用命名约定创建这些二进制crate,比如Cargo -[cmd],当使用 cargo install 安装该二进制crate时,Cargo将已安装的二进制文件传递给$PATH变量,然后可以使用cargo 进行调用。
应该说,这是一种简单而有效的方式,Cargo通过社区开发的子命令来扩展自身。当然还有许多其他类似的扩展,可以在下面网址上找到所有社区管理的子命令工具列表。https://github.com/rust-lang/cargo/wiki/Third-party-cargo-subcommandsgithub.com
cargo install也用于安装任何二进制crate或在Rust中开发的可执行文件/应用程序,这些文件和程序默认安装在/home//.cargo/bin/目录。
我们将以此来安装和构建的imgtool应用程序,使其在系统范围内可用。
用 Clippy来 Linting 代码
在编程实践中,将有助于将代码写的容易维护,质量合乎一定规范的做法,称为Linting,在Rust中,相应的工具是clippy。
在本节中,我们将安装clippy并在之前建立的库中试用一下:添加一些虚拟代码,并看看clippy能给出什么建议。
在项目中使用clippy有多种方法,但本节只使用cargo clippy子命令的方式,简单起见。Clippy可以对代码进行分析,是一个编译器插件,可以访问很多编译器的内部API。要使用clippy,先运行rustup component add clippy来安装。
现在,为了演示clippy如何在代码中指出一些写的不怎样的地方,我们在之前写过的myexponent 的crate中的pow函数里面的if条件中加入了一些烂语句。
如下所示:
// myexponent/src/lib.rs
pub fn pow(base: i64, exponent: usize) -> i64 {
/// Dummy code for clippy demo
let x = true;
if x == true {
}
///
let mut res = 1;
if exponent == 0 {
return 1;
}
for _ in 0..exponent {
res *= base as i64;
}
res
}
#[cfg(test)]
mod tests {
use super::pow;
#[test]
fn minus_two_raised_three_is_minus_eight() {
assert_eq!(pow(-2, 3), -8);
}
}
此时,我们运行cargo clippy
代码对应结果如下:
不难看出,显然是说添加的语句写的太多余了,“equality checks against true are unnecessary”,并给出了改进建议“ try simplifying it as shown: `x`”。
以此可以看出,clippy还是有使用价值的,可以指出我们代码上的潜在错误和不当之处。更多的实例,可以参见:https://rust-lang-nursery.github.io/rust-clippy/master/index.html#absurd_extreme_comparisonsrust-lang-nursery.github.io
有关clippy多种方式的配置,可以直接去https://github.com/rust-lang/rust-clippygithub.com
结语
本篇所介绍的都是在现阶段比较有用的工具,同时也是后续篇章的基础。
下一篇,会探索一下Cargo的项目清单文件cargo.toml,而后再说一下如何用vscode创建一个Rust的开发环境。
主要参考和建议读者进一步阅读的文献The Rust Programming Languagedoc.rust-lang.org
Rust编程之道,2019, 张汉东
The Complete Rust Programming Reference Guide,2019, Rahul Sharma,Vesa Kaihlavirta,Claus Matzinger
Hands-On Data Structures and Algorithms with Rust,2018,Claus Matzinger
Beginning Rust ,2018,Carlo Milanesi
Rust Cookbook,2017,Vigneshwer Dhinakaran