about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2016-12-29 13:23:38 +1300
committerNick Cameron <ncameron@mozilla.com>2016-12-29 18:17:07 +1300
commitb059a80d4c3911a9e59d517930ee6928b329cc35 (patch)
tree72ce2210b39c5a7880ed7e625da09a6588baf2f1
parent9c8916661105322df7774378a264eb25b873401b (diff)
downloadrust-b059a80d4c3911a9e59d517930ee6928b329cc35.tar.gz
rust-b059a80d4c3911a9e59d517930ee6928b329cc35.zip
Support --emit=foo,metadata
-rw-r--r--src/librustc/middle/dependency_format.rs2
-rw-r--r--src/librustc/session/config.rs13
-rw-r--r--src/librustc_trans/back/link.rs77
3 files changed, 66 insertions, 26 deletions
diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs
index 662b5a2e2e2..e60d0533c9f 100644
--- a/src/librustc/middle/dependency_format.rs
+++ b/src/librustc/middle/dependency_format.rs
@@ -103,7 +103,7 @@ pub fn calculate(sess: &session::Session) {
 
 fn calculate_type(sess: &session::Session,
                   ty: config::CrateType) -> DependencyList {
-    if sess.opts.output_types.contains_key(&config::OutputType::Metadata) {
+    if !sess.opts.output_types.should_trans() {
         return Vec::new();
     }
 
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 4cdf821c925..b3cb5ace45b 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -156,6 +156,19 @@ impl OutputTypes {
     pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option<PathBuf>> {
         self.0.values()
     }
+
+    // True if any of the output types require codegen or linking.
+    pub fn should_trans(&self) -> bool {
+        self.0.keys().any(|k| match *k {
+            OutputType::Bitcode |
+            OutputType::Assembly |
+            OutputType::LlvmAssembly |
+            OutputType::Object |
+            OutputType::Exe => true,
+            OutputType::Metadata |
+            OutputType::DepInfo => false,
+        })
+    }
 }
 
 
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index 58fe1e8e1c2..defbb44448a 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -192,7 +192,7 @@ pub fn link_binary(sess: &Session,
     for &crate_type in sess.crate_types.borrow().iter() {
         // Ignore executable crates if we have -Z no-trans, as they will error.
         if (sess.opts.debugging_opts.no_trans ||
-            sess.opts.output_types.contains_key(&OutputType::Metadata)) &&
+            !sess.opts.output_types.should_trans()) &&
            crate_type == config::CrateTypeExecutable {
             continue;
         }
@@ -201,13 +201,13 @@ pub fn link_binary(sess: &Session,
            bug!("invalid output type `{:?}` for target os `{}`",
                 crate_type, sess.opts.target_triple);
         }
-        let out_file = link_binary_output(sess, trans, crate_type, outputs, crate_name);
-        out_filenames.push(out_file);
+        let mut out_files = link_binary_output(sess, trans, crate_type, outputs, crate_name);
+        out_filenames.append(&mut out_files);
     }
 
     // Remove the temporary object file and metadata if we aren't saving temps
     if !sess.opts.cg.save_temps {
-        if !sess.opts.output_types.contains_key(&OutputType::Metadata) {
+        if sess.opts.output_types.should_trans() {
             for obj in object_filenames(trans, outputs) {
                 remove(sess, &obj);
             }
@@ -256,16 +256,21 @@ fn is_writeable(p: &Path) -> bool {
     }
 }
 
+fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilenames) -> PathBuf {
+    let out_filename = outputs.single_output_file.clone()
+        .unwrap_or(outputs
+            .out_directory
+            .join(&format!("lib{}{}.rmeta", crate_name, sess.opts.cg.extra_filename)));
+    check_file_is_writeable(&out_filename, sess);
+    out_filename
+}
+
 pub fn filename_for_input(sess: &Session,
                           crate_type: config::CrateType,
                           crate_name: &str,
                           outputs: &OutputFilenames) -> PathBuf {
     let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
 
-    if outputs.outputs.contains_key(&OutputType::Metadata) {
-        return outputs.out_directory.join(&format!("lib{}.rmeta", libname));
-    }
-
     match crate_type {
         config::CrateTypeRlib => {
             outputs.out_directory.join(&format!("lib{}.rlib", libname))
@@ -327,27 +332,41 @@ pub fn each_linked_rlib(sess: &Session,
     }
 }
 
+fn out_filename(sess: &Session,
+                crate_type: config::CrateType,
+                outputs: &OutputFilenames,
+                crate_name: &str)
+                -> PathBuf {
+    let default_filename = filename_for_input(sess, crate_type, crate_name, outputs);
+    let out_filename = outputs.outputs.get(&OutputType::Exe)
+                              .and_then(|s| s.to_owned())
+                              .or_else(|| outputs.single_output_file.clone())
+                              .unwrap_or(default_filename);
+
+    check_file_is_writeable(&out_filename, sess);
+
+    out_filename
+}
+
+// Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
+// check this already -- however, the Linux linker will happily overwrite a
+// read-only file.  We should be consistent.
+fn check_file_is_writeable(file: &Path, sess: &Session) {
+    if !is_writeable(file) {
+        sess.fatal(&format!("output file {} is not writeable -- check its \
+                            permissions", file.display()));
+    }
+}
+
 fn link_binary_output(sess: &Session,
                       trans: &CrateTranslation,
                       crate_type: config::CrateType,
                       outputs: &OutputFilenames,
-                      crate_name: &str) -> PathBuf {
+                      crate_name: &str) -> Vec<PathBuf> {
     let objects = object_filenames(trans, outputs);
-    let default_filename = filename_for_input(sess, crate_type, crate_name,
-                                              outputs);
-    let out_filename = outputs.outputs.get(&OutputType::Exe)
-                              .and_then(|s| s.to_owned())
-                              .or_else(|| outputs.single_output_file.clone())
-                              .unwrap_or(default_filename);
 
-    // Make sure files are writeable.  Mac, FreeBSD, and Windows system linkers
-    // check this already -- however, the Linux linker will happily overwrite a
-    // read-only file.  We should be consistent.
-    for file in objects.iter().chain(Some(&out_filename)) {
-        if !is_writeable(file) {
-            sess.fatal(&format!("output file {} is not writeable -- check its \
-                                permissions", file.display()));
-        }
+    for file in &objects {
+        check_file_is_writeable(file, sess);
     }
 
     let tmpdir = match TempDir::new("rustc") {
@@ -355,9 +374,16 @@ fn link_binary_output(sess: &Session,
         Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
     };
 
+    let mut out_filenames = vec![];
+
     if outputs.outputs.contains_key(&OutputType::Metadata) {
+        let out_filename = filename_for_metadata(sess, crate_name, outputs);
         emit_metadata(sess, trans, &out_filename);
-    } else {
+        out_filenames.push(out_filename);
+    }
+
+    if outputs.outputs.should_trans() {
+        let out_filename = out_filename(sess, crate_type, outputs, crate_name);
         match crate_type {
             config::CrateTypeRlib => {
                 link_rlib(sess, Some(trans), &objects, &out_filename,
@@ -371,9 +397,10 @@ fn link_binary_output(sess: &Session,
                               outputs, tmpdir.path());
             }
         }
+        out_filenames.push(out_filename);
     }
 
-    out_filename
+    out_filenames
 }
 
 fn object_filenames(trans: &CrateTranslation,