首页 > 其他分享 >Rust 的条件编译机制

Rust 的条件编译机制

时间:2024-04-11 15:33:05浏览次数:15  
标签:main cfg enabled feature 编译 println 机制 foo Rust

基本原理

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");
    }
}

参考

标签:main,cfg,enabled,feature,编译,println,机制,foo,Rust
From: https://www.cnblogs.com/RioTian/p/18129356

相关文章

  • 编译原理(清华大学版)第二章
    第二章文法和语言符号和符号串字母表是元素的非空有穷集合字母表中的元素称为符号字母表中的符号可以组成的任何又穷序列称为符号串符号串运算:1.符号串的头尾,固有头和固有尾​ \(z=xy,只对头感兴趣则可以写为z=x...\)2.符号串的链接​ $符号串x、y,连接之后为xy;\spac......
  • 编译原理(清华大学版)第一章
    第一章概论基本概念 词法分析经过词法分析器识别出Token,把字符串转化为一个个Token。Token包括:关键字、标识符、界符等语法分析把Token串转换成体现语法规则的抽象树(AST)语义分析审查源程序有无语义错误找到变量的作用域识别执行的运算方式进行类型......
  • Item31:最小化文件之间的编译依赖
    芝士wa2024.4.11Item31链接引子“你进入到你的程序中,并对一个类的实现进行了细微的改变。提醒你一下,不是类的接口,只是实现,仅仅是private的东西。然后你重建(rebuild)这个程序,预计这个任务应该只花费几秒钟。毕竟只有一个类被改变。你在Build上点击或者键入make(或者其它等......
  • ZOMI的AI编译原理4
    为什么需要AI编译器面临的问题挑战类别描述算子挑战越来越多新算子被提出,导致算子库的开发、维护、优化和测试工作量指数上升。1.硬件不仅需要实现新算子,还需要结合硬件进行特性优化和测试,以充分发挥硬件性能。例如,对于Convolution运算,需要将其转换为GEMM矩阵乘......
  • Rust Reference Cycles: Resolving and Avoiding them
    InRust,referencecyclesoccurwhentwoormoreobjectsmutuallyreferenceeachother,formingacircularchain.Inthissituation,thereferencecountbetweenobjectsneverbecomeszero,leadingtomemoryleaksandresourceleaks.Thisblogpostwilldi......
  • 看不懂来打我,vue3如何将template编译成render函数
    前言在之前的通过debug搞清楚.vue文件怎么变成.js文件文章中我们讲过了vue文件是如何编译成js文件,通过那篇文章我们知道了,template编译为render函数底层就是调用了@vue/compiler-sfc包暴露出来的compileTemplate函数。由于文章篇幅有限,我们没有去深入探索compileTemplate函数是......
  • vue编译器
    ast-编译成代码import*aspathfrom'path'importtype{Plugin,ResolvedConfig}from'vite'import{NodePath}from'@babel/traverse';import{JSXElement}from'@babel/types';import{compile,generate,transform......
  • 如何让WSL2使用自己编译的内核
    目录wsl基本介绍以及安装编译内核下载linux源码使用wsl内核配置添加uvc内核驱动编译内核切换wsl内核重启内核最近有一个摄像头的项目,想着为什么不直接使用wsl呢。查阅了网络上大量的资料,修改了WSL2内核来支持UVCwsl基本介绍以及安装wsl(windowssubsystemforlinux)是wind......
  • 千万不要将centos中python 默认2.7的编译器改为3.x的,会出现File “ usr bin yum“, li
    千万不要将centos中python默认2.7的编译器改为3.x的,在使用yum时,会报各种错,1、File"/usr/bin/yum",line30  exceptKeyboardInterrupt,e:原因是yum按python3.6解析2.7的语法出错了修改/usr/bin/yum文件中的第一行为#!/usr/bin/python2.72、 File"/usr/libexec/url......
  • 数据是一维数据,利用tensorflow深度学习框架,写一个带自注意力机制的卷积神经网络,并进行
    下面是一个使用TensorFlow框架的带有自注意力机制的卷积神经网络(Self-AttentionConvolutionalNeuralNetwork)的示例代码,包括数据处理、模型定义和训练过程:importtensorflowastffromtensorflow.keras.layersimportConv1D,Dense,GlobalMaxPooling1D,Concatenate#......