Skip to content

Commit

Permalink
Stateless feature probe
Browse files Browse the repository at this point in the history
  • Loading branch information
CAD97 committed Apr 15, 2022
1 parent 2dc4819 commit a1d7429
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 0 deletions.
36 changes: 36 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,42 @@ impl AutoCfg {
emit(cfg);
}
}

/// Tests whether the given features can be used.
///
/// To ensure the features work as expected, it is highly recommended to
/// attempt to use the features.
///
/// The test code is subject to change, but currently looks like:
///
/// ```ignore
/// #![feature(FEATURES)]
/// CODE
/// ```
pub fn probe_features(&self, features: &[&str], code: &str) -> bool {
use std::fmt::Write;
let probe = &mut String::new();
write!(probe, "#![feature(").unwrap();
for feature in features {
write!(probe, "{},", feature).unwrap();
}
write!(probe, ")] {}", code).unwrap();
self.probe(probe).unwrap_or(false)
}

/// Emits a config value `has_FEATURE` if `probe_features` returns true.
pub fn emit_has_feature(&self, feature: &str, code: &str) {
if self.probe_features(&[feature], code) {
emit(&format!("has_{}", feature));
}
}

/// Emits the given `cfg` value if `probe_features` returns true.
pub fn emit_features_cfg(&self, features: &[&str], code: &str, cfg: &str) {
if self.probe_features(features, code) {
emit(cfg)
}
}
}

fn mangle(s: &str) -> String {
Expand Down
39 changes: 39 additions & 0 deletions src/tests.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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]
Expand Down Expand Up @@ -133,6 +161,17 @@ fn probe_constant() {
ac.assert_min(1, 39, ac.probe_constant(r#""test".len()"#));
}

#[test]
fn prope_feature() {
let ac = AutoCfg::for_test().unwrap();
// an empty #![features()] has no effect
assert!(ac.probe_features(&[], ""));
// stabilized feature succeeds
ac.assert_nightly(ac.probe_features(&["rust1"], ""));
// fake feature fails
ac.assert_nightly(!ac.probe_features(&["RUSTC_DONT_MAKE_ME_A_LIAR"], ""));
}

#[test]
fn dir_does_not_contain_target() {
assert!(!super::dir_contains_target(
Expand Down

0 comments on commit a1d7429

Please sign in to comment.