Skip to content

Commit 20f23d9

Browse files
committed
Add support for wrapping cargo's rustc invocations by setting RUSTC_WRAPPER
1 parent 770512b commit 20f23d9

File tree

5 files changed

+49
-10
lines changed

5 files changed

+49
-10
lines changed

src/cargo/util/config.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,8 @@ impl Config {
9393
}
9494

9595
pub fn rustc(&self) -> CargoResult<&Rustc> {
96-
self.rustc.get_or_try_init(|| Rustc::new(self.get_tool("rustc")?))
96+
self.rustc.get_or_try_init(|| Rustc::new(self.get_tool("rustc")?,
97+
self.maybe_get_tool("rustc_wrapper")?))
9798
}
9899

99100
pub fn cargo_exe(&self) -> CargoResult<&Path> {
@@ -415,18 +416,27 @@ impl Config {
415416
}
416417
}
417418

418-
fn get_tool(&self, tool: &str) -> CargoResult<PathBuf> {
419+
/// Look for a path for `tool` in an environment variable or config path, but return `None`
420+
/// if it's not present.
421+
fn maybe_get_tool(&self, tool: &str) -> CargoResult<Option<PathBuf>> {
419422
let var = tool.chars().flat_map(|c| c.to_uppercase()).collect::<String>();
420423
if let Some(tool_path) = env::var_os(&var) {
421-
return Ok(PathBuf::from(tool_path));
424+
return Ok(Some(PathBuf::from(tool_path)));
422425
}
423426

424427
let var = format!("build.{}", tool);
425428
if let Some(tool_path) = self.get_path(&var)? {
426-
return Ok(tool_path.val);
429+
return Ok(Some(tool_path.val));
427430
}
428431

429-
Ok(PathBuf::from(tool))
432+
Ok(None)
433+
}
434+
435+
/// Look for a path for `tool` in an environment variable or config path, defaulting to `tool`
436+
/// as a path.
437+
fn get_tool(&self, tool: &str) -> CargoResult<PathBuf> {
438+
self.maybe_get_tool(tool)
439+
.map(|t| t.unwrap_or(PathBuf::from(tool)))
430440
}
431441
}
432442

src/cargo/util/rustc.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use util::{self, CargoResult, internal, ChainError, ProcessBuilder};
44

55
pub struct Rustc {
66
pub path: PathBuf,
7+
pub wrapper: Option<PathBuf>,
78
pub verbose_version: String,
89
pub host: String,
910
}
@@ -14,12 +15,12 @@ impl Rustc {
1415
///
1516
/// If successful this function returns a description of the compiler along
1617
/// with a list of its capabilities.
17-
pub fn new(path: PathBuf) -> CargoResult<Rustc> {
18+
pub fn new(path: PathBuf, wrapper: Option<PathBuf>) -> CargoResult<Rustc> {
1819
let mut cmd = util::process(&path);
1920
cmd.arg("-vV");
20-
21+
2122
let output = cmd.exec_with_output()?;
22-
23+
2324
let verbose_version = String::from_utf8(output.stdout).map_err(|_| {
2425
internal("rustc -v didn't return utf8 output")
2526
})?;
@@ -36,12 +37,21 @@ impl Rustc {
3637

3738
Ok(Rustc {
3839
path: path,
40+
wrapper: wrapper,
3941
verbose_version: verbose_version,
4042
host: host,
4143
})
4244
}
4345

4446
pub fn process(&self) -> ProcessBuilder {
45-
util::process(&self.path)
47+
if let Some(ref wrapper) = self.wrapper {
48+
let mut cmd = util::process(wrapper);
49+
{
50+
cmd.arg(&self.path);
51+
}
52+
cmd
53+
} else {
54+
util::process(&self.path)
55+
}
4656
}
4757
}

src/doc/environment-variables.md

+3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ system:
1717
relative to the current working directory.
1818
* `RUSTC` - Instead of running `rustc`, Cargo will execute this specified
1919
compiler instead.
20+
* `RUSTC_WRAPPER` - Instead of simply running `rustc`, Cargo will execute this
21+
specified wrapper instead, passing as its commandline arguments the rustc
22+
invocation, with the first argument being rustc.
2023
* `RUSTDOC` - Instead of running `rustdoc`, Cargo will execute this specified
2124
`rustdoc` instance instead.
2225
* `RUSTFLAGS` - A space-separated list of custom flags to pass to all compiler

tests/build.rs

+15
Original file line numberDiff line numberDiff line change
@@ -2899,3 +2899,18 @@ fn run_proper_binary_main_rs_as_foo() {
28992899
assert_that(p.cargo_process("run").arg("--bin").arg("foo"),
29002900
execs().with_status(0));
29012901
}
2902+
2903+
#[test]
2904+
fn rustc_wrapper() {
2905+
// We don't have /usr/bin/env on Windows.
2906+
if cfg!(windows) { return }
2907+
2908+
let p = project("foo")
2909+
.file("Cargo.toml", &basic_bin_manifest("foo"))
2910+
.file("src/foo.rs", &main_file(r#""i am foo""#, &[]));
2911+
2912+
assert_that(p.cargo_process("build").arg("-v").env("RUSTC_WRAPPER", "/usr/bin/env"),
2913+
execs().with_stderr_contains(
2914+
"[RUNNING] `/usr/bin/env rustc --crate-name foo [..]")
2915+
.with_status(0));
2916+
}

tests/cargotest/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use std::env;
2727
pub mod support;
2828
pub mod install;
2929

30-
thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc")).unwrap());
30+
thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc"), None).unwrap());
3131

3232
pub fn rustc_host() -> String {
3333
RUSTC.with(|r| r.host.clone())
@@ -54,6 +54,7 @@ fn _process(t: &OsStr) -> cargo::util::ProcessBuilder {
5454
.env_remove("__CARGO_DEFAULT_LIB_METADATA")
5555
.env_remove("RUSTC")
5656
.env_remove("RUSTDOC")
57+
.env_remove("RUSTC_WRAPPER")
5758
.env_remove("RUSTFLAGS")
5859
.env_remove("CARGO_INCREMENTAL")
5960
.env_remove("XDG_CONFIG_HOME") // see #2345

0 commit comments

Comments
 (0)