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

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

优化输出

前面已经对 cargo package 工程编译输出了好多遍,发现编译结果打印的信息都包含了这个

复制代码
unoptimized + debuginfo

这个信息表示 cargo 默认的编译构建未做任何的优化,这样方便于调试程序执行逻辑,和最终输出的文件仍然包含大量的调试信息,估计文件大小不容乐观。可见 cargo 编译构建默认是 dev 模式,或者叫它 debug 模式。

bash 复制代码
$ ll -h target/debug/hello_rust
-rwxrwxrwx 2 user user 4.5M Nov 15 01:58 target/debug/hello_rust

默认配置下 cargo 编译构建的二进制可执行文件 hello_rust 大小高达 4.5M。这对于开发调试过程中,是没有任何问题的。但是,一旦工程开发完毕,输出的二进制可执行文件或者库文件需要发布出去时,文件大小就显得非常刺眼了,况且执行性能也是非常受目标用户关注的。

Cargo 提供了 --release 的构建选项帮助去除调试信息和优化性能,也就是所谓的 release 模式了。

为了体现 release 模式对编译后输出文件的显著影响,先来修改一下代码,加入一些其他内容

rust 复制代码
$ cat src/main.rs
use rand::Rng;

fn main() {
    println!("Hello, world!");
    let mut rng = rand::thread_rng();
    let random = rng.gen_range(1..101);
    println!("random num is {}", random);
}

这段代码添加了打印一个随机数,所以也需要给工程添加依赖项 rand

ini 复制代码
$ cargo add rand
$ 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"

再分别在 debug 和 release 模式下编译输出可执行文件

shell 复制代码
$ cargo clean
$ cargo build
   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 5.89s
$ ll -h target/debug/hello_rust
-rwxrwxrwx 2 user user 5.8M Nov 15 02:14 target/debug/hello_rust
$ cargo clean
$ cargo build --release
   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 release [optimized] target(s) in 4.42s
$ ll -h target/release/hello_rust
-rwxrwxrwx 2 user user 4.5M Nov 15 02:15 target/release/hello_rust

在 debug 模式下,输出文件 5.8M,而 release 模式输出的文件减小到了 4.5M,效果是明显的。

在 release 模式下既然会对代码做性能优化,那么编译耗时也相对应该有所增长,可以使用 time 指令对比一下

scss 复制代码
$ cargo clean
$ time cargo build
   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 4.19s

real    0m4.273s
user    0m3.313s
sys     0m2.266s
$ cargo clean
$ time cargo build --release
   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 release [optimized] target(s) in 4.22s

real    0m4.299s
user    0m4.234s
sys     0m2.078s

从时长来看,release 模式略微比 debug 模式耗时,但是不明显,可能是因为上面示例程序比较简单的缘故,毕竟 release 模式下编译构建需要做的事情更复杂。

生成库或者可执行文件

上面的例子里,编译输出都是可执行文件,可执行文件可以独立执行,但也可调用库文件。软件工程的编译输出基本可以划分为两类,一个就是可执行文件,另一个就是库文件,一般在创建软件工程时可以指定输出类型。

Cargo 在创建 package 工程时默认指定生成可执行文件,如果是要输出库文件,需要添加 --lib 选项。下面来对比一下两种工程模板

go 复制代码
$ cargo new hello_rust
     Created binary (application) `hello_rust` package
$ tree hello_rust/
hello_rust/
├── Cargo.toml
└── src
    └── main.rs

1 directory, 2 files
$ cargo new lib_rust --lib
     Created library `lib_rust` package
$ tree lib_rust/
lib_rust/
├── Cargo.toml
└── src
    └── lib.rs

1 directory, 2 files

hello_rust 是可执行文件类型 package 工程,lib_rust 是库文件类型 package 工程。自动生成的源码文件有所不同,前者是 main.rs,后者是 lib.rs

对比一下自动生成的配置文件 Cargo.toml

yaml 复制代码
$ diff hello_rust/Cargo.toml lib_rust/Cargo.toml 
2c2
< name = "hello_rust"
---
> name = "lib_rust"

发现两种工程的配置文件内容除了工程名不一致,其它都是一样的,可推测 cargo 是通过 src 路径下的文件名来识别工程类型,src/main.rs 默认表明是可执行应用类型,src/lib.rs 默认表明是库类型。

相关推荐
该用户已不存在1 天前
Mojo vs Python vs Rust: 2025年搞AI,该学哪个?
后端·python·rust
大卫小东(Sheldon)1 天前
写了一个BBP算法的实现库,欢迎讨论
数学·rust
echoarts1 天前
Rayon Rust中的数据并行库入门教程
开发语言·其他·算法·rust
ftpeak2 天前
从零开始使用 axum-server 构建 HTTP/HTTPS 服务
网络·http·https·rust·web·web app
咸甜适中2 天前
rust语言 (1.88) 学习笔记:客户端和服务器端同在一个项目中
笔记·学习·rust
咸甜适中2 天前
rust语言 (1.88) egui (0.32.2) 学习笔记(逐行注释)(二十八)使用图片控件显示图片
笔记·学习·rust·egui
huli33202 天前
pingora_web:首款基于 Cloudflare Pingora 的企业级 Rust Web 框架
rust
Pomelo_刘金2 天前
如何优雅地抽离 Rust 子工程:以 rumqttd 为例
rust
几颗流星2 天前
Rust 常用语法速记 - 错误处理
后端·rust
向上的车轮2 天前
如何用 Rust 重写 SQLite 数据库(二):是否有市场空间?
数据库·rust·sqlite