Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support RUSTC_WRAPPER and RUSTC_WORKSPACE_WRAPPER #56

Merged
merged 1 commit into from
Mar 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 40 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ mod tests;
pub struct AutoCfg {
out_dir: PathBuf,
rustc: PathBuf,
rustc_wrapper: Option<PathBuf>,
rustc_workspace_wrapper: Option<PathBuf>,
rustc_version: Version,
target: Option<OsString>,
no_std: bool,
Expand Down Expand Up @@ -168,6 +170,8 @@ impl AutoCfg {

let mut ac = AutoCfg {
rustflags: rustflags(&target, &dir),
rustc_wrapper: get_rustc_wrapper(false),
rustc_workspace_wrapper: get_rustc_wrapper(true),
out_dir: dir,
rustc: rustc,
rustc_version: rustc_version,
Expand Down Expand Up @@ -234,7 +238,18 @@ impl AutoCfg {
static ID: AtomicUsize = ATOMIC_USIZE_INIT;

let id = ID.fetch_add(1, Ordering::Relaxed);
let mut command = Command::new(&self.rustc);

// Build the command with possible wrappers.
let mut rustc = self
.rustc_wrapper
.iter()
.chain(self.rustc_workspace_wrapper.iter())
.chain(Some(&self.rustc));
let mut command = Command::new(rustc.next().unwrap());
for arg in rustc {
command.arg(arg);
}

command
.arg("--crate-name")
.arg(format!("probe{}", id))
Expand Down Expand Up @@ -478,3 +493,27 @@ fn rustflags(target: &Option<OsString>, dir: &Path) -> Vec<String> {

Vec::new()
}

fn get_rustc_wrapper(workspace: bool) -> Option<PathBuf> {
// We didn't really know whether the workspace wrapper is applicable until Cargo started
// deliberately setting or unsetting it in rust-lang/cargo#9601. We'll use the encoded
// rustflags as a proxy for that change for now, but we could instead check version 1.55.
if workspace && env::var_os("CARGO_ENCODED_RUSTFLAGS").is_none() {
return None;
}

let name = if workspace {
"RUSTC_WORKSPACE_WRAPPER"
} else {
"RUSTC_WRAPPER"
};

if let Some(wrapper) = env::var_os(name) {
// NB: `OsStr` didn't get `len` or `is_empty` until 1.9.
if wrapper != OsString::new() {
return Some(wrapper.into());
}
}

None
}
51 changes: 51 additions & 0 deletions tests/wrappers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
extern crate autocfg;

use std::env;

/// Tests that autocfg uses the RUSTC_WRAPPER and/or RUSTC_WORKSPACE_WRAPPER
/// environment variables when running rustc.
#[test]
#[cfg(unix)] // we're using system binaries as wrappers
fn test_wrappers() {
fn set(name: &str, value: Option<bool>) {
match value {
Some(true) => env::set_var(name, "/usr/bin/env"),
Some(false) => env::set_var(name, "/bin/false"),
None => env::remove_var(name),
}
}

// Use the same path as this test binary.
let dir = env::current_exe().unwrap().parent().unwrap().to_path_buf();
env::set_var("OUT_DIR", &format!("{}", dir.display()));

// This is used as a heuristic to detect rust-lang/cargo#9601.
env::set_var("CARGO_ENCODED_RUSTFLAGS", "");

// No wrapper, a good pass-through wrapper, and a bad wrapper.
let variants = [None, Some(true), Some(false)];

for &workspace in &variants {
for &rustc in &variants {
set("RUSTC_WRAPPER", rustc);
set("RUSTC_WORKSPACE_WRAPPER", workspace);

let ac = autocfg::AutoCfg::new().unwrap();
if rustc == Some(false) || workspace == Some(false) {
// Everything should fail with bad wrappers.
assert!(!ac.probe_type("usize"));
} else {
// Try known good and bad types for the wrapped rustc.
assert!(ac.probe_type("usize"));
assert!(!ac.probe_type("mesize"));
}
}
}

// Finally, make sure that `RUSTC_WRAPPER` is applied outermost
// by using something that doesn't pass through at all.
env::set_var("RUSTC_WRAPPER", "/bin/true");
env::set_var("RUSTC_WORKSPACE_WRAPPER", "/bin/false");
let ac = autocfg::AutoCfg::new().unwrap();
assert!(ac.probe_type("mesize")); // anything goes!
}