#conditional-compilation #cfg #build #conditional #compilation #alias #build-script

构建 cfg_aliases

一个小巧的工具,可以帮助您在冗长的 #[cfg()] 检查上节省大量精力

6个版本

0.2.1 2024年5月10日
0.2.0 2023年12月19日
0.1.1 2020年10月20日
0.1.0 2020年4月8日
0.1.0-alpha.12020年4月5日

54Rust模式

Download history 535607/week @ 2024-04-25 535409/week @ 2024-05-02 532463/week @ 2024-05-09 537345/week @ 2024-05-16 565746/week @ 2024-05-23 663870/week @ 2024-05-30 680890/week @ 2024-06-06 710187/week @ 2024-06-13 703335/week @ 2024-06-20 737047/week @ 2024-06-27 790065/week @ 2024-07-04 785867/week @ 2024-07-11 795915/week @ 2024-07-18 834593/week @ 2024-07-25 807684/week @ 2024-08-01 725429/week @ 2024-08-08

3,308,665 每月下载量
6,198 个crate中(86个直接使用)

MIT 协议

20KB
202 行(不含注释)

CFG Aliases

CFG Aliases是一个小巧的工具,可以帮助您在冗长的 #[cfg()] 检查上节省大量精力。此crate提供了一个没有依赖项的单一 cfg_aliases! 宏,并且特别避免了引入 synquote,因此对您的编译时间的影响应该可以忽略不计。

您可以在您的 build.rs 脚本中使用 cfg_aliases! 宏来定义别名,例如 x11,然后可以在 cfg 属性或宏中进行条件编译: #[cfg(x11)]

示例

Cargo.toml

[build-dependencies]
cfg_aliases = "0.1.0"

build.rs

use cfg_aliases::cfg_aliases;

fn main() {
    // Setup cfg aliases
    cfg_aliases! {
        // Platforms
        wasm: { target_arch = "wasm32" },
        android: { target_os = "android" },
        macos: { target_os = "macos" },
        linux: { target_os = "linux" },
        // Backends
        surfman: { all(unix, feature = "surfman", not(wasm)) },
        glutin: { all(feature = "glutin", not(wasm)) },
        wgl: { all(windows, feature = "wgl", not(wasm)) },
        dummy: { not(any(wasm, glutin, wgl, surfman)) },
    }
}

现在我们已经设置了别名,我们可以像预期的那样使用它们

#[cfg(wasm)]
println!("This is running in WASM");

#[cfg(surfman)]
{
    // Do stuff related to surfman
}

#[cfg(dummy)]
println!("We're in dummy mode, specify another feature if you want a smarter app!");

这大大提高了没有使用别名时的样子

#[cfg(target_arch = "wasm32")]
println!("We're running in WASM");

#[cfg(all(unix, feature = "surfman", not(target_arch = "wasm32")))]
{
    // Do stuff related to surfman
}

#[cfg(not(any(
    target_arch = "wasm32",
    all(unix, feature = "surfman", not(target_arch = "wasm32")),
    all(windows, feature = "wgl", not(target_arch = "wasm32")),
    all(feature = "glutin", not(target_arch = "wasm32")),
)))]
println!("We're in dummy mode, specify another feature if you want a smarter app!");

您还可以使用 cfg! 宏,或者将您的别名与其他检查组合使用 all()not()any()。您的别名现在是真正的 cfg 标志了!

if cfg!(glutin) {
    // use glutin
} else {
    // Do something else
}

#[cfg(all(glutin, surfman))]
compile_error!("You cannot specify both `glutin` and `surfman` features");

语法和错误信息

别名名称受限于与 Rust 标识符相同的规则,这意味着它们不能包含破折号( - )。另外,如果您在别名名称等某些语法元素上犯了错误,宏将错误地表示达到递归限制,而不是明确指出实际出了什么问题。这是由于宏解析器的一个细微差别,可能在后续版本的 crate 中得到修复。也有可能在后续版本中支持包含破折号的别名名称。如果您想实现这一点,请提出一个问题。

最后,您还可以通过具有相互引用的规则来诱导无限递归,但这并不是真正的限制,因为这样做在逻辑上本来就没有意义

// This causes an error!
cfg_aliases! {
    test1: { not(test2) },
    test2: { not(test1) },
}

致谢

  • 感谢我的上帝和父亲,是他引导我解决这个问题,我所有的一切都归功于他。
  • 感谢 Rust 论坛上的 @Yandros,他 向我展示了 一些疯狂的宏技巧!
  • 感谢 @sfackler,他 指出了 使 cargo 添加 cfg 标志的方法。
  • 感谢 tectonic_cfg_support::target_cfg 宏的作者,该宏的大部分 cfg 属性解析逻辑都从中借鉴而来。还要感谢 @ratmice 在 Rust 论坛上 提出 了这个问题。

无运行时依赖