4

Cargo命令及其扩展

 1 year ago
source link: https://jasonkayzk.github.io/2022/11/23/Cargo%E5%91%BD%E4%BB%A4%E5%8F%8A%E5%85%B6%E6%89%A9%E5%B1%95/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

用过Rust中Cargo工具的,都会对其赞叹不已;

Cargo 不光支持代码格式化、构建、项目管理,还具备良好的可扩展性,同时也支持第三方的插件工具;

本文讲述了一些常见的Cargo命令,同时讲述了如何编写一个Cargo扩展插件;

Cargo命令及其扩展

Cargo概述

具体Cargo相关内容的学习,可以通过下面的网站学习:

在阅读本文之前,强烈建议你先完成上面的学习或至少了解Rust中Cargo的基本使用;

Cargo不仅支持内建(built-in)的子命令,比如最常用的:

  • cargo new
  • cargo build
  • cargo run
  • cargo clippy

同时,Cargo 也支持第三方的插件工具,下面罗列了些比较常用的cargo plugin:

  • cargo-expand:在编译时展开标准宏和继承宏(derive,过程宏的一种)展开信息,便于调试宏;
  • cargo-update:更新你所安装的cargo插件;
  • cargo-graph:生成工程的依赖关系图;
  • cargo-deb:把当前工程编译成deb包,Debian/Ubuntu;

这些插件都可以通过如下命令来安装到本地,比如:

$ cargo install cargo-expand

官方列出了一些常用的第三方插件:

Cargo常用插件(Plugins)

这里推荐一些常用的 Cargo 插件;

cargo-update

更新 Cargo.lock 中定义的依赖包的版本;

cargo-vendor

和 go 中的 vendor 模式一样,将项目的依赖包都缓存到本项目的 vendor 目录下;

这个特性对于 CI/CD 很有用处,不再需要每次自动编译时重新从 crates.io 下载源代码;

使用方法也很简单:只需要在根目录运行 cargo vendor 命令即可;

然后该命令会提醒我们修改本项目的 cargo config 文件:

$ mkdir .cargo
$ echo > .cargo/config << EOF
[source.crates-io]
replace-with = "vendored-sources"

[source.vendored-sources]
directory = "vendor"
EOF

但是,如果项目中依赖的包比较多,最终 vendor/ 可能会比较大;

cargo-edit

这个插件提供了三个命令:

  • cargo add:Cargo.toml 加入新的包;
  • cargo rm:从 Cargo.toml 中移除包;
  • cargo upgrade:升级 Cargo.toml 中的包到最新版,同时会修改 Cargo.toml 中定义的依赖包的版本号;与之相对应的 cargo update 命令只会更新 Cargo.lock 这个文件中定义的版本;

cargo-outdated

用于展示工作区中有哪些依赖包是过期的;

$ cargo outdated
Name                            Project  Compat  Latest  Kind    Platform
----                            -------  ------  ------  ----    --------
miniz_oxide_c_api->miniz_oxide  0.2.2    0.2.3   0.2.3   Normal  ---

cargo-script

直接以脚本的方式运行 rust 程序,安装:

$ cargo install cargo-script

比如,time.rs 文件的内容是:

use std::time::SystemTime;

fn main() {
  println!("now: {:?}",SystemTime::now());
}

现在执行这个文件:

$ cargo script time

cargo-watch

用于监控源码目录的更改,并运行指定的 cargo 命令;

比如,代码更改后自动重新编译并运行服务器代码:

$ cargo watch -x 'run --bin http_server'

该命令可以方便地与 vim/emacs 以及其它 IDE 集成;

cargo-audit

audit 工具可以检测 rust 项目中的依赖包是否有已知安全漏洞;

$ cargo install cargo-audit

然后在 rust 项目根目录运行一下:

$ cargo audit

即可扫描项目中的包依赖安全问题,并生成报告;

cargo-tree

tree 命令可以树形输入 crate 依赖关系;

$ cargo install cargo-tree

然后在项目根目录运行:

$ cargo tree                 
cargo-date v0.1.0 (/Users/kylinkzhang/self-workspace/rust-learn)
└── chrono v0.4.23
    ├── iana-time-zone v0.1.53
    │   └── core-foundation-sys v0.8.3
    ├── num-integer v0.1.45
    │   └── num-traits v0.2.15
    │       [build-dependencies]
    │       └── autocfg v1.1.0
    │   [build-dependencies]
    │   └── autocfg v1.1.0
    ├── num-traits v0.2.15 (*)
    └── time v0.1.44
        └── libc v0.2.137

cargo-count

count 命令用于统计 rust 源代码行数,安装:

$ cargo install cargo-count

查看一下当前项目:

$ cargo count --all
Gathering information...
         Language  Files  Lines  Blanks  Comments  Code
         --------  -----  -----  ------  --------  ----
         TOML      1      14     2       1         11
         D         4      30     6       0         24
         Rust      29     10994  1104    956       8934
         Python    2      79     24      8         47
         --------  -----  -----  ------  --------  ----
Totals:            36     11117  1136    965       9016

cargo-fix

常用的代码自动修正工具,基于 Rust 编译器以及像 clippy 这样的工具的提示.

$ cargo install cargo-fix

其他插件

还有一些其他插件:

  • cargo-asm:展示 rust 函数生成的汇编代码;
  • cargo-bloat:计算 rust 各部分代码在可执行文件中占的空间大小;
  • cargo-sweep:清除没用的编译结果文件;
  • cargo-geiger:检测所使用crate中的 unsafe 代码;

开发一个Cargo插件

上面分享了一些第三方 Cargo 插件,那么我们如何编写自己的 Cargo 插件呢?

官方文档中是有说明的:

当我们输入:

cargo ${command}

实际上Cargo 会在 $PATH 下面寻找 cargo-${command} 可执行文件;

因此,开发一个 Cargo 插件非常简单,我们只需要将该可执行文件命名为 cargo-${command} 即可!

下面来看一个例子,cargo-date 用于打印当前的系统时间;

首先,使用 Cargo 创建一个项目:

$ cargo new cargo-date

并增加配置:

Cargo.toml

[package]
name = "cargo-date"
version = "0.1.0"
edition = "2018"

+ [[bin]]
+ name = "cargo-date"
+ path = "src/main.rs"

+ [dependencies]
+ chrono = "0.4"

随后修改 main.rs 增加实现:

src/main.rs

use chrono::Local;

fn main() {
    let date = Local::now();
    println!("{}",date.format("[%Y-%m-%d] [%H:%M:%S]"));
}

最后,编译并安装:

$ cargo install --path .

默认安装在:~/.cargo/bin 目录下:

$ ll ~/.cargo/bin 
total 270224
drwxr-xr-x  19 kylinkzhang  staff   608B 11 23 10:54 .
-rwxr-xr-x   1 kylinkzhang  staff   596K 11 23 10:54 cargo-date
-rwxr-xr-x   1 kylinkzhang  staff   4.1M 11 23 10:22 cargo-install-update
-rwxr-xr-x   1 kylinkzhang  staff   1.4M 11 23 10:22 cargo-install-update-config
-rwxr-xr-x   1 kylinkzhang  staff   7.0M  8 14 14:31 cargo-expand
...

之后,我们就可以执行这个插件了:

$ cargo date
[2022-11-23] [11:52:09]

附录

文章参考:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK