]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Support output filenames for each emit type
authorAlex Crichton <alex@alexcrichton.com>
Wed, 30 Sep 2015 17:08:37 +0000 (10:08 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 30 Sep 2015 18:12:30 +0000 (11:12 -0700)
Currently the compiler supports the ability to emit multiple output types as
part of one compilation (e.g. asm, LLVM IR, bytecode, link, dep-info, etc). It
does not, however, support the ability to customize the output filename for each
of these output types. The `-o` flag is ignored if multiple emit types are
specified (and the compiler emits a warning about this).

Normally this doesn't matter too much, but in the case of `dep-info` it can lead
to a number of problems (e.g. see #28716). By allowing customization of the
output filename for each emit type we're able to solve the problems in that
issue.

This commit adds support for the `--emit` option to the compiler to look like:

    rustc foo.rs --emit dep-info=.deps/foo.d,link

This indicates that the `dep-info` output type will be placed at `.deps/foo.d`
and the `link` output type will otherwise be determined via the `--out-dir` and
`-o` flags.

Closes #28716

man/rustc.1
src/librustc/session/config.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_trans/back/link.rs
src/librustc_trans/back/write.rs
src/librustdoc/test.rs
src/test/run-make/issue-19371/foo.rs
src/test/run-make/output-type-permutations/Makefile

index 3ac79ecae64e5b4feaa298c0df7f54ac2cfd9aa6..56e3fe0515eb9b7dbe34dc8fed719acb39686347 100644 (file)
@@ -53,7 +53,9 @@ Comma separated list of types of crates for the compiler to emit.
 Specify the name of the crate being built.
 .TP
 \fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|link|dep\-info]
-Configure the output that \fBrustc\fR will produce.
+Configure the output that \fBrustc\fR will produce. Each option may also be of
+the form KIND=PATH to specify the explicit output location for that particular
+emission kind.
 .TP
 \fB\-\-print\fR [crate\-name|file\-names|sysroot]
 Comma separated list of compiler information to print on stdout.
@@ -66,7 +68,8 @@ Equivalent to \fI\-C\ opt\-level=2\fR.
 .TP
 \fB\-o\fR \fIFILENAME\fR
 Write output to \fIFILENAME\fR.
-Ignored if multiple \fI\-\-emit\fR outputs are specified.
+Ignored if multiple \fI\-\-emit\fR outputs are specified which don't have an
+explicit path otherwise.
 .TP
 \fB\-\-out\-dir\fR \fIDIR\fR
 Write output to compiler\[hy]chosen filename in \fIDIR\fR.
index dcc4ca137ead99fd72bc3e09088e63cc9408af90..0739420ea4d684889d8565b2fa59a2f9c52c4276 100644 (file)
@@ -15,7 +15,6 @@
 pub use self::CrateType::*;
 pub use self::Passes::*;
 pub use self::OptLevel::*;
-pub use self::OutputType::*;
 pub use self::DebugInfoLevel::*;
 
 use session::{early_error, early_warn, Session};
@@ -62,14 +61,14 @@ pub enum DebugInfoLevel {
     FullDebugInfo,
 }
 
-#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
+#[derive(Clone, Copy, PartialEq, Eq, Hash)]
 pub enum OutputType {
-    OutputTypeBitcode,
-    OutputTypeAssembly,
-    OutputTypeLlvmAssembly,
-    OutputTypeObject,
-    OutputTypeExe,
-    OutputTypeDepInfo,
+    Bitcode,
+    Assembly,
+    LlvmAssembly,
+    Object,
+    Exe,
+    DepInfo,
 }
 
 #[derive(Clone)]
@@ -85,7 +84,7 @@ pub struct Options {
     pub lint_opts: Vec<(String, lint::Level)>,
     pub lint_cap: Option<lint::Level>,
     pub describe_lints: bool,
-    pub output_types: Vec<OutputType>,
+    pub output_types: HashMap<OutputType, Option<PathBuf>>,
     // This was mutable for rustpkg, which updates search paths based on the
     // parsed code. It remains mutable in case its replacements wants to use
     // this.
@@ -105,8 +104,6 @@ pub struct Options {
     pub always_build_mir: bool,
     pub no_analysis: bool,
     pub debugging_opts: DebuggingOptions,
-    /// Whether to write dependency files. It's (enabled, optional filename).
-    pub write_dependency_info: (bool, Option<PathBuf>),
     pub prints: Vec<PrintRequest>,
     pub cg: CodegenOptions,
     pub color: ColorConfig,
@@ -151,26 +148,25 @@ pub struct OutputFilenames {
     pub out_filestem: String,
     pub single_output_file: Option<PathBuf>,
     pub extra: String,
+    pub outputs: HashMap<OutputType, Option<PathBuf>>,
 }
 
 impl OutputFilenames {
     pub fn path(&self, flavor: OutputType) -> PathBuf {
-        match self.single_output_file {
-            Some(ref path) => return path.clone(),
-            None => {}
-        }
-        self.temp_path(flavor)
+        self.outputs.get(&flavor).and_then(|p| p.to_owned())
+            .or_else(|| self.single_output_file.clone())
+            .unwrap_or_else(|| self.temp_path(flavor))
     }
 
     pub fn temp_path(&self, flavor: OutputType) -> PathBuf {
         let base = self.out_directory.join(&self.filestem());
         match flavor {
-            OutputTypeBitcode => base.with_extension("bc"),
-            OutputTypeAssembly => base.with_extension("s"),
-            OutputTypeLlvmAssembly => base.with_extension("ll"),
-            OutputTypeObject => base.with_extension("o"),
-            OutputTypeDepInfo => base.with_extension("d"),
-            OutputTypeExe => base,
+            OutputType::Bitcode => base.with_extension("bc"),
+            OutputType::Assembly => base.with_extension("s"),
+            OutputType::LlvmAssembly => base.with_extension("ll"),
+            OutputType::Object => base.with_extension("o"),
+            OutputType::DepInfo => base.with_extension("d"),
+            OutputType::Exe => base,
         }
     }
 
@@ -206,7 +202,7 @@ pub fn basic_options() -> Options {
         lint_opts: Vec::new(),
         lint_cap: None,
         describe_lints: false,
-        output_types: Vec::new(),
+        output_types: HashMap::new(),
         search_paths: SearchPaths::new(),
         maybe_sysroot: None,
         target_triple: host_triple().to_string(),
@@ -218,7 +214,6 @@ pub fn basic_options() -> Options {
         always_build_mir: false,
         no_analysis: false,
         debugging_opts: basic_debugging_options(),
-        write_dependency_info: (false, None),
         prints: Vec::new(),
         cg: basic_codegen_options(),
         color: Auto,
@@ -907,31 +902,30 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         unsafe { llvm::LLVMSetDebug(1); }
     }
 
-    let mut output_types = Vec::new();
+    let mut output_types = HashMap::new();
     if !debugging_opts.parse_only && !no_trans {
-        let unparsed_output_types = matches.opt_strs("emit");
-        for unparsed_output_type in &unparsed_output_types {
-            for part in unparsed_output_type.split(',') {
-                let output_type = match part {
-                    "asm" => OutputTypeAssembly,
-                    "llvm-ir" => OutputTypeLlvmAssembly,
-                    "llvm-bc" => OutputTypeBitcode,
-                    "obj" => OutputTypeObject,
-                    "link" => OutputTypeExe,
-                    "dep-info" => OutputTypeDepInfo,
-                    _ => {
+        for list in matches.opt_strs("emit") {
+            for output_type in list.split(',') {
+                let mut parts = output_type.splitn(2, '=');
+                let output_type = match parts.next().unwrap() {
+                    "asm" => OutputType::Assembly,
+                    "llvm-ir" => OutputType::LlvmAssembly,
+                    "llvm-bc" => OutputType::Bitcode,
+                    "obj" => OutputType::Object,
+                    "link" => OutputType::Exe,
+                    "dep-info" => OutputType::DepInfo,
+                    part => {
                         early_error(color, &format!("unknown emission type: `{}`",
                                                     part))
                     }
                 };
-                output_types.push(output_type)
+                let path = parts.next().map(PathBuf::from);
+                output_types.insert(output_type, path);
             }
         }
     };
-    output_types.sort();
-    output_types.dedup();
     if output_types.is_empty() {
-        output_types.push(OutputTypeExe);
+        output_types.insert(OutputType::Exe, None);
     }
 
     let cg = build_codegen_options(matches, color);
@@ -1004,7 +998,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
     let test = matches.opt_present("test");
-    let write_dependency_info = (output_types.contains(&OutputTypeDepInfo), None);
 
     let prints = matches.opt_strs("print").into_iter().map(|s| {
         match &*s {
@@ -1059,7 +1052,6 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         always_build_mir: always_build_mir,
         no_analysis: no_analysis,
         debugging_opts: debugging_opts,
-        write_dependency_info: write_dependency_info,
         prints: prints,
         cg: cg,
         color: color,
index ce04a5befd93978c2a09af235e9bc7a46ab8815e..e2835ae8f0d6f9cd3aaf7889a100c3821d060306 100644 (file)
@@ -12,7 +12,7 @@
 use rustc::front::map as hir_map;
 use rustc_mir as mir;
 use rustc::session::Session;
-use rustc::session::config::{self, Input, OutputFilenames};
+use rustc::session::config::{self, Input, OutputFilenames, OutputType};
 use rustc::session::search_paths::PathKind;
 use rustc::lint;
 use rustc::metadata;
@@ -36,6 +36,7 @@
 
 use serialize::json;
 
+use std::collections::HashMap;
 use std::env;
 use std::ffi::{OsString, OsStr};
 use std::fs;
@@ -117,7 +118,7 @@ macro_rules! controller_entry_point{($point: ident, $tsess: expr, $make_state: e
         let arenas = ty::CtxtArenas::new();
         let ast_map = make_map(&sess, &mut hir_forest);
 
-        write_out_deps(&sess, input, &outputs, &id[..]);
+        write_out_deps(&sess, &outputs, &id);
 
         controller_entry_point!(after_write_deps,
                                 sess,
@@ -807,16 +808,16 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
                                trans: &trans::CrateTranslation,
                                outputs: &OutputFilenames) {
     if sess.opts.cg.no_integrated_as {
-        let output_type = config::OutputTypeAssembly;
-
+        let mut map = HashMap::new();
+        map.insert(OutputType::Assembly, None);
         time(sess.time_passes(), "LLVM passes", ||
-            write::run_passes(sess, trans, &[output_type], outputs));
+            write::run_passes(sess, trans, &map, outputs));
 
         write::run_assembler(sess, outputs);
 
         // Remove assembly source, unless --save-temps was specified
         if !sess.opts.cg.save_temps {
-            fs::remove_file(&outputs.temp_path(config::OutputTypeAssembly)).unwrap();
+            fs::remove_file(&outputs.temp_path(OutputType::Assembly)).unwrap();
         }
     } else {
         time(sess.time_passes(), "LLVM passes", ||
@@ -847,16 +848,12 @@ fn escape_dep_filename(filename: &str) -> String {
     filename.replace(" ", "\\ ")
 }
 
-fn write_out_deps(sess: &Session,
-                  input: &Input,
-                  outputs: &OutputFilenames,
-                  id: &str) {
-
+fn write_out_deps(sess: &Session, outputs: &OutputFilenames, id: &str) {
     let mut out_filenames = Vec::new();
-    for output_type in &sess.opts.output_types {
+    for output_type in sess.opts.output_types.keys() {
         let file = outputs.path(*output_type);
         match *output_type {
-            config::OutputTypeExe => {
+            OutputType::Exe => {
                 for output in sess.crate_types.borrow().iter() {
                     let p = link::filename_for_input(sess, *output, id,
                                                      outputs);
@@ -867,23 +864,11 @@ fn write_out_deps(sess: &Session,
         }
     }
 
-    // Write out dependency rules to the dep-info file if requested with
-    // --dep-info
-    let deps_filename = match sess.opts.write_dependency_info {
-        // Use filename from --dep-file argument if given
-        (true, Some(ref filename)) => filename.clone(),
-        // Use default filename: crate source filename with extension replaced
-        // by ".d"
-        (true, None) => match *input {
-            Input::File(..) => outputs.with_extension("d"),
-            Input::Str(..) => {
-                sess.warn("can not write --dep-info without a filename \
-                           when compiling stdin.");
-                return
-            },
-        },
-        _ => return,
-    };
+    // Write out dependency rules to the dep-info file if requested
+    if !sess.opts.output_types.contains_key(&OutputType::DepInfo) {
+        return
+    }
+    let deps_filename = outputs.path(OutputType::DepInfo);
 
     let result = (|| -> io::Result<()> {
         // Build a list of files used to compile the output and
@@ -1012,11 +997,15 @@ pub fn build_output_filenames(input: &Input,
                 out_filestem: stem,
                 single_output_file: None,
                 extra: sess.opts.cg.extra_filename.clone(),
+                outputs: sess.opts.output_types.clone(),
             }
         }
 
         Some(ref out_file) => {
-            let ofile = if sess.opts.output_types.len() > 1 {
+            let unnamed_output_types = sess.opts.output_types.values()
+                                           .filter(|a| a.is_none())
+                                           .count();
+            let ofile = if unnamed_output_types > 1 {
                 sess.warn("ignoring specified output filename because multiple \
                            outputs were requested");
                 None
@@ -1035,6 +1024,7 @@ pub fn build_output_filenames(input: &Input,
                                       .to_str().unwrap().to_string(),
                 single_output_file: ofile,
                 extra: sess.opts.cg.extra_filename.clone(),
+                outputs: sess.opts.output_types.clone(),
             }
         }
     }
index 7d9c74fe48702d74b1f6900f2b25ee0bec600111..d5644d49e1ea4afc4c3896e5ae94d3c7d2b85193 100644 (file)
@@ -63,7 +63,7 @@
 use rustc_trans::back::link;
 use rustc_trans::save;
 use rustc::session::{config, Session, build_session};
-use rustc::session::config::{Input, PrintRequest};
+use rustc::session::config::{Input, PrintRequest, OutputType};
 use rustc::lint::Lint;
 use rustc::lint;
 use rustc::metadata;
@@ -382,7 +382,7 @@ fn build_controller(&mut self, sess: &Session) -> CompileController<'a> {
             control.after_analysis.stop = Compilation::Stop;
         }
 
-        if !sess.opts.output_types.iter().any(|&i| i == config::OutputTypeExe) {
+        if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe) {
             control.after_llvm.stop = Compilation::Stop;
         }
 
index 4e493e6779c667ae2492d192b879c88450161820..1590d20b09e7cc80e80f66391cc8b0dde0e9cc20 100644 (file)
@@ -16,7 +16,7 @@
 use super::svh::Svh;
 use session::config;
 use session::config::NoDebugInfo;
-use session::config::{OutputFilenames, Input, OutputTypeBitcode, OutputTypeExe, OutputTypeObject};
+use session::config::{OutputFilenames, Input, OutputType};
 use session::search_paths::PathKind;
 use session::Session;
 use metadata::common::LinkMeta;
@@ -486,7 +486,7 @@ pub fn filename_for_input(sess: &Session,
         }
         config::CrateTypeExecutable => {
             let suffix = &sess.target.target.options.exe_suffix;
-            let out_filename = outputs.path(OutputTypeExe);
+            let out_filename = outputs.path(OutputType::Exe);
             if suffix.is_empty() {
                 out_filename.to_path_buf()
             } else {
@@ -527,10 +527,12 @@ fn link_binary_output(sess: &Session,
                       outputs: &OutputFilenames,
                       crate_name: &str) -> PathBuf {
     let objects = object_filenames(sess, outputs);
-    let out_filename = match outputs.single_output_file {
-        Some(ref file) => file.clone(),
-        None => filename_for_input(sess, crate_type, crate_name, 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
@@ -571,7 +573,7 @@ fn link_binary_output(sess: &Session,
 fn object_filenames(sess: &Session, outputs: &OutputFilenames) -> Vec<PathBuf> {
     (0..sess.opts.cg.codegen_units).map(|i| {
         let ext = format!("{}.o", i);
-        outputs.temp_path(OutputTypeObject).with_extension(&ext)
+        outputs.temp_path(OutputType::Object).with_extension(&ext)
     }).collect()
 }
 
@@ -718,7 +720,7 @@ fn link_rlib<'a>(sess: &'a Session,
                 // See the bottom of back::write::run_passes for an explanation
                 // of when we do and don't keep .0.bc files around.
                 let user_wants_numbered_bitcode =
-                        sess.opts.output_types.contains(&OutputTypeBitcode) &&
+                        sess.opts.output_types.contains_key(&OutputType::Bitcode) &&
                         sess.opts.cg.codegen_units > 1;
                 if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode {
                     remove(sess, &bc_filename);
index 94e2891f40fa070d262de6674e241281e015ce59..1fbbf82ba38e47560f64398f3e0ffc5c3eda433a 100644 (file)
@@ -12,7 +12,7 @@
 use back::link::{get_linker, remove};
 use session::config::{OutputFilenames, Passes, SomePasses, AllPasses};
 use session::Session;
-use session::config;
+use session::config::{self, OutputType};
 use llvm;
 use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
 use llvm::SMDiagnosticRef;
 use syntax::diagnostic;
 use syntax::diagnostic::{Emitter, Handler, Level};
 
+use std::collections::HashMap;
 use std::ffi::{CStr, CString};
 use std::fs;
-use std::path::Path;
+use std::path::{Path, PathBuf};
 use std::ptr;
 use std::str;
 use std::sync::{Arc, Mutex};
 use std::thread;
 use libc::{self, c_uint, c_int, c_void};
 
-#[derive(Clone, Copy, PartialEq, PartialOrd, Ord, Eq)]
-pub enum OutputType {
-    OutputTypeBitcode,
-    OutputTypeAssembly,
-    OutputTypeLlvmAssembly,
-    OutputTypeObject,
-    OutputTypeExe,
-}
-
 pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! {
     unsafe {
         let cstr = llvm::LLVMRustGetLastError();
@@ -571,7 +563,7 @@ unsafe fn with_codegen<F>(tm: TargetMachineRef,
 
 pub fn run_passes(sess: &Session,
                   trans: &CrateTranslation,
-                  output_types: &[config::OutputType],
+                  output_types: &HashMap<OutputType, Option<PathBuf>>,
                   crate_output: &OutputFilenames) {
     // It's possible that we have `codegen_units > 1` but only one item in
     // `trans.modules`.  We could theoretically proceed and do LTO in that
@@ -611,32 +603,32 @@ pub fn run_passes(sess: &Session,
     // archive in order to allow LTO against it.
     let needs_crate_bitcode =
             sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
-            sess.opts.output_types.contains(&config::OutputTypeExe);
+            sess.opts.output_types.contains_key(&OutputType::Exe);
     let needs_crate_object =
-            sess.opts.output_types.contains(&config::OutputTypeExe);
+            sess.opts.output_types.contains_key(&OutputType::Exe);
     if needs_crate_bitcode {
         modules_config.emit_bc = true;
     }
 
-    for output_type in output_types {
+    for output_type in output_types.keys() {
         match *output_type {
-            config::OutputTypeBitcode => { modules_config.emit_bc = true; },
-            config::OutputTypeLlvmAssembly => { modules_config.emit_ir = true; },
-            config::OutputTypeAssembly => {
+            OutputType::Bitcode => { modules_config.emit_bc = true; },
+            OutputType::LlvmAssembly => { modules_config.emit_ir = true; },
+            OutputType::Assembly => {
                 modules_config.emit_asm = true;
                 // If we're not using the LLVM assembler, this function
                 // could be invoked specially with output_type_assembly, so
                 // in this case we still want the metadata object file.
-                if !sess.opts.output_types.contains(&config::OutputTypeAssembly) {
+                if !sess.opts.output_types.contains_key(&OutputType::Assembly) {
                     metadata_config.emit_obj = true;
                 }
             },
-            config::OutputTypeObject => { modules_config.emit_obj = true; },
-            config::OutputTypeExe => {
+            OutputType::Object => { modules_config.emit_obj = true; },
+            OutputType::Exe => {
                 modules_config.emit_obj = true;
                 metadata_config.emit_obj = true;
             },
-            config::OutputTypeDepInfo => {}
+            OutputType::DepInfo => {}
         }
     }
 
@@ -686,8 +678,9 @@ pub fn run_passes(sess: &Session,
         }
     };
 
-    let copy_if_one_unit = |ext: &str, output_type: config::OutputType, keep_numbered: bool| {
-        // Three cases:
+    let copy_if_one_unit = |ext: &str,
+                            output_type: OutputType,
+                            keep_numbered: bool| {
         if sess.opts.cg.codegen_units == 1 {
             // 1) Only one codegen unit.  In this case it's no difficulty
             //    to copy `foo.0.x` to `foo.x`.
@@ -697,17 +690,20 @@ pub fn run_passes(sess: &Session,
                 // The user just wants `foo.x`, not `foo.0.x`.
                 remove(sess, &crate_output.with_extension(ext));
             }
+        } else if crate_output.outputs.contains_key(&output_type) {
+            // 2) Multiple codegen units, with `--emit foo=some_name`.  We have
+            //    no good solution for this case, so warn the user.
+            sess.warn(&format!("ignoring emit path because multiple .{} files \
+                                were produced", ext));
+        } else if crate_output.single_output_file.is_some() {
+            // 3) Multiple codegen units, with `-o some_name`.  We have
+            //    no good solution for this case, so warn the user.
+            sess.warn(&format!("ignoring -o because multiple .{} files \
+                                were produced", ext));
         } else {
-            if crate_output.single_output_file.is_some() {
-                // 2) Multiple codegen units, with `-o some_name`.  We have
-                //    no good solution for this case, so warn the user.
-                sess.warn(&format!("ignoring -o because multiple .{} files were produced",
-                                  ext));
-            } else {
-                // 3) Multiple codegen units, but no `-o some_name`.  We
-                //    just leave the `foo.0.x` files in place.
-                // (We don't have to do any work in this case.)
-            }
+            // 4) Multiple codegen units, but no explicit name.  We
+            //    just leave the `foo.0.x` files in place.
+            // (We don't have to do any work in this case.)
         }
     };
 
@@ -716,27 +712,27 @@ pub fn run_passes(sess: &Session,
     // to get rid of it.
     let mut user_wants_bitcode = false;
     let mut user_wants_objects = false;
-    for output_type in output_types {
+    for output_type in output_types.keys() {
         match *output_type {
-            config::OutputTypeBitcode => {
+            OutputType::Bitcode => {
                 user_wants_bitcode = true;
                 // Copy to .bc, but always keep the .0.bc.  There is a later
                 // check to figure out if we should delete .0.bc files, or keep
                 // them for making an rlib.
-                copy_if_one_unit("0.bc", config::OutputTypeBitcode, true);
+                copy_if_one_unit("0.bc", OutputType::Bitcode, true);
             }
-            config::OutputTypeLlvmAssembly => {
-                copy_if_one_unit("0.ll", config::OutputTypeLlvmAssembly, false);
+            OutputType::LlvmAssembly => {
+                copy_if_one_unit("0.ll", OutputType::LlvmAssembly, false);
             }
-            config::OutputTypeAssembly => {
-                copy_if_one_unit("0.s", config::OutputTypeAssembly, false);
+            OutputType::Assembly => {
+                copy_if_one_unit("0.s", OutputType::Assembly, false);
             }
-            config::OutputTypeObject => {
+            OutputType::Object => {
                 user_wants_objects = true;
-                copy_if_one_unit("0.o", config::OutputTypeObject, true);
+                copy_if_one_unit("0.o", OutputType::Object, true);
             }
-            config::OutputTypeExe |
-            config::OutputTypeDepInfo => {}
+            OutputType::Exe |
+            OutputType::DepInfo => {}
         }
     }
     let user_wants_bitcode = user_wants_bitcode;
@@ -913,8 +909,8 @@ fn run_work_multithreaded(sess: &Session,
 pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
     let (pname, mut cmd) = get_linker(sess);
 
-    cmd.arg("-c").arg("-o").arg(&outputs.path(config::OutputTypeObject))
-                           .arg(&outputs.temp_path(config::OutputTypeAssembly));
+    cmd.arg("-c").arg("-o").arg(&outputs.path(OutputType::Object))
+                           .arg(&outputs.temp_path(OutputType::Assembly));
     debug!("{:?}", cmd);
 
     match cmd.output() {
index 2f47353fee7b299dca31520fb1afffdbdde54ca3..15ec26e5afe10de21452b0f2cb6f1b9a3c7c66f1 100644 (file)
@@ -23,7 +23,7 @@
 use testing;
 use rustc_lint;
 use rustc::session::{self, config};
-use rustc::session::config::get_unstable_features_setting;
+use rustc::session::config::{get_unstable_features_setting, OutputType};
 use rustc::session::search_paths::{SearchPaths, PathKind};
 use rustc_front::lowering::lower_crate;
 use rustc_back::tempdir::TempDir;
@@ -163,13 +163,15 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
     // never wrap the test in `fn main() { ... }`
     let test = maketest(test, Some(cratename), as_test_harness, opts);
     let input = config::Input::Str(test.to_string());
+    let mut outputs = HashMap::new();
+    outputs.insert(OutputType::Exe, None);
 
     let sessopts = config::Options {
         maybe_sysroot: Some(env::current_exe().unwrap().parent().unwrap()
                                               .parent().unwrap().to_path_buf()),
         search_paths: libs,
         crate_types: vec!(config::CrateTypeExecutable),
-        output_types: vec!(config::OutputTypeExe),
+        output_types: outputs,
         externs: externs,
         cg: config::CodegenOptions {
             prefer_dynamic: true,
index 8745cbecf913704df7cfa2c17631bb243b79a8a3..bd8c735df31a9f9a324a74f74a13fc1db6acf75a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(rustc_private, path, convert)]
+#![feature(rustc_private)]
 
 extern crate rustc;
 extern crate rustc_driver;
@@ -16,7 +16,7 @@
 extern crate syntax;
 
 use rustc::session::{build_session, Session};
-use rustc::session::config::{basic_options, build_configuration, Input, OutputTypeExe};
+use rustc::session::config::{basic_options, build_configuration, Input, OutputType};
 use rustc_driver::driver::{compile_input, CompileController};
 use syntax::diagnostics::registry::Registry;
 
@@ -46,7 +46,7 @@ fn main() {}
 
 fn basic_sess(sysroot: PathBuf) -> Session {
     let mut opts = basic_options();
-    opts.output_types = vec![OutputTypeExe];
+    opts.output_types.insert(OutputType::Exe, None);
     opts.maybe_sysroot = Some(sysroot);
 
     let descriptions = Registry::new(&rustc::DIAGNOSTICS);
index a785e916cf73379ba73d5c3a5756f9addb5b8aa7..b4b2e827e947eb32e65754fe88f16a99496d024f 100644 (file)
@@ -23,45 +23,83 @@ all:
        rm -f $(TMPDIR)/bar.pdb
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --emit=asm -o $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit asm -o $(TMPDIR)/foo
+       rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit asm=$(TMPDIR)/foo
        rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --emit=llvm-bc -o $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit llvm-bc -o $(TMPDIR)/foo
+       rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit llvm-bc=$(TMPDIR)/foo
        rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --emit=llvm-ir -o $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit llvm-ir -o $(TMPDIR)/foo
+       rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit llvm-ir=$(TMPDIR)/foo
        rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --emit=obj -o $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit obj -o $(TMPDIR)/foo
+       rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --emit obj=$(TMPDIR)/foo
        rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
-       $(RUSTC) foo.rs --emit=link -o $(TMPDIR)/$(call BIN,foo)
+       $(RUSTC) foo.rs --emit link -o $(TMPDIR)/$(call BIN,foo)
+       rm $(TMPDIR)/$(call BIN,foo)
+       $(RUSTC) foo.rs --emit link=$(TMPDIR)/$(call BIN,foo)
        rm $(TMPDIR)/$(call BIN,foo)
        rm -f $(TMPDIR)/foo.pdb
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --crate-type=rlib -o $(TMPDIR)/foo
        rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --crate-type=rlib --emit link=$(TMPDIR)/foo
+       rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --crate-type=dylib -o $(TMPDIR)/$(call BIN,foo)
        rm $(TMPDIR)/$(call BIN,foo)
+       $(RUSTC) foo.rs --crate-type=dylib --emit link=$(TMPDIR)/$(call BIN,foo)
+       rm $(TMPDIR)/$(call BIN,foo)
        rm -f $(TMPDIR)/foo.{exp,lib,pdb}
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --crate-type=staticlib -o $(TMPDIR)/foo
        rm $(TMPDIR)/foo
+       $(RUSTC) foo.rs --crate-type=staticlib --emit link=$(TMPDIR)/foo
+       rm $(TMPDIR)/foo
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
        $(RUSTC) foo.rs --crate-type=bin -o $(TMPDIR)/$(call BIN,foo)
        rm $(TMPDIR)/$(call BIN,foo)
+       $(RUSTC) foo.rs --crate-type=bin --emit link=$(TMPDIR)/$(call BIN,foo)
+       rm $(TMPDIR)/$(call BIN,foo)
        rm -f $(TMPDIR)/foo.pdb
        [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
 
+       $(RUSTC) foo.rs --emit llvm-ir=$(TMPDIR)/ir \
+                       --emit link \
+                       --crate-type=rlib
+       rm $(TMPDIR)/ir
+       rm $(TMPDIR)/libbar.rlib
+       [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
+
+       $(RUSTC) foo.rs --emit asm=$(TMPDIR)/asm \
+                       --emit llvm-ir=$(TMPDIR)/ir \
+                       --emit llvm-bc=$(TMPDIR)/bc \
+                       --emit obj=$(TMPDIR)/obj \
+                       --emit link=$(TMPDIR)/link \
+                       --crate-type=staticlib
+       rm $(TMPDIR)/asm
+       rm $(TMPDIR)/ir
+       rm $(TMPDIR)/bc
+       rm $(TMPDIR)/obj
+       rm $(TMPDIR)/link
+       [ "$$(ls -1 $(TMPDIR) | wc -l)" -eq "0" ]
+
        $(RUSTC) foo.rs --emit=asm,llvm-ir,llvm-bc,obj,link --crate-type=staticlib
        rm $(TMPDIR)/bar.ll
        rm $(TMPDIR)/bar.s