2 个版本
| 0.1.1 | 2024年4月22日 |
|---|---|
| 0.1.0 | 2023年5月28日 |
#491 in Rust 模式
每月 50 次下载
用于 3 个 crate (通过 jit-allocator)
20KB
233 行
CFGenius
一个宏,用于定义包含跨 crate 变量的条件编译 if-else 语句。
此宏类似于 cfg_if!——事实上非常相似,以至于我们将暂时抄袭其文档
此 crate 提供的宏
cond!类似于 C 预处理器宏if/elif,允许定义一系列#[cfg]情况,并输出匹配的第一个实现。这允许你方便地提供一系列
#[cfg]编译代码块,而无需多次重写每个条款。示例
cfgenius::cond! { if cfg(unix) { fn foo() { /* unix specific functionality */ } } else if cfg(target_pointer_width = "32") { fn foo() { /* non-unix, 32-bit functionality */ } } else { fn foo() { /* fallback implementation */ } } }
然而,新的功能是可以 define! 自定义条件编译变量,并在你的 cond! 命题中使用这些变量
// In `crate_1`...
cfgenius::define! {
pub(super) is_32_bit_or_more = cfg(any(
target_pointer_width = "32",
target_pointer_width = "64",
));
pub is_recommended = all(
macro(is_32_bit_or_more),
macro(is_supported),
cfg(target_has_atomic),
);
}
cfgenius::cond! {
if all(cfg(windows), not(macro(is_32_bit_or_more))) {
cfgenius::define!(pub is_supported = true());
// windows-specific non-32-bit functionality
} else if all(cfg(windows), macro(is_32_bit_or_more)) {
cfgenius::define!(pub is_supported = true());
// windows-specific non-32-bit functionality
} else {
cfgenius::define!(pub is_supported = false());
}
}
pub const IS_SUPPORTED: bool = cfgenius::cond_expr!(macro(is_supported));
// In `crate_2`...
cfgenius::cond! {
if any(
macro(crate_1::is_recommended),
all(cfg(feature = "force_crate_1_backend"), macro(crate_1::is_supported))
) {
// (`crate_1` implementation)
} else {
// (fallback implementation)
}
}
在常规的 #[cfg] 属性中无法实现
macro_rules! truthy {
() => { all() };
}
#[cfg(truthy!())]
// ^ Syntax Error: expected one of `(`, `,`, `::`, or `=`, found `!`
mod this_is_compiled {}
命题
在每个可能期望条件编译命题的地方,支持以下命题
-
true():始终为真 -
false():始终为假 -
cfg(<cfg 输入>):解析为具有相同输入的常规 cfg 属性 的结果。 -
not(<谓词>):否定提供的cfgenius谓词的解析。 -
all(<谓词 1>, <谓词 2>, ...):如果提供的所有cfgenius谓词都不失败,则解析为真。没有提供谓词的all()解析为真。 -
any(<谓词 1>, <谓词 2>, ...):如果提供的至少一个cfgenius谓词成功,则解析为真。没有提供谓词的any()解析为假。 -
macro(<宏的路径>):使用宏来决定谓词的真假。 -
macro(<宏的路径> => <宏参数>):使用提供的参数调用宏来决定谓词的真假。
自定义变量
大多数变量可以使用define!简洁地定义。然而,由于变量只是扩展以获得结果的宏,您可以通过遵循此协议定义自己的变量。
谓词macro(<宏的路径>)通过展开进行评估
path::to::macro! {
yes { /* truthy tokens */ }
no { /* falsy tokens */ }
}
...并且谓词macro(<宏的路径> => <宏参数>)通过展开进行评估
path::to::macro! {
args { /* macro arguments */ }
yes { /* truthy tokens */ }
no { /* falsy tokens */ }
}
如果变量应该为真,则宏应展开为/* 真值标记 */以及更多。如果变量应该为假,则宏应展开为/* 假值标记 */以及更多。
这些宏应该在与环境无关的情况下是无效的和纯净的。您不应该依赖于该宏在谓词中出现一次时被评估一次,尽管这是当前的行为。