Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditional compilation for 'nightly' vs 'stable' Rust or compiler version

Tags:

rust

I am using some Rust unstable features, but I still want to be able to compile a reduced version of my library with stable Rust. I am happy to only include those unstable features when the compiler supports them, and exclude them when they are not supported.

I thought it would be easy to achieve this goal using conditional compilation like #[cfg(rust_version = "nightly")], but it seems like 'stable' vs 'nightly' are not cfg options.

How do you guys perform conditional compilation based on 'stable' vs 'nightly', or based on the compiler version?

like image 220
likebike Avatar asked Mar 14 '26 11:03

likebike


1 Answers

I recommend creating a feature for your nightly-only code that is disabled by default, for example

Cargo.toml

[features]
default = []
nightly-features = []

Since the nightly-features feature is not default, compilation with the stable toolchain works out of the box. You can use attributes #[cfg(feature = "nightly-features")] and #[cfg(not(feature = "nightly-features"))] to include or exclude code from nightly-specialized versions. This method has the added benefit of allowing testing of the nightly features independently of the compiler (i.e. answer the question: did the compiler break my code, or does code enabled by nightly-features contain bugs?).

Despite the risks, I want to enable nightly features automatically

Use build scripts, sometimes called build.rs in addition to the nightly feature described above. (note: the following should NEVER be used in a library, otherwise switching compilers could become a breaking change. prefer the solution explained above)

build.rs (goes in package root)

use std::env;

fn main() {
    let rust_toolchain = env::var("RUSTUP_TOOLCHAIN").unwrap();
    if rust_toolchain.starts_with("stable") {
        // do nothing
    } else if rust_toolchain.starts_with("nightly") {
        //enable the 'nightly-features' feature flag
        println!("cargo:rustc-cfg=feature=\"nightly-features\"");
    } else {
        panic!("Unexpected value for rustc toolchain")
    }
}

this build script checks the toolchain environment variable set by rustup (some rust installations do not use rustup) and enables the nightly feature flag if the compiler is nightly.

src/main.rs

fn main() {
    #[cfg(feature = "nightly-features")]
    println!("Hello, nightly!");
    #[cfg(not(feature = "nightly-features"))]
    println!("Hello, stable!");
}

now, running

➜  cargo +stable run      
Hello, stable!
➜  cargo +nightly run
Hello, nightly!

Is it possible to turn this feature off when build.rs turns it on?

As far as I can tell, no. Running cargo +nightly run --no-default-features leaves the feature on, due to how cargo passes flags to rustc. A programmer could create a specific environmental variable that build.rs checks for to skip the automatic version detection, but that is more complicated than the alternative with no build script - cargo build --features=nightly-features

Crate alternative

Instead of the proposed solution, you can use the rustversion crate, which works in a very similar way (but parses the output of rustc --version).

fn main() {
    #[rustversion(nightly)]
    println!("Hello, nightly!");
    #[rustversion::not(nightly)]
    println!("Hello, stable! (or beta)");
}
like image 132
asky Avatar answered Mar 16 '26 09:03

asky



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!