Preprobe info for known crate type
authorAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 21 Mar 2018 07:54:15 +0000 (10:54 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 21 Mar 2018 07:54:15 +0000 (10:54 +0300)
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
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/mod.rs
tests/testsuite/bad_config.rs

index f56e1d58070a582c86fe3dcffd085b8f000f19aa..a9e9b906682e5f9d26c7e77f38fd23ba02580090 100644 (file)
@@ -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)?;
index dd258ee07d92404e1246e7024427919a66cb652f..cdcfe414f927d54cc0ad5ec7c2cd3b48dc5646f8 100644 (file)
@@ -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<String>,
-        visited_units: &mut HashSet<Unit<'a>>,
-    ) -> 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<String>,
-        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);
         }
index 700230d859293a991d67be80c66cf236d4a5d855..a602c7c849e32d1f3ad0cda86371a8a6a5f40067 100644 (file)
@@ -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)?;
 
index 0486297f3d3ebaf31f00c59d65e7a3de842d1117..574d84bff1be97b66d17a7cde8269e13c644a05a 100644 (file)
@@ -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",
         ),
     );
 }