From 9f7618b36c07e91f10ce643fc6538a289f3c8935 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 21 Mar 2018 10:54:15 +0300 Subject: [PATCH] Preprobe info for known crate type Previously, we've calculated the set of crate types to learn about by recursively walking the graph of units. However, to actually know dependencies of a unit exactly, we must know target specific info, and we don't know it at this moment (in fact, we are trying calculating it). Note that crate-type calculation is already lazy, we don't have to calc all crate-types upfront. So, let's just scrape this info once for well-known crate types, and fill whatever is left lazily. --- src/cargo/ops/cargo_clean.rs | 2 +- src/cargo/ops/cargo_rustc/context.rs | 61 +++++----------------------- src/cargo/ops/cargo_rustc/mod.rs | 2 +- tests/testsuite/bad_config.rs | 2 +- 4 files changed, 13 insertions(+), 54 deletions(-) diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index f56e1d580..a9e9b9066 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -96,7 +96,7 @@ pub fn clean(ws: &Workspace, opts: &CleanOptions) -> CargoResult<()> { } } - cx.probe_target_info(&units)?; + cx.probe_target_info()?; for unit in units.iter() { rm_rf(&cx.fingerprint_dir(unit), config)?; diff --git a/src/cargo/ops/cargo_rustc/context.rs b/src/cargo/ops/cargo_rustc/context.rs index dd258ee07..cdcfe414f 100644 --- a/src/cargo/ops/cargo_rustc/context.rs +++ b/src/cargo/ops/cargo_rustc/context.rs @@ -1,6 +1,6 @@ #![allow(deprecated)] -use std::collections::{BTreeSet, HashMap, HashSet}; +use std::collections::{HashMap, HashSet}; use std::collections::hash_map::Entry; use std::env; use std::fmt; @@ -234,60 +234,18 @@ impl<'a, 'cfg> Context<'a, 'cfg> { /// Ensure that we've collected all target-specific information to compile /// all the units mentioned in `units`. - pub fn probe_target_info(&mut self, units: &[Unit<'a>]) -> CargoResult<()> { - let mut crate_types = BTreeSet::new(); - let mut visited_units = HashSet::new(); - // pre-fill with `bin` for learning about tests (nothing may be - // explicitly `bin`) as well as `rlib` as it's the coalesced version of - // `lib` in the compiler and we're not sure which we'll see. - crate_types.insert("bin".to_string()); - crate_types.insert("rlib".to_string()); - for unit in units { - self.visit_crate_type(unit, &mut crate_types, &mut visited_units)?; - } - debug!("probe_target_info: crate_types={:?}", crate_types); - self.probe_target_info_kind(&crate_types, Kind::Target)?; + pub fn probe_target_info(&mut self) -> CargoResult<()> { + debug!("probe_target_info"); + self.probe_target_info_kind(Kind::Target)?; if self.requested_target().is_none() { self.host_info = self.target_info.clone(); } else { - self.probe_target_info_kind(&crate_types, Kind::Host)?; + self.probe_target_info_kind(Kind::Host)?; } Ok(()) } - /// A recursive function that checks all crate types (`rlib`, ...) are in `crate_types` - /// for this unit and its dependencies. - /// - /// Tracks visited units to avoid unnecessary work. - fn visit_crate_type( - &self, - unit: &Unit<'a>, - crate_types: &mut BTreeSet, - visited_units: &mut HashSet>, - ) -> CargoResult<()> { - if !visited_units.insert(*unit) { - return Ok(()); - } - for target in unit.pkg.manifest().targets() { - crate_types.extend(target.rustc_crate_types().iter().map(|s| { - if *s == "lib" { - "rlib".to_string() - } else { - s.to_string() - } - })); - } - for dep in self.dep_targets(unit)? { - self.visit_crate_type(&dep, crate_types, visited_units)?; - } - Ok(()) - } - - fn probe_target_info_kind( - &mut self, - crate_types: &BTreeSet, - kind: Kind, - ) -> CargoResult<()> { + fn probe_target_info_kind(&mut self, kind: Kind) -> CargoResult<()> { let rustflags = env_args( self.config, &self.build_config, @@ -309,8 +267,9 @@ impl<'a, 'cfg> Context<'a, 'cfg> { } let crate_type_process = process.clone(); - - for crate_type in crate_types { + const KNOWN_CRATE_TYPES: &[&str] = + &["bin", "rlib", "dylib", "cdylib", "staticlib", "proc-macro"]; + for crate_type in KNOWN_CRATE_TYPES.iter() { process.arg("--crate-type").arg(crate_type); } @@ -331,7 +290,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> { let output = str::from_utf8(&output.stdout).unwrap(); let mut lines = output.lines(); let mut map = HashMap::new(); - for crate_type in crate_types { + for crate_type in KNOWN_CRATE_TYPES { let out = parse_crate_type(crate_type, error, &mut lines)?; map.insert(crate_type.to_string(), out); } diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index 700230d85..a602c7c84 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -169,7 +169,7 @@ pub fn compile_targets<'a, 'cfg: 'a>( let mut queue = JobQueue::new(&cx); cx.prepare()?; - cx.probe_target_info(&units)?; + cx.probe_target_info()?; cx.build_used_in_plugin_map(&units)?; custom_build::build_map(&mut cx, &units)?; diff --git a/tests/testsuite/bad_config.rs b/tests/testsuite/bad_config.rs index 0486297f3..574d84bff 100644 --- a/tests/testsuite/bad_config.rs +++ b/tests/testsuite/bad_config.rs @@ -529,7 +529,7 @@ fn bad_crate_type() { assert_that( p.cargo("build").arg("-v"), execs().with_status(101).with_stderr_contains( - "error: failed to run `rustc` to learn about target-specific information", + "error: failed to run `rustc` to learn about crate-type bad_type information", ), ); } -- 2.30.2