From 501823b0bbf9128acf70a36bf27eca1dbc9adbb5 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Mon, 16 Apr 2018 18:50:25 +0300 Subject: [PATCH] Handle non-rustup cargo + rustup rustc in rustc cache --- src/cargo/util/config.rs | 1 + src/cargo/util/rustc.rs | 31 +++++++++++++++++++++++++------ tests/testsuite/cargotest/mod.rs | 11 +++++++++-- 3 files changed, 35 insertions(+), 8 deletions(-) diff --git a/src/cargo/util/config.rs b/src/cargo/util/config.rs index 1dfefb8c8..c7a37e744 100644 --- a/src/cargo/util/config.rs +++ b/src/cargo/util/config.rs @@ -171,6 +171,7 @@ impl Config { Rustc::new( self.get_tool("rustc")?, self.maybe_get_tool("rustc_wrapper")?, + &self.home().join("bin").join("rustc").into_path_unlocked(), if self.cache_rustc_info { cache_location } else { diff --git a/src/cargo/util/rustc.rs b/src/cargo/util/rustc.rs index b9ec492c2..53f74e130 100644 --- a/src/cargo/util/rustc.rs +++ b/src/cargo/util/rustc.rs @@ -35,11 +35,12 @@ impl Rustc { pub fn new( path: PathBuf, wrapper: Option, + rustup_rustc: &Path, cache_location: Option, ) -> CargoResult { let _p = profile::start("Rustc::new"); - let mut cache = Cache::load(&path, cache_location); + let mut cache = Cache::load(&path, rustup_rustc, cache_location); let mut cmd = util::process(&path); cmd.arg("-vV"); @@ -86,6 +87,9 @@ impl Rustc { /// hundred milliseconds! Because we need compiler version info even for no-op /// builds, we cache it here, based on compiler's mtime and rustup's current /// toolchain. +/// +/// https://github.com/rust-lang/cargo/issues/5315 +/// https://github.com/rust-lang/rust/issues/49761 #[derive(Debug)] struct Cache { cache_location: Option, @@ -100,8 +104,8 @@ struct CacheData { } impl Cache { - fn load(rustc: &Path, cache_location: Option) -> Cache { - match (cache_location, rustc_fingerprint(rustc)) { + fn load(rustc: &Path, rustup_rustc: &Path, cache_location: Option) -> Cache { + match (cache_location, rustc_fingerprint(rustc, rustup_rustc)) { (Some(cache_location), Ok(rustc_fingerprint)) => { let empty = CacheData { rustc_fingerprint, @@ -195,7 +199,7 @@ impl Drop for Cache { } } -fn rustc_fingerprint(path: &Path) -> CargoResult { +fn rustc_fingerprint(path: &Path, rustup_rustc: &Path) -> CargoResult { let mut hasher = SipHasher::new_with_keys(0, 0); let path = paths::resolve_executable(path)?; @@ -203,8 +207,20 @@ fn rustc_fingerprint(path: &Path) -> CargoResult { paths::mtime(&path)?.hash(&mut hasher); - match (env::var("RUSTUP_HOME"), env::var("RUSTUP_TOOLCHAIN")) { - (Ok(rustup_home), Ok(rustup_toolchain)) => { + // Rustup can change the effective compiler without touching + // the `rustc` binary, so we try to account for this here. + // If we see rustup's env vars, we mix them into the fingerprint, + // but we also mix in the mtime of the actual compiler (and not + // the rustup shim at `~/.cargo/bin/rustup`), because `RUSTUP_TOOLCHAIN` + // could be just `stable-x86_64-unknown-linux-gnu`, i.e, it could + // not mention the version of Rust at all, which changes after + // `rustup update`. + // + // If we don't see rustup env vars, but it looks like the compiler + // is managed by rustup, we conservatively bail out. + let maybe_rustup = rustup_rustc == path; + match (maybe_rustup, env::var("RUSTUP_HOME"), env::var("RUSTUP_TOOLCHAIN")) { + (_, Ok(rustup_home), Ok(rustup_toolchain)) => { debug!("adding rustup info to rustc fingerprint"); rustup_toolchain.hash(&mut hasher); rustup_home.hash(&mut hasher); @@ -215,6 +231,9 @@ fn rustc_fingerprint(path: &Path) -> CargoResult { .join("rustc"); paths::mtime(&rustup_rustc)?.hash(&mut hasher); } + (true, _, _) => { + bail!("probably rustup rustc, but without rustup's env vars") + } _ => (), } diff --git a/tests/testsuite/cargotest/mod.rs b/tests/testsuite/cargotest/mod.rs index 23efab703..c2852ef14 100644 --- a/tests/testsuite/cargotest/mod.rs +++ b/tests/testsuite/cargotest/mod.rs @@ -3,14 +3,21 @@ use std::time::Duration; use cargo::util::Rustc; use cargo; -use std::path::PathBuf; +use std::path::{Path, PathBuf}; #[macro_use] pub mod support; pub mod install; -thread_local!(pub static RUSTC: Rustc = Rustc::new(PathBuf::from("rustc"), None, None).unwrap()); +thread_local!( +pub static RUSTC: Rustc = Rustc::new( + PathBuf::from("rustc"), + None, + Path::new("should be path to rustup rustc, but we don't care in tests"), + None, +).unwrap() +); pub fn rustc_host() -> String { RUSTC.with(|r| r.host.clone()) -- 2.30.2