cfg有两种使用方式,一种是属性: #[cfg()]
,一种是宏:cfg! ,这两个都是非常常用的功能。
#[cfg()]
是 Rust 中的一个属性
用于根据配置条件来选择性地包含或排除代码。cfg
是 "configuration" 的缩写,用于控制在不同的构建环境或平台上编译和执行不同的代码块。在不同的操作系统上会编译不同的函数示例:
#[cfg(target_os = "linux")]
fn get_os_info(){
println!("linux");
}
#[cfg(target_os = "windows")]
fn get_os_info() {
println!("windows");
}
fn main() {
get_os_info();
}
也可使用not表达式:在非 linux 系统下会编译此函数
#[cfg(not(target_os = "linux"))]
fn get_os_info() {
println!("not linux");
}
#[cfg()]
属性可以用于函数、结构体、枚举、模块、模块导入等各种代码元素,以及条件编译块(#[cfg()]
包围的代码块)。它使用一个或多个条件表达式来指定编译时要包含或排除的代码。条件表达式可以是 Rust 的预定义属性、环境变量、操作系统类型、目标架构等。
#[cfg()]
属性中使用的逻辑运算符有以下几种:
all(expr1, expr2, ...)
:逻辑与运算符,要求所有条件表达式都为真才返回真。例如:#[cfg(all(feature = "foo", target_os = "linux"))]
表示只有在启用 "foo" 功能并且目标操作系统是 Linux 时条件成立。any(expr1, expr2, ...)
:逻辑或运算符,只要有任一条件表达式为真就返回真。例如:#[cfg(any(feature = "foo", feature = "bar"))]
表示只要启用 "foo" 或 "bar" 中的任意一个功能时条件成立。not(expr)
:逻辑非运算符,对条件表达式取反。例如:#[cfg(not(debug_assertions))]
表示只有在非调试断言模式下条件成立。
以下是一些示例用法:
#[cfg(target_os = "linux")]
fn only_on_linux() {
// 仅在 Linux 系统上编译和执行的代码
}
#[cfg(all(unix, not(target_os = "linux")))]
fn on_unix_but_not_linux() {
// 仅在 Unix 系统但不是 Linux 上编译和执行的代码
}
#[cfg(any(windows, target_os = "macos"))]
fn on_windows_or_macos() {
// 仅在 Windows 或 macOS 上编译和执行的代码
}
#[cfg(not(debug_assertions))]
fn when_not_debug_assertions() {
// 仅在非调试断言模式下编译和执行的代码
}
#[cfg(feature = "my_feature")]
fn with_my_feature_enabled() {
// 仅在启用 "my_feature" 功能时编译和执行的代码
}
在这些示例中,#[cfg()]
属性根据不同的条件表达式来控制代码的编译和执行。根据配置条件的不同,编译器会选择性地包含或排除相应的代码。
#[cfg()]
属性可以根据不同的需求来组合条件表达式,并支持各种逻辑运算符(如 all
、any
、not
)来组合条件。你可以根据特定的配置条件来编写平台特定的代码、功能开关的代码、调试模式的代码等。
注意:#[cfg()]
属性是在编译时进行判断和处理的,不会在运行时起作用。因此,通过使用不同的配置条件,你可以在不同的构建环境中选择性地编译和执行特定的代码块。
cfg!宏的方法
判断操作系统,执行不同的代码块:
if cfg!(target_os = "linux") {
println!("linux");
} else {
println!("not linux");
}
比如执行cmd命令还是shell命令:
use std::process::Command;
// cmd_str可以是从输入流读取或从文件里读取
let cmd_str: String;
if cfg!(target_os = "windows") {
// 这里不用\\而是/的话会被windows认为/tmp的/t是一个option而报错
cmd_str = "dir d:\\tmp".to_string();
} else {
cmd_str = "dir /usr/tmp".to_string();
}
let output = if cfg!(target_os = "windows") {
Command::new("cmd").arg("/c").arg(cmd_str).output().expect("cmd exec error!")
} else {
Command::new("sh").arg("-c").arg(cmd_str).output().expect("sh exec error!")
}
let output_str = String::from_utf8_lossy(&output.stdout);
println!("{}", output_str);