Rust 的条件编译机制
Contents
基本原理
Rust 提供了一个 [cfg]
的编译选项,允许你基于一个传递给编译器的标记编译代码,有两种形式:
-
#[cfg(foo)]
如果
foo
设置了编译对应代码; -
#[cfg(bar = "baz")]
如果
bar = "baz"
,则编译对应代码;
比如:
|
|
如果我们利用 rustc
和 --cfg
进行编译:
|
|
Rust 还提供了一些断言语句:
-
all()
所有断言成立才可以编译,比如:
1 2 3 4 5 6
fn main() { #[cfg(all(feature = "foo", bar, hello = "world"))] println!("foo enabled"); println!("hello"); }
需要满足 3 个条件才进行编译:
1
$ rustc --cfg 'feature="foo"' --cfg 'bar' --cfg 'hello="world"' main.rs
-
any()
只要有一个条件满足才进行编译。比如:
1 2 3 4 5 6
fn main() { #[cfg(any(feature = "foo", bar, hello = "world"))] println!("foo enabled"); println!("hello"); }
-
not()
比如:
1 2 3 4 5 6
fn main() { #[cfg(not(feature = "foo"))] println!("foo enabled"); println!("hello"); }
如果不配置
feature="foo"
,下面那段代码将被编译。
这几种语句还可以相互之间嵌套:
|
|
与 Cargo 配合
Cargo.toml
有一个 [features]
字段:
|
|
其中 default
字段配置了默认启动那些 feature。具体每一个 feature 都是一个列表,列表中表示将依赖于那些 feature,比如上文中 foo
这个 feature 就不依赖其他 feature:
|
|
如果设置 default
开启 foo
则将打印出 foo enabled
,如果保持 default
为空列表,则不会打印。
看一个稍微复杂点的例子:
|
|
ico
的开启依赖于 bmp
和 png
,也就是说,只要开启了 ico
,bmp
和 png
也开启了:
|
|
将打印出:
|
|
cfg_attr
的使用
cfg_attr
的使用稍微有点绕,可以看下面这个例子:
|
|
这句话表达是:当 target_os = "macos"
成立时,当前的条件编译将使用 cfg(os = "mac")
,即变成:
|
|
如果是在 macos 环境下,必须用如下命令进行编译才能打印 macos
:
|
|
还有一个例子,比如:
|
|
如果 magic
这个 feature 开启了,则对应的条件编译将展开成:
|
|
cfg!
的使用
可以利用 cfg!
来在运行时使用一些编译时的静态信息进行条件判断:
|
|