cfg! 巨集
本集目標
學會用 cfg! 判斷編譯時期的條件並取得 bool 結果,以及它跟 #[cfg] 的差別。
概念說明
cfg! 回傳 bool
上一集學了 #[cfg(...)]——條件編譯,不符合條件的程式碼整塊被移除。但有時候你只是想根據條件走不同分支,不想移除整塊程式碼。cfg! 就是做這件事的:
fn main() {
if cfg!(target_os = "windows") {
println!("你在 Windows 上");
} else {
println!("你不在 Windows 上");
}
}
跟 #[cfg] 的差別
#[cfg(...)] | cfg!(...) | |
|---|---|---|
| 作用 | 條件編譯:整段程式碼移除或保留 | 在編譯時期展開成 true 或 false |
| 程式碼檢查 | 不符合條件的程式碼會被移除,不接受檢查 | 兩個分支都會保留並接受檢查 |
cfg! 常放在一般的 if 裡,但條件已經在編譯時期決定,不是等到執行時期才判斷。兩個分支都會保留,而且必須通過編譯器的檢查。
這是很重要的差別:#[cfg] 不符合的那塊完全不存在,裡面就算有不存在的函數也不會報錯。但使用 cfg! 時,如果某一邊有編譯錯誤,不管條件成不成立都會報錯。
// #[cfg] 版:Windows 上不會編譯 linux_only(),不會報錯
#[cfg(target_os = "linux")]
fn linux_only() { /* Linux 特有功能 */ }
// cfg! 版:兩邊都會被編譯
if cfg!(target_os = "linux") {
// linux_only(); // 如果函數不存在,在 Windows 上也會編譯錯誤!
}
常見條件
#[cfg] 和 cfg! 能用的條件一樣:
target_os = "windows"/"linux"/"macos"target_arch = "x86_64"/"aarch64"。debug_assertions— debug 模式下為truefeature = "my_feature"— Cargo featuretest— 在cargo test時為true
範例程式碼
fn main() {
if cfg!(debug_assertions) {
println!("debug 模式");
} else {
println!("release 模式");
}
let os = if cfg!(target_os = "windows") {
"Windows"
} else if cfg!(target_os = "linux") {
"Linux"
} else if cfg!(target_os = "macos") {
"macOS"
} else {
"其他"
};
println!("作業系統:{}", os);
}
重點整理
cfg!(...)會在編譯時期展開成bool常數;兩個分支都會保留並接受檢查。#[cfg(...)]是條件編譯,不符合的程式碼整塊移除。- 兩者能用的條件一樣:
target_os、debug_assertions、feature、test等。