DP Cache target_metadata. Update all the lifetimes
authorNipunn Koorapati <nipunn@dropbox.com>
Tue, 5 Sep 2017 16:40:01 +0000 (09:40 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Sat, 9 Sep 2017 20:46:02 +0000 (13:46 -0700)
src/cargo/ops/cargo_rustc/context.rs
src/cargo/ops/cargo_rustc/fingerprint.rs
src/cargo/ops/cargo_rustc/mod.rs

index afd36b826a8dcf4842cffff4a94d5ab03940903d..ce3bba0a84115f4559074cd4fc7fce06a6908cbb 100755 (executable)
@@ -55,7 +55,9 @@ pub struct Context<'a, 'cfg: 'a> {
     host_info: TargetInfo,
     profiles: &'a Profiles,
     incremental_enabled: bool,
+
     target_filenames: HashMap<Unit<'a>, Arc<Vec<(PathBuf, Option<PathBuf>, bool)>>>,
+    target_metadatas: HashMap<Unit<'a>, Option<Metadata>>,
 }
 
 #[derive(Clone, Default)]
@@ -154,7 +156,10 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
             used_in_plugin: HashSet::new(),
             incremental_enabled: incremental_enabled,
             jobserver: jobserver,
+
+            // TODO: Pre-Calculate these with a topo-sort, rather than lazy-calculating
             target_filenames: HashMap::new(),
+            target_metadatas: HashMap::new(),
         })
     }
 
@@ -362,13 +367,13 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
 
     /// Returns the directory for the specified unit where fingerprint
     /// information is stored.
