#cfg #build #version #compiler-version #rustc #autoconf

nightly build cfg_rust_features

根据 Rust 编译器、语言和库功能的探测设置 cfg 选项

3 个版本

使用旧的 Rust 2015

0.1.2 2024 年 3 月 15 日
0.1.1 2022 年 10 月 25 日
0.1.0 2022 年 3 月 23 日

#133 in 构建工具

32 每月下载量
用于 6 个crate (3 直接)

无许可证

37KB
400

cfg_rust_features

一个构建脚本辅助工具,用于根据探测您选择的哪些功能在 Rust 编译器、语言和库中启用来设置 cfg 选项,而不参考 Rust 的版本。

主要目的是检测之前不稳定的功能何时变得稳定,基于功能的存在而不是 Rust 版本。这有助于设计条件编译代码,使其能够根据 Rust 未知未来的任何版本中功能何时变得稳定而进行调整。

设置的 cfg 选项是键值形式的,例如:rust_lib_feature = "iter_zip"rust_lang_feature = "never_type" 等。

探测不使用 #![feature(...)],因此设置的选项表示与 nightlystable 编译器一致稳定的特性。仍然可以使用 rust_comp_feature = "unstable_features" 选项条件性地启用不稳定的功能,该选项可以在使用 nightly(或 dev)编译器时检测和设置。

注意

  • 在设计围绕可能在不稳定之前发生变化的功能的代码时,必须非常小心。

  • 目前,这个crate只支持一小部分特性(包括不稳定和稳定版本)。您可以通过在以下位置打开问题请求支持更多特性:https://github.com/DerickEddington/cfg_rust_features/issues

示例

  • 您的构建脚本,通常是 build.rs,可以非常简单:

    fn main() {
        let of_interest = ["iter_zip", /* Or: "unstable_features", etc ... */];
        cfg_rust_features::emit!(of_interest).unwrap();
    }
    
  • 要处理稳定Rust版本,您实现了一个绕过方案,以解决您希望使用但尚未稳定的不稳定特性,您不知道它将在哪个未来的版本中成为稳定(如果会的话),但您确信在它稳定之前该特性的API不会改变。因此,借助这个crate,您设计了条件编译,如果该特性变为稳定,则将绕过方案标记为已弃用,并使用该特性。

    如果您的绕过方案是在 Result<T, Infallible> 上添加一个 into_ok 方法,则这种检测可以像这样完成:

    #[cfg_attr(rust_lib_feature = "unwrap_infallible", deprecated)]
    trait IntoOk { /* ... */ }
    
    #[cfg(not(rust_lib_feature = "unwrap_infallible"))]
    impl<T> IntoOk for Result<T, Infallible> { /* ... */ }
    
  • 仅在使用 nightly(或 dev)编译器时启用不稳定特性

    #![cfg_attr(rust_comp_feature = "unstable_features", feature(step_trait))]
    
    #[cfg(rust_comp_feature = "unstable_features")]
    fn maybe_use_step_trait() { /* ... */ }
    

    这避免了需要一些Cargo包特性(例如 "unstable"),这可能是一些项目所希望的。

    或者,只有在特性尚未稳定时才能启用不稳定特性,并且当特性成为稳定时不再启用,例如

    #![cfg_attr(not(rust_lib_feature = "step_trait"), feature(step_trait))]
    
    fn assume_step_trait_is_available() { /* ... */ }
    
  • 要具有(截至2022-10-23需要 nightly 编译器)不会干扰使用 stable 编译器的基准测试,而无需额外的包特性。这允许使用Cargo选项 --all-targets(包括 --benches),而无需错误地使用 stable 编译器,这对于使用该工具特别有帮助。这是在 benches/ 的顶部完成的,例如

    #![cfg(rust_comp_feature = "unstable_features")]
    /* ... */
    

    因此,在 stable 编译器下,benches/ 目标实际上是空的,但在 nightly 下是非空的,无需记住提供 --features

    此外,当Rust的某个未来版本稳定一个特性时,例如基准测试的 test 特性,以及如果这个crate的未来版本增加了对该特性的支持时,目标可以进行调整;并且即使在特性不稳定并且这个crate没有支持时,目标仍然可以工作,例如

    // If provided by either stable or unstable feature, have this target
    // be non-empty.
    #![cfg(any(
        // Only set/true when the currently-used version of the
        // cfg_rust_features crate supports it and it is stable in the
        // currently-used version of Rust.
        rust_lib_feature = "test",
        // Only set/true when a nightly (or dev) compiler is being used.
        rust_comp_feature = "unstable_features"
    ))]
    // Else, a stable compiler version without the feature is being used,
    // so have this target be empty to cause all the below items to be
    // ignored as if they do not exist.
    
    #![cfg_attr(
        // If the feature is still unstable
        not(rust_lib_feature = "test"),
        // then it needs to be specially enabled.
        feature(test)
    )]
    // Else if the feature is stable, #![feature(test)] is not needed.
    
    // Valid whenever the feature is enabled, whether stable or unstable.
    extern crate test;
    
    /* ... */
    

    因此,至少在文件顶部,此代码在特性不稳定和后来变为稳定时都不需要更改(除非特性在不稳定时本身发生变化,当然);此外,此代码在Rust的较旧版本中也将继续有效,即使较新版本稳定了该特性。

稳定性策略

API遵循正常的Cargo SemVer策略,但有资格说明,未来版本的错误行为允许有一定的变化

  • 未来版本可能改为支持更多的特性名称,因此不再为这些名称报错。但是,一旦支持了特性名称,就不会将其删除,因此未来版本将永远不会报错。

  • 未来版本可能改变,在创建 CfgRustFeatures 实例时,在 dyn Error 后面返回不同的 Error 类型,这是由于探测方式内部的变化以及所使用的依赖项的变化。但是,Box<dyn Error> 类型的使用将保持稳定。

最低支持的Rust版本

Rust 1.0.0 将始终得到支持,因此这个crate可以被支持该旧版本的其它crate使用。

文档

源代码包含文档注释,这些注释将被渲染为API文档。

在线查看: http://docs.rs/cfg_rust_features

或者,您可以通过以下方式自己生成并本地查看:

cargo doc --open

依赖

~48KB