Skip to content

Commit 4b72474

Browse files
authored
Detect and use sccache by introspecting RUSTC_WRAPPER (#475)
* Detect and use `sccache` via `RUSTC_WRAPPER` If no other C/C++ caching tool is found by inspecting `CC` and `CXX`, `RUSTC_WRAPPER` is tested to see if an output-caching wrapper for `rustc` is in use. If that is the case and it is a wrapper known to also support C/C++ caching, use it. (Also correct/clarify a misnamed variable that caused me some confusion looking over the code.) * Support RUSTC_WRAPPER on Windows and with absolute paths When checking for possible `RUSTC_WRAPPER`s that we can use to cache C/C++ output, allow for filename extensions (e.g. `sccache.exe`) and absolute paths (e.g. `/usr/local/bin/sccache`). Closes #473
1 parent aebeadd commit 4b72474

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

src/lib.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1867,7 +1867,7 @@ impl Build {
18671867
cmd.args.push(sdk_path.trim().into());
18681868
cmd.args.push("-fembed-bitcode".into());
18691869
/*
1870-
* TODO we probably ultimatedly want the -fembed-bitcode-marker flag
1870+
* TODO we probably ultimately want the -fembed-bitcode-marker flag
18711871
* but can't have it now because of an issue in LLVM:
18721872
* https://github.com/alexcrichton/cc-rs/issues/301
18731873
* https://github.com/rust-lang/rust/pull/48896#comment-372192660
@@ -1919,13 +1919,13 @@ impl Build {
19191919
.iter()
19201920
.find(|a| a.starts_with(DRIVER_MODE))
19211921
.map(|a| &a[DRIVER_MODE.len()..]);
1922-
// chop off leading/trailing whitespace to work around
1922+
// Chop off leading/trailing whitespace to work around
19231923
// semi-buggy build scripts which are shared in
19241924
// makefiles/configure scripts (where spaces are far more
19251925
// lenient)
19261926
let mut t = Tool::with_clang_driver(PathBuf::from(tool.trim()), driver_mode);
1927-
if let Some(cc) = wrapper {
1928-
t.cc_wrapper_path = Some(PathBuf::from(cc));
1927+
if let Some(cc_wrapper) = wrapper {
1928+
t.cc_wrapper_path = Some(PathBuf::from(cc_wrapper));
19291929
}
19301930
for arg in args {
19311931
t.cc_wrapper_args.push(arg.into());
@@ -2065,7 +2065,12 @@ impl Build {
20652065
} else {
20662066
default.to_string()
20672067
};
2068-
Tool::new(PathBuf::from(compiler))
2068+
2069+
let mut t = Tool::new(PathBuf::from(compiler));
2070+
if let Some(cc_wrapper) = Self::rustc_wrapper_fallback() {
2071+
t.cc_wrapper_path = Some(PathBuf::from(cc_wrapper));
2072+
}
2073+
t
20692074
}
20702075
};
20712076

@@ -2141,6 +2146,24 @@ impl Build {
21412146
.collect()
21422147
}
21432148

2149+
/// Returns a fallback `cc_compiler_wrapper` by introspecting `RUSTC_WRAPPER`
2150+
fn rustc_wrapper_fallback() -> Option<String> {
2151+
// No explicit CC wrapper was detected, but check if RUSTC_WRAPPER
2152+
// is defined and is a build accelerator that is compatible with
2153+
// C/C++ compilers (e.g. sccache)
2154+
let valid_wrappers = ["sccache"];
2155+
2156+
let rustc_wrapper = std::env::var_os("RUSTC_WRAPPER")?;
2157+
let wrapper_path = Path::new(&rustc_wrapper);
2158+
let wrapper_stem = wrapper_path.file_stem()?;
2159+
2160+
if valid_wrappers.contains(&wrapper_stem.to_str()?) {
2161+
Some(rustc_wrapper.to_str()?.to_owned())
2162+
} else {
2163+
None
2164+
}
2165+
}
2166+
21442167
/// Returns compiler path, optional modifier name from whitelist, and arguments vec
21452168
fn env_tool(&self, name: &str) -> Option<(String, Option<String>, Vec<String>)> {
21462169
let tool = match self.get_var(name) {
@@ -2200,7 +2223,7 @@ impl Build {
22002223

22012224
Some((
22022225
maybe_wrapper.to_string(),
2203-
None,
2226+
Self::rustc_wrapper_fallback(),
22042227
parts.map(|s| s.to_string()).collect(),
22052228
))
22062229
}

tests/support/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,18 @@ pub struct Execution {
2222

2323
impl Test {
2424
pub fn new() -> Test {
25+
// This is ugly: `sccache` needs to introspect the compiler it is
26+
// executing, as it adjusts its behavior depending on the
27+
// language/compiler. This crate's test driver uses mock compilers that
28+
// are obviously not supported by sccache, so the tests fail if
29+
// RUSTC_WRAPPER is set. rust doesn't build test dependencies with
30+
// the `test` feature enabled, so we can't conditionally disable the
31+
// usage of `sccache` if running in a test environment, at least not
32+
// without setting an environment variable here and testing for it
33+
// there. Explicitly deasserting RUSTC_WRAPPER here seems to be the
34+
// lesser of the two evils.
35+
env::remove_var("RUSTC_WRAPPER");
36+
2537
let mut gcc = PathBuf::from(env::current_exe().unwrap());
2638
gcc.pop();
2739
if gcc.ends_with("deps") {

0 commit comments

Comments
 (0)