]> git.lizzy.rs Git - rust.git/commitdiff
Move metadata writing earlier.
authorNicholas Nethercote <nnethercote@mozilla.com>
Tue, 30 Apr 2019 05:53:30 +0000 (15:53 +1000)
committerNicholas Nethercote <nnethercote@mozilla.com>
Wed, 1 May 2019 07:17:13 +0000 (17:17 +1000)
The commit moves metadata writing from `link_binary` to
`encode_metadata` (and renames the latter as
`encode_and_write_metadata`). This is at the very start of code
generation.

Cargo.lock
src/librustc_codegen_ssa/back/link.rs
src/librustc_interface/Cargo.toml
src/librustc_interface/passes.rs

index aeddf35eb0dd929f24c2f23abfb6af0e5ffb9e20..a7b8447ef356ae8817a0ebd8f925586e8bee9d2e 100644 (file)
@@ -2802,6 +2802,7 @@ dependencies = [
  "rustc-rayon 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc_allocator 0.0.0",
  "rustc_borrowck 0.0.0",
+ "rustc_codegen_ssa 0.0.0",
  "rustc_codegen_utils 0.0.0",
  "rustc_data_structures 0.0.0",
  "rustc_errors 0.0.0",
@@ -2821,6 +2822,7 @@ dependencies = [
  "syntax 0.0.0",
  "syntax_ext 0.0.0",
  "syntax_pos 0.0.0",
+ "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
index f80618441054af2be9bbeaa7c1f294ff7bdafb07..f25891d77ce5353b6b4564ee96beb44537e46ca2 100644 (file)
@@ -7,7 +7,7 @@
 };
 use rustc::session::search_paths::PathKind;
 use rustc::middle::dependency_format::Linkage;
-use rustc::middle::cstore::{LibSource, NativeLibrary, NativeLibraryKind};
+use rustc::middle::cstore::{EncodedMetadata, LibSource, NativeLibrary, NativeLibraryKind};
 use rustc::util::common::{time, time_ext};
 use rustc::hir::def_id::CrateNum;
 use rustc_data_structures::fx::FxHashSet;
@@ -50,9 +50,9 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
                                               outputs: &OutputFilenames,
                                               crate_name: &str,
                                               target_cpu: &str) {
+    let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
     for &crate_type in sess.crate_types.borrow().iter() {
         // Ignore executable crates if we have -Z no-codegen, as they will error.
-        let output_metadata = sess.opts.output_types.contains_key(&OutputType::Metadata);
         if (sess.opts.debugging_opts.no_codegen || !sess.opts.output_types.should_codegen()) &&
            !output_metadata &&
            crate_type == config::CrateType::Executable {
@@ -68,29 +68,6 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
             check_file_is_writeable(obj, sess);
         }
 
-        if outputs.outputs.contains_key(&OutputType::Metadata) {
-            let out_filename = filename_for_metadata(sess, crate_name, outputs);
-            // To avoid races with another rustc process scanning the output directory,
-            // we need to write the file somewhere else and atomically move it to its
-            // final destination, with a `fs::rename` call. In order for the rename to
-            // always succeed, the temporary file needs to be on the same filesystem,
-            // which is why we create it inside the output directory specifically.
-            let metadata_tmpdir = TempFileBuilder::new()
-                .prefix("rmeta")
-                .tempdir_in(out_filename.parent().unwrap())
-                .unwrap_or_else(|err| sess.fatal(&format!("couldn't create a temp dir: {}", err)));
-            let metadata = emit_metadata(sess, codegen_results, &metadata_tmpdir);
-            match fs::rename(&metadata, &out_filename) {
-                Ok(_) => {
-                    if sess.opts.debugging_opts.emit_directives {
-                        sess.parse_sess.span_diagnostic.maybe_emit_json_directive(
-                            format!("metadata file written: {}", out_filename.display()));
-                    }
-                }
-                Err(e) => sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)),
-            }
-        }
-
         let tmpdir = TempFileBuilder::new().prefix("rustc").tempdir().unwrap_or_else(|err|
             sess.fatal(&format!("couldn't create a temp dir: {}", err)));
 
@@ -248,13 +225,13 @@ pub fn each_linked_rlib(sess: &Session,
 /// building an `.rlib` (stomping over one another), or writing an `.rmeta` into a
 /// directory being searched for `extern crate` (observing an incomplete file).
 /// The returned path is the temporary file containing the complete metadata.
-fn emit_metadata<'a>(
+pub fn emit_metadata<'a>(
     sess: &'a Session,
-    codegen_results: &CodegenResults,
+    metadata: &EncodedMetadata,
     tmpdir: &TempDir
 ) -> PathBuf {
     let out_filename = tmpdir.path().join(METADATA_FILENAME);
-    let result = fs::write(&out_filename, &codegen_results.metadata.raw_data);
+    let result = fs::write(&out_filename, &metadata.raw_data);
 
     if let Err(e) = result {
         sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e));
