如何用 Cargo 管理 Rust 工程系列 丙

以下内容为本人的学习笔记,如需要转载,请声明原文链接微信公众号「ENG八戒」mp.weixin.qq.com/s/viSsCaFR2...

添加依赖项

前面已经提到过在 cargo 配置文件 Cargo.toml 中如何手动添加工程依赖项,cargo 同样提供了 add 指令用于快捷添加依赖项,比如添加随机数生成包 rand

ini 复制代码
$ cargo add rand
    Updating crates.io index
      Adding rand v0.8.5 to dependencies.
             Features:
             + alloc
             + getrandom
             + libc
             + rand_chacha
             + std
             + std_rng
             - log
             - min_const_gen
             - nightly
             - packed_simd
             - serde
             - serde1
             - simd_support
             - small_rng
    Updating crates.io index
$ cat Cargo.toml 
[package]
name = "hello_rust"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rand = "0.8.5"

添加完依赖项 rand 后,然后看看编译执行过程

scss 复制代码
$ cargo run
  Downloaded cfg-if v1.0.0
  Downloaded rand_chacha v0.3.1
  Downloaded ppv-lite86 v0.2.17
  Downloaded rand_core v0.6.4
  Downloaded rand v0.8.5
  Downloaded getrandom v0.2.11
  Downloaded libc v0.2.150
  Downloaded 7 crates (910.0 KB) in 4.12s
   Compiling libc v0.2.150
   Compiling cfg-if v1.0.0
   Compiling ppv-lite86 v0.2.17
   Compiling getrandom v0.2.11
   Compiling rand_core v0.6.4
   Compiling rand_chacha v0.3.1
   Compiling rand v0.8.5
   Compiling hello_rust v0.1.0 (~/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 20.75s
     Running `target/debug/hello_rust`
Hello rust's world!

看到编译过程 cargo 会先从 crates.io 下载依赖项源码,然后编译依赖项源码,最后才编译本地工程代码。但是刚刚用 cargo add 指令添加的依赖项是 rand,为什么多了这么多其它内容?因为 rand 也有依赖项,为了编译 rand 也需要先把它的依赖项源码下载下来。

在工程被首次构建后,发现工程目录下多了个 Cargo.lock 文件。这个文件是为了更具体地描述 Cargo.toml 文件中所添加的依赖项,它由 cargo 自动维护,开发人员不应该手动修改它。

看看构建之后的 Cargo.lock

ini 复制代码
$ cat Cargo.lock 
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3

[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"

[[package]]
name = "getrandom"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
dependencies = [
 "cfg-if",
 "libc",
 "wasi",
]

[[package]]
name = "hello_rust"
version = "0.1.0"
dependencies = [
 "rand",
]

[[package]]
name = "libc"
version = "0.2.150"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c"

[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"

[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
 "libc",
 "rand_chacha",
 "rand_core",
]

[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
 "ppv-lite86",
 "rand_core",
]

[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
 "getrandom",
]

[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"

为什么还需要更多的依赖项描述呢?因为 Cargo.toml 文件中填写的依赖项其自身所依赖的包可能会更新,为避免依赖项各自更新后不兼容导致的编译错误,需要更多的详细描述对依赖项进行身份固化,比如依赖项所依赖的的依赖包名、版本、来源、校验码等,确保循环依赖在后期的再次编译中不会突然报错。

同时,Cargo.lock 文件仅会在 package 工程首次编译构建时生成,如果依赖项被更新了,再次利用 cargo 重新构建编译时会自动维护 Cargo.lock 文件内容。

检查代码

开发软件过程中,往往要不断迭代升级,频繁修改,又为了在开始下一部分编码之前,先检查当前编写代码的正确性,无论是语法还是逻辑层面都需要。由于功能逻辑未必开发完整,中途检查更多的是侧重于编译完整性,也就是语法层面,只要能编译顺利通过即可,这并不需要最终的输出文件。对于逻辑功能的验证,才需要实际运行最终输出文件。

编译时输出文件的大小直接影响到投入的等待检查时间,工程代码少,编译输出的文件较小,耗时也短;但是面对庞大项目工程时,为了加快开发中途的检查,那么 cargo 有没有提供这方面的选项工具帮助跳过输出文件这最后一步呢?

Cargo 提供了 check 指令用于检查 package 工程代码和依赖项相关的问题。

为了演示,先用 cargo clean 将当前工程的中间文件清除,然后执行 cargo check 检查代码

scss 复制代码
$ cargo clean
$ cargo check
    Checking hello_rust v0.1.0 (~/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.07s
$ cargo clean
$ cargo build
   Compiling hello_rust v0.1.0 (~/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.23s

从上面的输出来看,和 cargo build 编译指令相比,cargo check 的输出更快。

为了更详细了解 cargo build 和 cargo check 的耗时,我们重新用 time 指令来对比一下

scss 复制代码
$ cargo clean
$ time cargo check
    Checking hello_rust v0.1.0 (~/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 0.80s

real    0m0.894s
user    0m0.109s
sys     0m0.297s
$ cargo clean
$ time cargo build
   Compiling hello_rust v0.1.0 (~/hello_rust)
    Finished dev [unoptimized + debuginfo] target(s) in 1.17s

real    0m1.260s
user    0m0.266s
sys     0m0.453s

从上面的统计数据来看,cargo check 执行速度明显要快很多,而这还只是编译构建简单的 hello world 程序。如果换做普通规模的软件工程,cargo check 的执行速度优势想必会更明显。

相关推荐
许野平23 分钟前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
‍。。。11 小时前
使用Rust实现http/https正向代理
http·https·rust
Source.Liu11 小时前
【用Rust写CAD】第二章 第四节 函数
开发语言·rust
monkey_meng11 小时前
【Rust中的迭代器】
开发语言·后端·rust
余衫马11 小时前
Rust-Trait 特征编程
开发语言·后端·rust
monkey_meng11 小时前
【Rust中多线程同步机制】
开发语言·redis·后端·rust
hikktn19 小时前
如何在 Rust 中实现内存安全:与 C/C++ 的对比分析
c语言·安全·rust
睡觉谁叫~~~19 小时前
一文解秘Rust如何与Java互操作
java·开发语言·后端·rust
音徽编程19 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust
梦想画家1 天前
快速解锁Rust Slice特性
开发语言·rust·slice