Emit only necessary compilation options in save-analysis

This is `command`, `directory` and `output` file.
This commit is contained in:
Igor Matuszewski 2018-09-22 23:19:39 +02:00
parent cddd00a1e6
commit d45f87701c
4 changed files with 47 additions and 34 deletions

View File

@ -2373,6 +2373,7 @@ dependencies = [
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0", "rustc 0.0.0",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "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_data_structures 0.0.0",
"rustc_target 0.0.0", "rustc_target 0.0.0",
"rustc_typeck 0.0.0", "rustc_typeck 0.0.0",

View File

@ -12,6 +12,7 @@ crate-type = ["dylib"]
log = "0.4" log = "0.4"
rustc = { path = "../librustc" } rustc = { path = "../librustc" }
rustc_data_structures = { path = "../librustc_data_structures" } rustc_data_structures = { path = "../librustc_data_structures" }
rustc_codegen_utils = { path = "../librustc_codegen_utils" }
rustc_target = { path = "../librustc_target" } rustc_target = { path = "../librustc_target" }
rustc_typeck = { path = "../librustc_typeck" } rustc_typeck = { path = "../librustc_typeck" }
syntax = { path = "../libsyntax" } syntax = { path = "../libsyntax" }

View File

@ -28,8 +28,9 @@ use rustc::hir::def_id::DefId;
use rustc::ty::{self, TyCtxt}; use rustc::ty::{self, TyCtxt};
use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::fx::FxHashSet;
use std::path::{Path, PathBuf}; use std::path::Path;
use std::env; use std::env;
use std::fs;
use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID}; use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID};
use syntax::parse::token; 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); self.dumper.crate_prelude(data);
} }
pub fn dump_compilation_options(&mut self) { pub fn dump_compilation_options(&mut self, crate_name: &str) {
// Apply possible `remap-path-prefix` remapping to the raw invocation // Apply possible `remap-path-prefix` remapping to the raw command
let invocation = { 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 remap_arg_indices = {
let mut indices = FxHashSet(); let mut indices = FxHashSet();
// rustc args are guaranteed to be valid UTF-8 (checked early)
for (i, e) in env::args().enumerate() { for (i, e) in env::args().enumerate() {
if e.starts_with("--remap-path-prefix=") { if e.starts_with("--remap-path-prefix=") {
indices.insert(i); indices.insert(i);
@ -188,19 +198,10 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
indices indices
}; };
let args_without_remap_args = env::args() let args = env::args()
.enumerate() .enumerate()
.filter(|(i, _)| !remap_arg_indices.contains(i)) .filter(|(i, _)| !remap_arg_indices.contains(i))
.map(|(_, e)| e); .map(|(_, elem)| {
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| {
let mut arg = elem.splitn(2, '='); let mut arg = elem.splitn(2, '=');
match (arg.next(), arg.next()) { match (arg.next(), arg.next()) {
// Apart from `--remap...`, in `a=b` args usually only // 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(" ") args.as_slice().join(" ")
}; };
let opts = &self.tcx.sess.opts;
let data = CompilationOptions { let data = CompilationOptions {
invocation, directory: self.tcx.sess.working_dir.0.clone(),
crate_name: opts.crate_name.clone(), command,
test: opts.test, output: self.save_ctxt.compilation_output(crate_name),
sysroot: opts.maybe_sysroot.clone(),
target_triple: opts.target_triple.to_string(),
}; };
self.dumper.compilation_opts(data); self.dumper.compilation_opts(data);

View File

@ -23,6 +23,7 @@ extern crate rustc;
#[macro_use] #[macro_use]
extern crate log; extern crate log;
extern crate rustc_data_structures; extern crate rustc_data_structures;
extern crate rustc_codegen_utils;
extern crate rustc_serialize; extern crate rustc_serialize;
extern crate rustc_target; extern crate rustc_target;
extern crate rustc_typeck; extern crate rustc_typeck;
@ -45,9 +46,10 @@ use rustc::hir::def::Def as HirDef;
use rustc::hir::Node; use rustc::hir::Node;
use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::middle::cstore::ExternCrate; use rustc::middle::cstore::ExternCrate;
use rustc::session::config::CrateType; use rustc::session::config::{CrateType, OutputType};
use rustc::ty::{self, TyCtxt}; use rustc::ty::{self, TyCtxt};
use rustc_typeck::hir_ty_to_ty; use rustc_typeck::hir_ty_to_ty;
use rustc_codegen_utils::link::{filename_for_metadata, out_filename};
use std::cell::Cell; use std::cell::Cell;
use std::default::Default; 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. // List external crates used by the current crate.
pub fn get_external_crates(&self) -> Vec<ExternalCrateData> { pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
let mut result = Vec::with_capacity(self.tcx.crates().len()); 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(), disambiguator: self.tcx.crate_disambiguator(n).to_fingerprint().as_value(),
}, },
source: CrateSource { source: CrateSource {
dylib: src.dylib.as_ref().map(|(ref path, _)| dylib: src.dylib.as_ref().map(|(path, _)| map_prefix(path)),
map_prefix(path).display().to_string() rlib: src.rlib.as_ref().map(|(path, _)| map_prefix(path)),
), rmeta: src.rmeta.as_ref().map(|(path, _)| map_prefix(path)),
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()
),
} }
}); });
} }
@ -1103,7 +1117,7 @@ impl<'a> SaveHandler for DumpHandler<'a> {
let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper); let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
visitor.dump_crate_info(cratename, krate); visitor.dump_crate_info(cratename, krate);
visitor.dump_compilation_options(); visitor.dump_compilation_options(cratename);
visit::walk_crate(&mut visitor, krate); 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); let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
visitor.dump_crate_info(cratename, krate); visitor.dump_crate_info(cratename, krate);
visitor.dump_compilation_options(); visitor.dump_compilation_options(cratename);
visit::walk_crate(&mut visitor, krate); visit::walk_crate(&mut visitor, krate);
} }
} }