@@ -338,7 +315,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(sess: &'a Session,
         RlibFlavor::Normal => {
             // Instead of putting the metadata in an object file section, rlibs
             // contain the metadata in a separate file.
-            ab.add_file(&emit_metadata(sess, codegen_results, tmpdir));
+            ab.add_file(&emit_metadata(sess, &codegen_results.metadata, tmpdir));
 
             // For LTO purposes, the bytecode of this library is also inserted
             // into the archive.
index fa2a5d2fc89bc1798ce6fb5d8952ac05edc16314..bcaa4216109aa7c839301286d4bae000ba6b7e2e 100644 (file)
@@ -24,6 +24,7 @@ rustc_borrowck = { path = "../librustc_borrowck" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_traits = { path = "../librustc_traits" }
 rustc_data_structures = { path = "../librustc_data_structures" }
+rustc_codegen_ssa = { path = "../librustc_codegen_ssa" }
 rustc_codegen_utils = { path = "../librustc_codegen_utils" }
 rustc_metadata = { path = "../librustc_metadata" }
 rustc_mir = { path = "../librustc_mir" }
@@ -34,3 +35,4 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_plugin = { path = "../librustc_plugin" }
 rustc_privacy = { path = "../librustc_privacy" }
 rustc_resolve = { path = "../librustc_resolve" }
+tempfile = "3.0.5"
index 38d641d2f60761994a8a964b3f1f4bd00b957882..6d3115c621343ad1eb131caa65d70a5e61fb26c1 100644 (file)
@@ -20,7 +20,9 @@
 use rustc::session::search_paths::PathKind;
 use rustc_allocator as allocator;
 use rustc_borrowck as borrowck;
+use rustc_codegen_ssa::back::link::emit_metadata;
 use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_codegen_utils::link::filename_for_metadata;
 use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::stable_hasher::StableHasher;
@@ -50,6 +52,7 @@
 use syntax_ext;
 
 use serialize::json;
+use tempfile::Builder as TempFileBuilder;
 
 use std::any::Any;
 use std::env;
@@ -999,7 +1002,10 @@ fn analysis<'tcx>(
     Ok(())
 }
 
-fn encode_metadata<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>) -> (middle::cstore::EncodedMetadata, bool) {
+fn encode_and_write_metadata<'tcx>(
+    tcx: TyCtxt<'_, 'tcx, 'tcx>,
+    outputs: &OutputFilenames,
+) -> (middle::cstore::EncodedMetadata, bool) {
     #[derive(PartialEq, Eq, PartialOrd, Ord)]
     enum MetadataKind {
         None,
@@ -1020,14 +1026,41 @@ enum MetadataKind {
         }
     }).max().unwrap_or(MetadataKind::None);
 
-    let need_metadata_module = metadata_kind == MetadataKind::Compressed;
-
     let metadata = match metadata_kind {
         MetadataKind::None => middle::cstore::EncodedMetadata::new(),
         MetadataKind::Uncompressed |
         MetadataKind::Compressed => tcx.encode_metadata(),
     };
 
+    let need_metadata_file = tcx.sess.opts.output_types.contains_key(&OutputType::Metadata);
+    if need_metadata_file {
+        let crate_name = &tcx.crate_name(LOCAL_CRATE).as_str();
+        let out_filename = filename_for_metadata(tcx.sess, crate_name, outputs);
+        // To avoid races with another rustc process scanning the output directory,
+        // we need to write the file somewhere else and atomically move it to its
+        // final destination, with an `fs::rename` call. In order for the rename to
+        // always succeed, the temporary file needs to be on the same filesystem,
+        // which is why we create it inside the output directory specifically.
+        let metadata_tmpdir = TempFileBuilder::new()
+            .prefix("rmeta")
+            .tempdir_in(out_filename.parent().unwrap())
+            .unwrap_or_else(|err| {
+                tcx.sess.fatal(&format!("couldn't create a temp dir: {}", err))
+            });
+        let metadata_filename = emit_metadata(tcx.sess, &metadata, &metadata_tmpdir);
+        match std::fs::rename(&metadata_filename, &out_filename) {
+            Ok(_) => {
+                if tcx.sess.opts.debugging_opts.emit_directives {
+                    tcx.sess.parse_sess.span_diagnostic.maybe_emit_json_directive(
+                        format!("metadata file written: {}", out_filename.display()));
+                }
+            }
+            Err(e) => tcx.sess.fatal(&format!("failed to write {}: {}", out_filename.display(), e)),
+        }
+    }
+
+    let need_metadata_module = metadata_kind == MetadataKind::Compressed;
+
     (metadata, need_metadata_module)
 }
 
@@ -1048,8 +1081,8 @@ pub fn start_codegen<'tcx>(
         middle::dependency_format::calculate(tcx)
     });
 
-    let (metadata, need_metadata_module) = time(tcx.sess, "metadata encoding", || {
-        encode_metadata(tcx)
+    let (metadata, need_metadata_module) = time(tcx.sess, "metadata encoding and writing", || {
+        encode_and_write_metadata(tcx, outputs)
     });
 
     tcx.sess.profiler(|p| p.start_activity("codegen crate"));