From 980ac5e30110ac21d591564e9bdc95c602ecd513 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Fri, 15 Apr 2022 13:27:34 -0500 Subject: [PATCH] probe with_features --- src/lib.rs | 17 +++++++++++++++++ src/tests.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index cbe393a..e891777 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,6 +86,7 @@ pub struct AutoCfg { rustc_version: Version, target: Option, no_std: bool, + features: Vec, rustflags: Vec, } @@ -172,6 +173,7 @@ impl AutoCfg { rustc: rustc, rustc_version: rustc_version, target: target, + features: Vec::new(), no_std: false, }; @@ -229,6 +231,11 @@ impl AutoCfg { if self.no_std { try!(stdin.write_all(b"#![no_std]\n").map_err(error::from_io)); } + for feature in &self.features { + try!(stdin + .write_all(format!("#![feature({})]\n", feature).as_bytes()) + .map_err(error::from_io)); + } try!(stdin.write_all(code.as_ref()).map_err(error::from_io)); drop(stdin); @@ -378,6 +385,16 @@ impl AutoCfg { emit(cfg); } } + + /// Run some autocfg probes with a set of features enabled. + /// + /// This adds `#![feature(FEATURE)]` to the start of all probes done with + /// the callback's `AutoCfg` for each enabled feature. + pub fn with_features FnOnce(&'a mut AutoCfg)>(&mut self, features: &[&str], f: F) { + self.features.extend(features.iter().map(|s| s.to_string())); + f(self); + self.features.truncate(self.features.len() - features.len()); + } } fn mangle(s: &str) -> String { diff --git a/src/tests.rs b/src/tests.rs index d3b1fbb..cd7d097 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,6 +1,8 @@ use super::AutoCfg; use std::env; use std::path::Path; +use std::process::Command; +use std::str; impl AutoCfg { fn core_std(&self, path: &str) -> String { @@ -22,6 +24,32 @@ impl AutoCfg { None => Self::with_dir("target"), } } + + fn assert_nightly(&self, probe_result: bool) { + // Get rustc's verbose version + let output = Command::new(&self.rustc) + .args(&["--version", "--verbose"]) + .output() + .unwrap(); + if !output.status.success() { + panic!("could not execute rustc") + } + let output = str::from_utf8(&output.stdout).unwrap(); + + // Find the release line in the verbose version output. + let release = match output.lines().find(|line| line.starts_with("release: ")) { + Some(line) => &line["release: ".len()..], + None => panic!("could not find rustc release"), + }; + + // Check for nightly channel info, e.g. "-nightly", "-dev" + let nightly = match release.find('-') { + Some(i) => &release[i..] == "-nightly" || &release[i..] == "-dev", + None => false, + }; + + assert_eq!(nightly, probe_result); + } } #[test] @@ -133,6 +161,23 @@ fn probe_constant() { ac.assert_min(1, 39, ac.probe_constant(r#""test".len()"#)); } +#[test] +fn prope_feature() { + let mut ac = AutoCfg::for_test().unwrap(); + // an empty #![features()] has no effect + ac.with_features(&[], |ac| { + assert!(ac.probe("").unwrap_or(false)); + }); + // stabilized feature succeeds + ac.with_features(&["rust1"], |ac| { + ac.assert_nightly(ac.probe("").unwrap_or(false)); + }); + // fake feature fails + ac.with_features(&["RUSTC_DONT_MAKE_ME_A_LIAR"], |ac| { + ac.assert_nightly(!ac.probe("").unwrap_or(false)); + }); +} + #[test] fn dir_does_not_contain_target() { assert!(!super::dir_contains_target(