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

Rustc cache #5359

Merged
merged 11 commits into from
Apr 16, 2018
2 changes: 1 addition & 1 deletion src/bin/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
}

if let Some(ref code) = args.value_of("explain") {
let mut procss = config.rustc()?.process();
let mut procss = config.rustc(None)?.process();
procss.arg("--explain").arg(code).exec()?;
return Ok(());
}
Expand Down
8 changes: 6 additions & 2 deletions src/cargo/core/compiler/compilation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,17 @@ pub struct Compilation<'cfg> {
/// Flags to pass to rustdoc when invoked from cargo test, per package.
pub rustdocflags: HashMap<PackageId, Vec<String>>,

pub host: String,
pub target: String,

config: &'cfg Config,
rustc_process: ProcessBuilder,

target_runner: LazyCell<Option<(PathBuf, Vec<String>)>>,
}

impl<'cfg> Compilation<'cfg> {
pub fn new(config: &'cfg Config) -> Compilation<'cfg> {
pub fn new(config: &'cfg Config, rustc_process: ProcessBuilder) -> Compilation<'cfg> {
Compilation {
libraries: HashMap::new(),
native_dirs: BTreeSet::new(), // TODO: deprecated, remove
Expand All @@ -81,14 +83,16 @@ impl<'cfg> Compilation<'cfg> {
cfgs: HashMap::new(),
rustdocflags: HashMap::new(),
config,
rustc_process,
host: String::new(),
target: String::new(),
target_runner: LazyCell::new(),
}
}

/// See `process`.
pub fn rustc_process(&self, pkg: &Package) -> CargoResult<ProcessBuilder> {
self.fill_env(self.config.rustc()?.process(), pkg, true)
self.fill_env(self.rustc_process.clone(), pkg, true)
}

/// See `process`.
Expand Down
4 changes: 1 addition & 3 deletions src/cargo/core/compiler/context/compilation_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,9 +434,7 @@ fn compute_metadata<'a, 'cfg>(
unit.target.name().hash(&mut hasher);
unit.target.kind().hash(&mut hasher);

if let Ok(rustc) = cx.config.rustc() {
rustc.verbose_version.hash(&mut hasher);
}
cx.build_config.rustc.verbose_version.hash(&mut hasher);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my perception, it seemed that build_config should probably stay immutable over the lifetime of the Context (and in fact that is enforced, I think, by #5358).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, not sure I understand this comment :) build_config is not mutated here at all?


// Seed the contents of __CARGO_DEFAULT_LIB_METADATA to the hasher if present.
// This should be the release channel, to get a different hash for each channel.
Expand Down
10 changes: 6 additions & 4 deletions src/cargo/core/compiler/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
let _p = profile::start("Context::probe_target_info");
debug!("probe_target_info");
let host_target_same = match build_config.requested_target {
Some(ref s) if s != &config.rustc()?.host => false,
Some(ref s) if s != &build_config.host_triple() => false,
_ => true,
};

Expand All @@ -150,7 +150,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
config,
target_info,
host_info,
compilation: Compilation::new(config),
compilation: Compilation::new(config, build_config.rustc.process()),
build_state: Arc::new(BuildState::new(&build_config)),
build_config,
fingerprints: HashMap::new(),
Expand Down Expand Up @@ -302,6 +302,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
self.compilation.native_dirs.insert(dir.clone());
}
}
self.compilation.host = self.build_config.host_triple().to_string();
self.compilation.target = self.build_config.target_triple().to_string();
Ok(self.compilation)
}
Expand Down Expand Up @@ -440,7 +441,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
None => return true,
};
let (name, info) = match kind {
Kind::Host => (self.build_config.host_triple.as_ref(), &self.host_info),
Kind::Host => (self.build_config.host_triple(), &self.host_info),
Kind::Target => (self.build_config.target_triple(), &self.target_info),
};
platform.matches(name, info.cfg())
Expand Down Expand Up @@ -652,7 +653,8 @@ fn env_args(
let target = build_config
.requested_target
.as_ref()
.unwrap_or(&build_config.host_triple);
.map(|s| s.as_str())
.unwrap_or(build_config.host_triple());
let key = format!("target.{}.{}", target, name);
if let Some(args) = config.get_list_or_split_string(&key)? {
let args = args.val.into_iter();
Expand Down
13 changes: 6 additions & 7 deletions src/cargo/core/compiler/context/target_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl FileType {
impl TargetInfo {
pub fn new(config: &Config, build_config: &BuildConfig, kind: Kind) -> CargoResult<TargetInfo> {
let rustflags = env_args(config, build_config, None, kind, "RUSTFLAGS")?;
let mut process = config.rustc()?.process();
let mut process = build_config.rustc.process();
process
.arg("-")
.arg("--crate-name")
Expand All @@ -78,20 +78,19 @@ impl TargetInfo {
with_cfg.arg("--print=cfg");

let mut has_cfg_and_sysroot = true;
let output = with_cfg
.exec_with_output()
let (output, error) = build_config
.rustc
.cached_output(&with_cfg)
.or_else(|_| {
has_cfg_and_sysroot = false;
process.exec_with_output()
build_config.rustc.cached_output(&process)
})
.chain_err(|| "failed to run `rustc` to learn about target-specific information")?;

let error = str::from_utf8(&output.stderr).unwrap();
let output = str::from_utf8(&output.stdout).unwrap();
let mut lines = output.lines();
let mut map = HashMap::new();
for crate_type in KNOWN_CRATE_TYPES {
let out = parse_crate_type(crate_type, error, &mut lines)?;
let out = parse_crate_type(crate_type, &error, &mut lines)?;
map.insert(crate_type.to_string(), out);
}

Expand Down
6 changes: 3 additions & 3 deletions src/cargo/core/compiler/custom_build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
.env(
"TARGET",
&match unit.kind {
Kind::Host => &cx.build_config.host_triple,
Kind::Host => &cx.build_config.host_triple(),
Kind::Target => cx.build_config.target_triple(),
},
)
Expand All @@ -141,8 +141,8 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoRes
"debug"
},
)
.env("HOST", &cx.build_config.host_triple)
.env("RUSTC", &cx.config.rustc()?.path)
.env("HOST", &cx.build_config.host_triple())
.env("RUSTC", &cx.build_config.rustc.path)
.env("RUSTDOC", &*cx.config.rustdoc()?)
.inherit_jobserver(&cx.jobserver);

Expand Down
16 changes: 6 additions & 10 deletions src/cargo/core/compiler/fingerprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,9 +220,7 @@ impl Fingerprint {
match *local {
LocalFingerprint::MtimeBased(ref slot, ref path) => {
let path = root.join(path);
let meta = fs::metadata(&path)
.chain_err(|| internal(format!("failed to stat `{}`", path.display())))?;
let mtime = FileTime::from_last_modification_time(&meta);
let mtime = paths::mtime(&path)?;
*slot.0.lock().unwrap() = Some(mtime);
}
LocalFingerprint::EnvBased(..) | LocalFingerprint::Precalculated(..) => continue,
Expand Down Expand Up @@ -457,7 +455,7 @@ fn calculate<'a, 'cfg>(
cx.rustflags_args(unit)?
};
let fingerprint = Arc::new(Fingerprint {
rustc: util::hash_u64(&cx.config.rustc()?.verbose_version),
rustc: util::hash_u64(&cx.build_config.rustc.verbose_version),
target: util::hash_u64(&unit.target),
profile: util::hash_u64(&(&unit.profile, cx.incremental_args(unit)?)),
// Note that .0 is hashed here, not .1 which is the cwd. That doesn't
Expand Down Expand Up @@ -718,22 +716,20 @@ where
I: IntoIterator,
I::Item: AsRef<Path>,
{
let meta = match fs::metadata(output) {
Ok(meta) => meta,
let mtime = match paths::mtime(output) {
Ok(mtime) => mtime,
Err(..) => return None,
};
let mtime = FileTime::from_last_modification_time(&meta);

let any_stale = paths.into_iter().any(|path| {
let path = path.as_ref();
let meta = match fs::metadata(path) {
Ok(meta) => meta,
let mtime2 = match paths::mtime(path) {
Ok(mtime) => mtime,
Err(..) => {
info!("stale: {} -- missing", path.display());
return true;
}
};
let mtime2 = FileTime::from_last_modification_time(&meta);
if mtime2 > mtime {
info!("stale: {} -- {} vs {}", path.display(), mtime2, mtime);
true
Expand Down
38 changes: 22 additions & 16 deletions src/cargo/core/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@ use serde_json;
use core::{Feature, PackageId, Profile, Target};
use core::manifest::Lto;
use core::shell::ColorChoice;
use util::{self, machine_message, Config, ProcessBuilder};
use util::{self, machine_message, Config, Freshness, ProcessBuilder, Rustc};
use util::{internal, join_paths, profile};
use util::paths;
use util::errors::{CargoResult, CargoResultExt, Internal};
use util::Freshness;

use self::job::{Job, Work};
use self::job_queue::JobQueue;
Expand Down Expand Up @@ -48,15 +47,8 @@ pub enum Kind {
}

/// Configuration information for a rustc build.
#[derive(Default, Clone)]
pub struct BuildConfig {
/// The host arch triple
///
/// e.g. x86_64-unknown-linux-gnu, would be
/// - machine: x86_64
/// - hardware-platform: unknown
/// - operating system: linux-gnu
pub host_triple: String,
pub rustc: Rustc,
/// Build information for the host arch
pub host: TargetConfig,
/// The target arch triple, defaults to host arch
Expand Down Expand Up @@ -88,6 +80,7 @@ impl BuildConfig {
config: &Config,
jobs: Option<u32>,
requested_target: &Option<String>,
rustc_info_cache: Option<PathBuf>,
) -> CargoResult<BuildConfig> {
if let &Some(ref s) = requested_target {
if s.trim().is_empty() {
Expand Down Expand Up @@ -125,27 +118,40 @@ impl BuildConfig {
None => None,
};
let jobs = jobs.or(cfg_jobs).unwrap_or(::num_cpus::get() as u32);

let host_triple = config.rustc()?.host.clone();
let host_config = TargetConfig::new(config, &host_triple)?;
let rustc = config.rustc(rustc_info_cache)?;
let host_config = TargetConfig::new(config, &rustc.host)?;
let target_config = match target.as_ref() {
Some(triple) => TargetConfig::new(config, triple)?,
None => host_config.clone(),
};
Ok(BuildConfig {
host_triple,
rustc,
requested_target: target,
jobs,
host: host_config,
target: target_config,
..Default::default()
release: false,
test: false,
doc_all: false,
json_messages: false,
})
}

/// The host arch triple
///
/// e.g. x86_64-unknown-linux-gnu, would be
/// - machine: x86_64
/// - hardware-platform: unknown
/// - operating system: linux-gnu
pub fn host_triple(&self) -> &str {
&self.rustc.host
}

pub fn target_triple(&self) -> &str {
self.requested_target
.as_ref()
.unwrap_or_else(|| &self.host_triple)
.map(|s| s.as_str())
.unwrap_or(self.host_triple())
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_clean.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> {
}
}

let mut build_config = BuildConfig::new(config, Some(1), &opts.target)?;
let mut build_config = BuildConfig::new(config, Some(1), &opts.target, None)?;
build_config.release = opts.release;
let mut cx = Context::new(ws, &resolve, &packages, opts.config, build_config, profiles)?;
cx.prepare_units(None, &units)?;
Expand Down
3 changes: 2 additions & 1 deletion src/cargo/ops/cargo_compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,8 @@ pub fn compile_ws<'a>(
bail!("jobs must be at least 1")
}

let mut build_config = BuildConfig::new(config, jobs, &target)?;
let rustc_info_cache = ws.target_dir().join("rustc_info.json").into_path_unlocked();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mind throwing a . on the front to hide it away?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✔️

let mut build_config = BuildConfig::new(config, jobs, &target, Some(rustc_info_cache))?;
build_config.release = release;
build_config.test = mode == CompileMode::Test || mode == CompileMode::Bench;
build_config.json_messages = message_format == MessageFormat::Json;
Expand Down
2 changes: 1 addition & 1 deletion src/cargo/ops/cargo_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ fn run_doc_tests(
let config = options.compile_opts.config;

// We don't build/rust doctests if target != host
if config.rustc()?.host != compilation.target {
if compilation.host != compilation.target {
return Ok((Test::Doc, errors));
}

Expand Down
5 changes: 2 additions & 3 deletions src/cargo/sources/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use ignore::gitignore::GitignoreBuilder;
use core::{Dependency, Package, PackageId, Registry, Source, SourceId, Summary};
use ops;
use util::{self, internal, CargoResult};
use util::paths;
use util::Config;

pub struct PathSource<'cfg> {
Expand Down Expand Up @@ -529,9 +530,7 @@ impl<'cfg> Source for PathSource<'cfg> {
// condition where this path was rm'ed - either way,
// we can ignore the error and treat the path's mtime
// as 0.
let mtime = fs::metadata(&file)
.map(|meta| FileTime::from_last_modification_time(&meta))
.unwrap_or(FileTime::zero());
let mtime = paths::mtime(&file).unwrap_or(FileTime::zero());
warn!("{} {}", mtime, file.display());
if mtime > max {
max = mtime;
Expand Down
33 changes: 7 additions & 26 deletions src/cargo/util/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,13 +158,12 @@ impl Config {
}

/// Get the path to the `rustc` executable
pub fn rustc(&self) -> CargoResult<&Rustc> {
self.rustc.try_borrow_with(|| {
Rustc::new(
self.get_tool("rustc")?,
self.maybe_get_tool("rustc_wrapper")?,
)
})
pub fn rustc(&self, cache_location: Option<PathBuf>) -> CargoResult<Rustc> {
Rustc::new(
self.get_tool("rustc")?,
self.maybe_get_tool("rustc_wrapper")?,
cache_location,
)
}

/// Get the path to the `cargo` executable
Expand Down Expand Up @@ -193,25 +192,7 @@ impl Config {
.map(PathBuf::from)
.next()
.ok_or(format_err!("no argv[0]"))?;
if argv0.components().count() == 1 {
probe_path(argv0)
} else {
Ok(argv0.canonicalize()?)
}
}

fn probe_path(argv0: PathBuf) -> CargoResult<PathBuf> {
let paths = env::var_os("PATH").ok_or(format_err!("no PATH"))?;
for path in env::split_paths(&paths) {
let candidate = PathBuf::from(path).join(&argv0);
if candidate.is_file() {
// PATH may have a component like "." in it, so we still need to
// canonicalize.
return Ok(candidate.canonicalize()?);
}
}

bail!("no cargo executable candidate found in PATH")
paths::resolve_executable(&argv0)
}

let exe = from_current_exe()
Expand Down
Loading