diff --git a/src/Cargo.lock b/src/Cargo.lock index 9a383a381d5..5a44b696a03 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2373,6 +2373,7 @@ dependencies = [ "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_codegen_utils 0.0.0", "rustc_data_structures 0.0.0", "rustc_target 0.0.0", "rustc_typeck 0.0.0", diff --git a/src/librustc_save_analysis/Cargo.toml b/src/librustc_save_analysis/Cargo.toml index b6dd9ec8d3f..e47f89c64ff 100644 --- a/src/librustc_save_analysis/Cargo.toml +++ b/src/librustc_save_analysis/Cargo.toml @@ -12,6 +12,7 @@ crate-type = ["dylib"] log = "0.4" rustc = { path = "../librustc" } rustc_data_structures = { path = "../librustc_data_structures" } +rustc_codegen_utils = { path = "../librustc_codegen_utils" } rustc_target = { path = "../librustc_target" } rustc_typeck = { path = "../librustc_typeck" } syntax = { path = "../libsyntax" } diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index b044210c092..c87f52f8bd1 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -28,8 +28,9 @@ use rustc::hir::def_id::DefId; use rustc::ty::{self, TyCtxt}; use rustc_data_structures::fx::FxHashSet; -use std::path::{Path, PathBuf}; +use std::path::Path; use std::env; +use std::fs; use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID}; use syntax::parse::token; @@ -172,11 +173,20 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { self.dumper.crate_prelude(data); } - pub fn dump_compilation_options(&mut self) { - // Apply possible `remap-path-prefix` remapping to the raw invocation - let invocation = { + pub fn dump_compilation_options(&mut self, crate_name: &str) { + // Apply possible `remap-path-prefix` remapping to the raw command + let command = { + let mapping = self.tcx.sess.source_map().path_mapping(); + let remap_arg = |x: &str| -> String { + match fs::canonicalize(x) { + Ok(path) => mapping.map_prefix(path).0.to_str().unwrap().to_owned(), + Err(_) => x.to_owned(), // Probably not a path, ignore + } + }; + let remap_arg_indices = { let mut indices = FxHashSet(); + // rustc args are guaranteed to be valid UTF-8 (checked early) for (i, e) in env::args().enumerate() { if e.starts_with("--remap-path-prefix=") { indices.insert(i); @@ -188,19 +198,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { indices }; - let args_without_remap_args = env::args() + let args = env::args() .enumerate() .filter(|(i, _)| !remap_arg_indices.contains(i)) - .map(|(_, e)| e); - - let mapping = self.tcx.sess.source_map().path_mapping(); - let remap_arg = |x: &str| -> String { - mapping.map_prefix(PathBuf::from(x)).0.to_str().unwrap().to_owned() - }; - - // Naively attempt to remap every argument - let args = args_without_remap_args - .map(|elem| { + .map(|(_, elem)| { let mut arg = elem.splitn(2, '='); match (arg.next(), arg.next()) { // Apart from `--remap...`, in `a=b` args usually only @@ -214,14 +215,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> { args.as_slice().join(" ") }; - let opts = &self.tcx.sess.opts; - let data = CompilationOptions { - invocation, - crate_name: opts.crate_name.clone(), - test: opts.test, - sysroot: opts.maybe_sysroot.clone(), - target_triple: opts.target_triple.to_string(), + directory: self.tcx.sess.working_dir.0.clone(), + command, + output: self.save_ctxt.compilation_output(crate_name), }; self.dumper.compilation_opts(data); diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs index 06496db5274..702edb70757 100644 --- a/src/librustc_save_analysis/lib.rs +++ b/src/librustc_save_analysis/lib.rs @@ -23,6 +23,7 @@ extern crate rustc; #[macro_use] extern crate log; extern crate rustc_data_structures; +extern crate rustc_codegen_utils; extern crate rustc_serialize; extern crate rustc_target; extern crate rustc_typeck; @@ -45,9 +46,10 @@ use rustc::hir::def::Def as HirDef; use rustc::hir::Node; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::cstore::ExternCrate; -use rustc::session::config::CrateType; +use rustc::session::config::{CrateType, OutputType}; use rustc::ty::{self, TyCtxt}; use rustc_typeck::hir_ty_to_ty; +use rustc_codegen_utils::link::{filename_for_metadata, out_filename}; use std::cell::Cell; use std::default::Default; @@ -111,6 +113,24 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { } } + // Returns path to the compilation output (e.g. libfoo-12345678.rmeta) + pub fn compilation_output(&self, crate_name: &str) -> PathBuf { + let sess = &self.tcx.sess; + // Save-analysis is emitted per whole session, not per each crate type + let crate_type = sess.crate_types.borrow()[0]; + let outputs = &*self.tcx.output_filenames(LOCAL_CRATE); + + if outputs.outputs.contains_key(&OutputType::Metadata) { + filename_for_metadata(sess, crate_name, outputs) + } else if outputs.outputs.should_codegen() { + out_filename(sess, crate_type, outputs, crate_name) + } else { + // Otherwise it's only a DepInfo, in which case we return early and + // not even reach the analysis stage. + unreachable!() + } + } + // List external crates used by the current crate. pub fn get_external_crates(&self) -> Vec { let mut result = Vec::with_capacity(self.tcx.crates().len()); @@ -139,15 +159,9 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> { disambiguator: self.tcx.crate_disambiguator(n).to_fingerprint().as_value(), }, source: CrateSource { - dylib: src.dylib.as_ref().map(|(ref path, _)| - map_prefix(path).display().to_string() - ), - rlib: src.rlib.as_ref().map(|(ref path, _)| - map_prefix(path).display().to_string() - ), - rmeta: src.rmeta.as_ref().map(|(ref path, _)| - map_prefix(path).display().to_string() - ), + dylib: src.dylib.as_ref().map(|(path, _)| map_prefix(path)), + rlib: src.rlib.as_ref().map(|(path, _)| map_prefix(path)), + rmeta: src.rmeta.as_ref().map(|(path, _)| map_prefix(path)), } }); } @@ -1103,7 +1117,7 @@ impl<'a> SaveHandler for DumpHandler<'a> { let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); visitor.dump_crate_info(cratename, krate); - visitor.dump_compilation_options(); + visitor.dump_compilation_options(cratename); visit::walk_crate(&mut visitor, krate); } } @@ -1129,7 +1143,7 @@ impl<'b> SaveHandler for CallbackHandler<'b> { let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); visitor.dump_crate_info(cratename, krate); - visitor.dump_compilation_options(); + visitor.dump_compilation_options(cratename); visit::walk_crate(&mut visitor, krate); } }