use std::env;
use std::process::Command;
use std::str;
const VERSION_CFGS: &[(u64, u64, &str)] = &[
(1, 54, "rustc_ge_1_54_0"),
(1, 57, "rustc_ge_1_57_0"),
(1, 59, "rustc_ge_1_59_0"),
(1, 81, "rustc_ge_1_81_0"),
(1, 84, "rustc_ge_1_84_0"),
(1, 95, "rustc_ge_1_95_0"),
];
fn main() {
match rustc_release() {
Some(release) => {
if release.is_nightly() {
println!("cargo:rustc-cfg=branches_nightly");
} else {
println!("cargo:rustc-cfg=branches_stable");
}
for &(major, minor, cfg) in VERSION_CFGS {
if release.is_at_least(major, minor) {
println!("cargo:rustc-cfg={}", cfg);
}
}
let opt_level = env::var("OPT_LEVEL").unwrap_or_default();
if release.is_at_least(1, 84) && (opt_level == "2" || opt_level == "3") {
println!("cargo:rustc-cfg=branches_cold_weights");
}
}
None => println!("cargo:rustc-cfg=branches_stable"),
}
}
struct Release {
major: u64,
minor: u64,
patch: u64,
pre: String,
}
impl Release {
fn is_nightly(&self) -> bool {
self.pre.starts_with("nightly")
}
fn is_at_least(&self, major: u64, minor: u64) -> bool {
if (self.major, self.minor, self.patch) == (major, minor, 0) {
self.pre.is_empty()
} else {
(self.major, self.minor, self.patch) > (major, minor, 0)
}
}
}
fn rustc_release() -> Option<Release> {
let rustc = env::var_os("RUSTC").unwrap_or_else(|| "rustc".into());
let wrapper = env::var_os("RUSTC_WRAPPER").filter(|w| !w.is_empty());
let mut cmd = match wrapper {
Some(wrapper) => {
let mut cmd = Command::new(wrapper);
cmd.arg(rustc);
cmd
}
None => Command::new(rustc),
};
let output = cmd.arg("-vV").output().ok()?;
if !output.status.success() {
return None;
}
let stdout = str::from_utf8(&output.stdout).ok()?;
let release = stdout
.lines()
.find_map(|line| line.strip_prefix("release: "))?;
parse_release(release.trim())
}
fn parse_release(release: &str) -> Option<Release> {
let release = release.split('+').next()?;
let mut parts = release.splitn(2, '-');
let triple = parts.next()?;
let pre = parts.next().unwrap_or("").to_string();
let mut numbers = triple.split('.');
let major = numbers.next()?.parse().ok()?;
let minor = numbers.next()?.parse().ok()?;
let patch = numbers.next()?.parse().ok()?;
if numbers.next().is_some() {
return None;
}
Some(Release {
major,
minor,
patch,
pre,
})
}