文章524
标签277
分类67

通过一个例子学习Cargo Features

在C、C++中我们经常会使用#define、#ifdef等预处理指令进行条件编译,这样会提升编译速度、减少编译后文件大小,在某些场景下会非常有用;

例如:某些和具体平台实现相关的代码,在win平台下使用时,其实无需编译linux平台下的代码;

本文通过一个例子讲解了Cargo Features是如何实现的;

源代码:


通过一个例子学习Cargo Features

前言

本文只是通过一个例子来讲解如何使用 Cargo Features,并非讲解 Cargo Features 的全部特性以及底层实现;

同时,在阅读本文之前,请先阅读:

对 Cargo Features 有一定的基础,再来学习本文;


实现一个含有feature的lib

和上面 条件编译 Features 的内容保持一致,在例子中会定义这么几个 feature:

1
2
3
4
5
[features]
bmp = []
png = []
ico = ["bmp", "png"]
webp = []

bmp、png、ico、webp,并且 ico 依赖 bmp 和 png 特性;

创建 feature-demo crate:

1
cargo new feature-demo --lib

修改 Cargo.toml,增加 feature 定义:

feature-demo/Cargo.toml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
+ [features]

+ default = []

+ full = [
+ "bmp",
+ "png",
+ "ico",
+ "webp"
+ ]

+ bmp = []
+ png = []
+ ico = ["bmp", "png"]
+ webp = []

同时实现各个 feature:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// feature-demo/src/lib.rs
pub mod bmp;
pub mod ico;
pub mod png;
pub mod webp;

// feature-demo/src/bmp.rs
#[cfg(feature = "bmp")]
pub fn process_bmp() {
println!("Processing bmp");
}

// feature-demo/src/png.rs
#[cfg(feature = "png")]
pub fn process_png() {
println!("Processing png");
}

// feature-demo/src/webp.rs
#[cfg(feature = "webp")]
pub fn process_webp() {
println!("Processing webp");
}

// feature-demo/src/ico.rs
use crate::bmp::process_bmp;
use crate::png::process_png;

#[cfg(all(feature = "png", feature = "bmp"))]
#[cfg(feature = "ico")]
pub fn process_ico() {
println!("Before process_ico: ");
process_bmp();
process_png();
println!("Processing ico")
}

各个文件中的内容如上所示,其中 #[cfg(...)] 的意思是,只有定义了这个 feature 才编译下面的代码;

关于 cfg:

同时,由于 ico 特性依赖 bmp、png 特性,因此需要先使用了 png、bmp 特性,同时使用了 ico 特性才会编译相应的代码;

至此,我们带有 feature 的 lib 编写完成;


使用一个含有feature的lib

下面来使用我们刚刚编写的含有 feature 的 lib;

首先引入这个 crate:

Cargo.toml

1
2
[dependencies]
feature-demo = { path = "./feature-demo", features = ["bmp", "ico"] }

这里引入了 bmp 和 ico 特性,但是由于 ico 特性依赖了 png 特性,因此实际上我们也是可以使用 png 特性的!

在 main 中使用这个 lib:

src/main.rs

1
2
3
4
5
6
7
8
9
10
11
use feature_demo::bmp::process_bmp;
use feature_demo::ico::process_ico;
use feature_demo::png::process_png;

fn main() {
process_bmp();

process_png();

process_ico();
}

执行后输出:

1
2
3
4
5
6
Processing bmp
Processing png
Before process_ico:
Processing bmp
Processing png
Processing ico

但是,由于我们没有引入 webp 特性,因此这部分代码实际上不会被编译,并且我们也无法使用!

例如,添加下面的代码,会造成编译失败:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
use feature_demo::bmp::process_bmp;
use feature_demo::ico::process_ico;
use feature_demo::png::process_png;
+ use feature_demo::webp::process_webp;

fn main() {
process_bmp();

process_png();

process_ico();
+
+ process_webp();
}

在添加了相关的 feature 之后,编译成功:

1
2
- feature-demo = { path = "./feature-demo", features = ["bmp", "ico"] }
+ feature-demo = { path = "./feature-demo", features = ["bmp", "ico", "webp"] }

附录

源代码:

文章参考:



本文作者:Jasonkay
本文链接:https://jasonkayzk.github.io/cn/2022/11/28/%E9%80%9A%E8%BF%87%E4%B8%80%E4%B8%AA%E4%BE%8B%E5%AD%90%E5%AD%A6%E4%B9%A0Cargo-Features/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可