-    pub fn fingerprint_dir(&mut self, unit: &Unit) -> PathBuf {
+    pub fn fingerprint_dir(&mut self, unit: &Unit<'a>) -> PathBuf {
         let dir = self.pkg_dir(unit);
         self.layout(unit.kind).fingerprint().join(dir)
     }
 
     /// Returns the appropriate directory layout for either a plugin or not.
-    pub fn build_script_dir(&mut self, unit: &Unit) -> PathBuf {
+    pub fn build_script_dir(&mut self, unit: &Unit<'a>) -> PathBuf {
         assert!(unit.target.is_custom_build());
         assert!(!unit.profile.run_custom_build);
         let dir = self.pkg_dir(unit);
@@ -376,7 +381,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     }
 
     /// Returns the appropriate directory layout for either a plugin or not.
-    pub fn build_script_out_dir(&mut self, unit: &Unit) -> PathBuf {
+    pub fn build_script_out_dir(&mut self, unit: &Unit<'a>) -> PathBuf {
         assert!(unit.target.is_custom_build());
         assert!(unit.profile.run_custom_build);
         let dir = self.pkg_dir(unit);
@@ -394,7 +399,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
 
     /// Returns the appropriate output directory for the specified package and
     /// target.
-    pub fn out_dir(&mut self, unit: &Unit) -> PathBuf {
+    pub fn out_dir(&mut self, unit: &Unit<'a>) -> PathBuf {
         if unit.profile.doc {
             self.layout(unit.kind).root().parent().unwrap().join("doc")
         } else if unit.target.is_custom_build() {
@@ -406,7 +411,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         }
     }
 
-    fn pkg_dir(&mut self, unit: &Unit) -> String {
+    fn pkg_dir(&mut self, unit: &Unit<'a>) -> String {
         let name = unit.pkg.package_id().name();
         match self.target_metadata(unit) {
             Some(meta) => format!("{}-{}", name, meta),
@@ -440,7 +445,17 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     /// We build to the path: "{filename}-{target_metadata}"
     /// We use a linking step to link/copy to a predictable filename
     /// like `target/debug/libfoo.{a,so,rlib}` and such.
-    pub fn target_metadata(&mut self, unit: &Unit) -> Option<Metadata> {
+    pub fn target_metadata(&mut self, unit: &Unit<'a>) -> Option<Metadata> {
+        if let Some(cache) = self.target_metadatas.get(unit) {
+            return cache.clone()
+        }
+
+        let metadata = self.calc_target_metadata(unit);
+        self.target_metadatas.insert(*unit, metadata.clone());
+        metadata
+    }
+
+    fn calc_target_metadata(&mut self, unit: &Unit<'a>) -> Option<Metadata> {
         // No metadata for dylibs because of a couple issues
         // - OSX encodes the dylib name in the executable
         // - Windows rustc multiple files of which we can't easily link all of them
@@ -521,7 +536,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
     }
 
     /// Returns the file stem for a given target/profile combo (with metadata)
-    pub fn file_stem(&mut self, unit: &Unit) -> String {
+    pub fn file_stem(&mut self, unit: &Unit<'a>) -> String {
         match self.target_metadata(unit) {
             Some(ref metadata) => format!("{}-{}", unit.target.crate_name(),
                                           metadata),
@@ -546,7 +561,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
 
     /// Returns an Option because in some cases we don't want to link
     /// (eg a dependent lib)
-    pub fn link_stem(&mut self, unit: &Unit) -> Option<(PathBuf, String)> {
+    pub fn link_stem(&mut self, unit: &Unit<'a>) -> Option<(PathBuf, String)> {
         let src_dir = self.out_dir(unit);
         let bin_stem = self.bin_stem(unit);
         let file_stem = self.file_stem(unit);
@@ -587,6 +602,15 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
             return Ok(cache.clone())
         }
 
+        let result = self.calc_target_filenames(unit);
+        if let Ok(ref ret) = result {
+            self.target_filenames.insert(*unit, ret.clone());
+        }
+        result
+    }
+
+    fn calc_target_filenames(&mut self, unit: &Unit<'a>)
+                            -> CargoResult<Arc<Vec<(PathBuf, Option<PathBuf>, bool)>>> {
         let out_dir = self.out_dir(unit);
         let stem = self.file_stem(unit);
         let link_stem = self.link_stem(unit);
@@ -668,9 +692,7 @@ impl<'a, 'cfg> Context<'a, 'cfg> {
         }
         info!("Target filenames: {:?}", ret);
 
-        let ret = Arc::new(ret);
-        self.target_filenames.insert(*unit, ret.clone());
-        Ok(ret)
+        Ok(Arc::new(ret))
     }
 
     fn used_deps(&self, unit: &Unit<'a>) -> CargoResult<Vec<Unit<'a>>> {
index fd32f2b9cc94928f03c56516f5ed0aa472d0192f..38cef8f1c34ff7d4d2c788f034a7cc39f2135dd0 100644 (file)
@@ -538,7 +538,7 @@ fn write_fingerprint(loc: &Path, fingerprint: &Fingerprint) -> CargoResult<()> {
 }
 
 /// Prepare for work when a package starts to build
-pub fn prepare_init(cx: &mut Context, unit: &Unit) -> CargoResult<()> {
+pub fn prepare_init<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> CargoResult<()> {
     let new1 = cx.fingerprint_dir(unit);
 
     if fs::metadata(&new1).is_err() {
@@ -548,7 +548,7 @@ pub fn prepare_init(cx: &mut Context, unit: &Unit) -> CargoResult<()> {
     Ok(())
 }
 
-pub fn dep_info_loc(cx: &mut Context, unit: &Unit) -> PathBuf {
+pub fn dep_info_loc<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> PathBuf {
     cx.fingerprint_dir(unit).join(&format!("dep-{}", filename(cx, unit)))
 }
 
@@ -670,7 +670,7 @@ fn mtime_if_fresh<I>(output: &Path, paths: I) -> Option<FileTime>
     }
 }
 
-fn filename(cx: &mut Context, unit: &Unit) -> String {
+fn filename<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>) -> String {
     // file_stem includes metadata hash. Thus we have a different
     // fingerprint for every metadata hash version. This works because
     // even if the package is fresh, we'll still link the fresh target
index febeb1c5413c7066d8110eb75cc54f896690bacf..02fa67727a55bb3b9aa4dacee69c5febfa70d6f2 100644 (file)
@@ -684,10 +684,10 @@ fn root_path(cx: &Context, unit: &Unit) -> PathBuf {
     }
 }
 
-fn build_base_args(cx: &mut Context,
-                   cmd: &mut ProcessBuilder,
-                   unit: &Unit,
-                   crate_types: &[&str]) {
+fn build_base_args<'a, 'cfg>(cx: &mut Context<'a, 'cfg>,
+                             cmd: &mut ProcessBuilder,
+                             unit: &Unit<'a>,
+                             crate_types: &[&str]) {
     let Profile {
         ref opt_level, lto, codegen_units, ref rustc_args, debuginfo,
         debug_assertions, overflow_checks, rpath, test, doc: _doc,