Rust 的条件编译机制

news/发布时间2024/5/15 23:41:46

基本原理

Rust 提供了一个 [cfg] 的编译选项,允许你基于一个传递给编译器的标记编译代码,有两种形式:

  • #[cfg(foo)]

    如果 foo 设置了编译对应代码;

  • #[cfg(bar = "baz")]

    如果 bar = "baz" ,则编译对应代码;

比如:

fn main() {#[cfg(feature = "foo")]println!("foo enabled");#[cfg(bar)]println!("bar enabled");println!("hello");
}

如果我们利用 rustc--cfg 进行编译

# 什么都不开启
$ rustc main.rs
$ ./main
hello# 开启 bar
$ rustc --cfg 'bar' main.rs
$ ./main 
bar enabled
hello# 开启 foo
$ rustc --cfg 'feature="foo"' main.rs
$ ./main 
foo enabled
hello# 全都开启
$ rustc --cfg 'feature="foo"' --cfg 'bar' main.rs
$ ./main
foo enabled
bar enabled
hello

Rust 还提供了一些断言语句

  • all()

    所有断言成立才可以编译,比如:

    fn main() {#[cfg(all(feature = "foo", bar, hello = "world"))]println!("foo enabled");println!("hello");
    }
    

    需要满足 3 个条件才进行编译:

    $ rustc --cfg 'feature="foo"' --cfg 'bar' --cfg 'hello="world"' main.rs
    
  • any()

    只要有一个条件满足才进行编译。比如:

    fn main() {#[cfg(any(feature = "foo", bar, hello = "world"))]println!("foo enabled");println!("hello");
    }
    
  • not()

    比如:

    fn main() {#[cfg(not(feature = "foo"))]println!("foo enabled");println!("hello");
    }
    

    如果不配置 feature="foo",下面那段代码将被编译。

这几种语句还可以相互之间嵌套:

#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))]

与 Cargo 配合

Cargo.toml 有一个 [features] 字段:

[features]
default = ["foo"]
foo = []

其中 default 字段配置了默认启动那些 feature。具体每一个 feature 都是一个列表,列表中表示将依赖于那些 feature,比如上文中 foo 这个 feature 就不依赖其他 feature:

fn main() {#[cfg(feature = "foo")]println!("foo enabled");println!("hello");
}

如果设置 default 开启 foo 则将打印出 foo enabled,如果保持 default 为空列表,则不会打印。

看一个稍微复杂点的例子:

[features]
default = ["ico", "webp"]
bmp = []
png = []
ico = ["bmp", "png"]
webp = []

ico 的开启依赖于 bmppng,也就是说,只要开启了 icobmppng 也开启了:

#[cfg(feature = "ico")]
fn enable_ico() {#[cfg(feature = "bmp")]println!("bmp enabled");#[cfg(feature = "png")]println!("png enabled");println!("ico enabled");
}fn main() {#[cfg(feature = "ico")]enable_ico();println!("hello");
}

将打印出:

bmp enabled
png enabled
ico enabled
hello

cfg_attr 的使用

cfg_attr 的使用稍微有点绕,可以看下面这个例子:

fn main() {#[cfg_attr(target_os = "macos", cfg(os = "mac"))]println!("macos");
}

这句话表达是:当 target_os = "macos" 成立时,当前的条件编译将使用 cfg(os = "mac"),即变成:

fn main() {#[cfg(os = "mac"))]println!("macos");
}

如果是在 macos 环境下,必须用如下命令进行编译才能打印 macos

 rustc --cfg='os="mac"' main.rs

还有一个例子,比如:

#[cfg_attr(feature = "magic", sparkles, crackles)]
fn bewitched() {}

如果 magic 这个 feature 开启了,则对应的条件编译将展开成:

#[sparkles]
#[crackles]
fn bewitched() {}

cfg! 的使用

可以利用 cfg! 来在运行时使用一些编译时的静态信息进行条件判断:

fn main() {if cfg!(target_os = "macos") {println!("macos");} else {println!("other os");}
}

参考

  • conditional-compilation
  • cargo-features

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.ulsteruni.cn/article/56235506.html

如若内容造成侵权/违法违规/事实不符,请联系编程大学网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

Avalonia下拉可搜索树(TreeComboBox)

1.需求分析树形下拉的功能是ComboBox和TreeView的功能结合起来,再结合数据模板来实现这一功能。 2.代码实现1.创建UserControl集成TreeView控件 ` public class TreeComboBox : TreeView { private bool _isPushTextChangedEvent = true; private Button ClearButton; private…

void usart_dma_init(void)

void usart_dma_init(void) {GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;DMA_InitTypeDef DMA_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;/* 配置GPIO的模式和IO口 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_…

k8s-调度-taint

NoSchedule :表示k8s将不会将Pod调度到具有该污点的Node上 PreferNoSchedule :表示k8s将尽量避免将Pod调度到具有该污点的Node上 NoExecute :表示k8s将不会将Pod调度到具有该污点的Node上,同时会将Node上已经存在的Pod驱逐出去去除污点 kubectl taint nodes k8s-node2 chec…

Cisco Nexus 9000 Series Switches, NX-OS Standalone 10.4(3)F and ACI Mode 16.0(5h)

Cisco Nexus 9000 Series Switches, NX-OS Standalone 10.4(3)F and ACI Mode 16.0(5h)Cisco Nexus 9000 Series Switches, NX-OS Standalone 10.4(3)F and ACI Mode 16.0(5h) include Application Policy Infrastructure Controller (APIC) Release 6.0(5h) 请访问原文链接:C…

003提供器(provider)

一、介绍 提供器是 Nest 中的一个基本概念。 许多基本的 Nest 类可以被视为提供器,例如: 服务、存储库、工厂、助手等等。 提供器的主要思想是它可以作为依赖注入;这意味着对象之间可以创建各种关系,并且 "接线" 这些对象的功能很大程度上可以委托给 Nest 运行时…

SQL事前巡检插件

背景: 事故频发 •每年都会看到SQL问题引发的线上问题 不易发觉 •对于SQL性能问题测试在预发环境不易发现 •saas系统隔离字段在SQL条件中遗漏,造成越权风险 •业务初期SQL没问题,业务增长容易出现事故 •DBS慢SQL不支持实时报警,无法及时发现 •靠大家review代码总会出现遗…