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 */ }
}
如果变量应该为真,则宏应展开为/* 真值标记 */
以及更多。如果变量应该为假,则宏应展开为/* 假值标记 */
以及更多。
这些宏应该在与环境无关的情况下是无效的和纯净的。您不应该依赖于该宏在谓词中出现一次时被评估一次,尽管这是当前的行为。