Browse Source

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
master
Mahmoud Al-Qudsi 5 years ago
committed by GitHub
parent
commit
4b72474342
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 35
      src/lib.rs
  2. 12
      tests/support/mod.rs

35
src/lib.rs

@ -1867,7 +1867,7 @@ impl Build {
cmd.args.push(sdk_path.trim().into()); cmd.args.push(sdk_path.trim().into());
cmd.args.push("-fembed-bitcode".into()); cmd.args.push("-fembed-bitcode".into());
/* /*
* TODO we probably ultimatedly want the -fembed-bitcode-marker flag * TODO we probably ultimately want the -fembed-bitcode-marker flag
* but can't have it now because of an issue in LLVM: * but can't have it now because of an issue in LLVM:
* https://github.com/alexcrichton/cc-rs/issues/301 * https://github.com/alexcrichton/cc-rs/issues/301
* https://github.com/rust-lang/rust/pull/48896#comment-372192660 * https://github.com/rust-lang/rust/pull/48896#comment-372192660
@ -1919,13 +1919,13 @@ impl Build {
.iter() .iter()
.find(|a| a.starts_with(DRIVER_MODE)) .find(|a| a.starts_with(DRIVER_MODE))
.map(|a| &a[DRIVER_MODE.len()..]); .map(|a| &a[DRIVER_MODE.len()..]);
// chop off leading/trailing whitespace to work around // Chop off leading/trailing whitespace to work around
// semi-buggy build scripts which are shared in // semi-buggy build scripts which are shared in
// makefiles/configure scripts (where spaces are far more // makefiles/configure scripts (where spaces are far more
// lenient) // lenient)
let mut t = Tool::with_clang_driver(PathBuf::from(tool.trim()), driver_mode); let mut t = Tool::with_clang_driver(PathBuf::from(tool.trim()), driver_mode);
if let Some(cc) = wrapper { if let Some(cc_wrapper) = wrapper {
t.cc_wrapper_path = Some(PathBuf::from(cc)); t.cc_wrapper_path = Some(PathBuf::from(cc_wrapper));
} }
for arg in args { for arg in args {
t.cc_wrapper_args.push(arg.into()); t.cc_wrapper_args.push(arg.into());
@ -2065,7 +2065,12 @@ impl Build {
} else { } else {
default.to_string() default.to_string()
}; };
Tool::new(PathBuf::from(compiler))
let mut t = Tool::new(PathBuf::from(compiler));
if let Some(cc_wrapper) = Self::rustc_wrapper_fallback() {
t.cc_wrapper_path = Some(PathBuf::from(cc_wrapper));
}
t
} }
}; };
@ -2141,6 +2146,24 @@ impl Build {
.collect() .collect()
} }
/// Returns a fallback `cc_compiler_wrapper` by introspecting `RUSTC_WRAPPER`
fn rustc_wrapper_fallback() -> Option<String> {
// No explicit CC wrapper was detected, but check if RUSTC_WRAPPER
// is defined and is a build accelerator that is compatible with
// C/C++ compilers (e.g. sccache)
let valid_wrappers = ["sccache"];
let rustc_wrapper = std::env::var_os("RUSTC_WRAPPER")?;
let wrapper_path = Path::new(&rustc_wrapper);
let wrapper_stem = wrapper_path.file_stem()?;
if valid_wrappers.contains(&wrapper_stem.to_str()?) {
Some(rustc_wrapper.to_str()?.to_owned())
} else {
None
}
}
/// Returns compiler path, optional modifier name from whitelist, and arguments vec /// Returns compiler path, optional modifier name from whitelist, and arguments vec
fn env_tool(&self, name: &str) -> Option<(String, Option<String>, Vec<String>)> { fn env_tool(&self, name: &str) -> Option<(String, Option<String>, Vec<String>)> {
let tool = match self.get_var(name) { let tool = match self.get_var(name) {
@ -2200,7 +2223,7 @@ impl Build {
Some(( Some((
maybe_wrapper.to_string(), maybe_wrapper.to_string(),
None, Self::rustc_wrapper_fallback(),
parts.map(|s| s.to_string()).collect(), parts.map(|s| s.to_string()).collect(),
)) ))
} }

12
tests/support/mod.rs

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

Loading…
Cancel
Save