Skip to content

Commit 80e6e3e

Browse files
committed
Auto merge of #54356 - Xanewok:save-analysis-invocation, r=nrc
Emit used rustc invocation in the save-analysis file Blocked on rust-dev-tools/rls-data#19. (I'm guessing it won't pass CI due to an out-of-tree git dependency) This should allow RLS to recreate a Rust compilation build plan from the save-analysis files alone, which should be useful when fetching those from external build systems, most notably Buck now. Also this includes some more potentially useful compilation-specific options (e.g. sysroot or the actual path to extern crates) but that's not required for the build plan bits. cc @jsgf @alexcrichton r? @nrc
2 parents d623ec6 + 58a8621 commit 80e6e3e

File tree

9 files changed

+123
-25
lines changed

9 files changed

+123
-25
lines changed

Diff for: src/Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -2373,6 +2373,7 @@ dependencies = [
23732373
"rls-span 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
23742374
"rustc 0.0.0",
23752375
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
2376+
"rustc_codegen_utils 0.0.0",
23762377
"rustc_data_structures 0.0.0",
23772378
"rustc_target 0.0.0",
23782379
"rustc_typeck 0.0.0",

Diff for: src/librustc_codegen_llvm/back/link.rs

+2-10
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,8 @@ use std::str;
4747
use syntax::attr;
4848

4949
pub use rustc_codegen_utils::link::{find_crate_name, filename_for_input, default_output_for_target,
50-
invalid_output_for_target, out_filename, check_file_is_writeable};
50+
invalid_output_for_target, out_filename, check_file_is_writeable,
51+
filename_for_metadata};
5152

5253
// The third parameter is for env vars, used on windows to set up the
5354
// path for MSVC to find its DLLs, and gcc to find its bundled
@@ -218,15 +219,6 @@ fn preserve_objects_for_their_debuginfo(sess: &Session) -> bool {
218219
false
219220
}
220221

221-
fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilenames) -> PathBuf {
222-
let out_filename = outputs.single_output_file.clone()
223-
.unwrap_or(outputs
224-
.out_directory
225-
.join(&format!("lib{}{}.rmeta", crate_name, sess.opts.cg.extra_filename)));
226-
check_file_is_writeable(&out_filename, sess);
227-
out_filename
228-
}
229-
230222
pub(crate) fn each_linked_rlib(sess: &Session,
231223
info: &CrateInfo,
232224
f: &mut dyn FnMut(CrateNum, &Path)) -> Result<(), String> {

Diff for: src/librustc_codegen_utils/link.rs

+13
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ pub fn find_crate_name(sess: Option<&Session>,
9797
"rust_out".to_string()
9898
}
9999

100+
pub fn filename_for_metadata(sess: &Session,
101+
crate_name: &str,
102+
outputs: &OutputFilenames) -> PathBuf {
103+
let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
104+
105+
let out_filename = outputs.single_output_file.clone()
106+
.unwrap_or(outputs.out_directory.join(&format!("lib{}.rmeta", libname)));
107+
108+
check_file_is_writeable(&out_filename, sess);
109+
110+
out_filename
111+
}
112+
100113
pub fn filename_for_input(sess: &Session,
101114
crate_type: config::CrateType,
102115
crate_name: &str,

Diff for: src/librustc_driver/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,7 @@ pub fn enable_save_analysis(control: &mut CompileController) {
980980
state.expanded_crate.unwrap(),
981981
state.analysis.unwrap(),
982982
state.crate_name.unwrap(),
983+
state.input,
983984
None,
984985
DumpHandler::new(state.out_dir,
985986
state.crate_name.unwrap()))

Diff for: src/librustc_save_analysis/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ crate-type = ["dylib"]
1212
log = "0.4"
1313
rustc = { path = "../librustc" }
1414
rustc_data_structures = { path = "../librustc_data_structures" }
15+
rustc_codegen_utils = { path = "../librustc_codegen_utils" }
1516
rustc_target = { path = "../librustc_target" }
1617
rustc_typeck = { path = "../librustc_typeck" }
1718
syntax = { path = "../libsyntax" }

Diff for: src/librustc_save_analysis/dump_visitor.rs

+52-2
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,12 @@
2525
2626
use rustc::hir::def::Def as HirDef;
2727
use rustc::hir::def_id::DefId;
28+
use rustc::session::config::Input;
2829
use rustc::ty::{self, TyCtxt};
2930
use rustc_data_structures::fx::FxHashSet;
3031

3132
use std::path::Path;
33+
use std::env;
3234

3335
use syntax::ast::{self, Attribute, NodeId, PatKind, CRATE_NODE_ID};
3436
use syntax::parse::token;
@@ -49,8 +51,8 @@ use json_dumper::{Access, DumpOutput, JsonDumper};
4951
use span_utils::SpanUtils;
5052
use sig;
5153

52-
use rls_data::{CratePreludeData, Def, DefKind, GlobalCrateId, Import, ImportKind, Ref, RefKind,
53-
Relation, RelationKind, SpanData};
54+
use rls_data::{CompilationOptions, CratePreludeData, Def, DefKind, GlobalCrateId, Import,
55+
ImportKind, Ref, RefKind, Relation, RelationKind, SpanData};
5456

5557
macro_rules! down_cast_data {
5658
($id:ident, $kind:ident, $sp:expr) => {
@@ -169,6 +171,54 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
169171
self.dumper.crate_prelude(data);
170172
}
171173

174+
pub fn dump_compilation_options(&mut self, input: &Input, crate_name: &str) {
175+
// Apply possible `remap-path-prefix` remapping to the input source file
176+
// (and don't include remapping args anymore)
177+
let (program, arguments) = {
178+
let remap_arg_indices = {
179+
let mut indices = FxHashSet();
180+
// Args are guaranteed to be valid UTF-8 (checked early)
181+
for (i, e) in env::args().enumerate() {
182+
if e.starts_with("--remap-path-prefix=") {
183+
indices.insert(i);
184+
} else if e == "--remap-path-prefix" {
185+
indices.insert(i);
186+
indices.insert(i + 1);
187+
}
188+
}
189+
indices
190+
};
191+
192+
let mut args = env::args()
193+
.enumerate()
194+
.filter(|(i, _)| !remap_arg_indices.contains(i))
195+
.map(|(_, arg)| {
196+
match input {
197+
Input::File(ref path) if path == Path::new(&arg) => {
198+
let mapped = &self.tcx.sess.local_crate_source_file;
199+
mapped
200+
.as_ref()
201+
.unwrap()
202+
.to_string_lossy()
203+
.into()
204+
},
205+
_ => arg,
206+
}
207+
});
208+
209+
(args.next().unwrap(), args.collect())
210+
};
211+
212+
let data = CompilationOptions {
213+
directory: self.tcx.sess.working_dir.0.clone(),
214+
program,
215+
arguments,
216+
output: self.save_ctxt.compilation_output(crate_name),
217+
};
218+
219+
self.dumper.compilation_opts(data);
220+
}
221+
172222
// Return all non-empty prefixes of a path.
173223
// For each prefix, we return the span for the last segment in the prefix and
174224
// a str representation of the entire prefix.

Diff for: src/librustc_save_analysis/json_dumper.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ use std::io::Write;
1212

1313
use rustc_serialize::json::as_json;
1414

15-
use rls_data::{self, Analysis, CratePreludeData, Def, DefKind, Import, MacroRef, Ref, RefKind,
16-
Relation, Impl};
1715
use rls_data::config::Config;
16+
use rls_data::{self, Analysis, CompilationOptions, CratePreludeData, Def, DefKind, Impl, Import,
17+
MacroRef, Ref, RefKind, Relation};
1818
use rls_span::{Column, Row};
1919

2020
#[derive(Debug)]
@@ -89,6 +89,10 @@ impl<'b, O: DumpOutput + 'b> JsonDumper<O> {
8989
self.result.prelude = Some(data)
9090
}
9191

92+
pub fn compilation_opts(&mut self, data: CompilationOptions) {
93+
self.result.compilation = Some(data);
94+
}
95+
9296
pub fn macro_use(&mut self, data: MacroRef) {
9397
if self.config.pub_only || self.config.reachable_only {
9498
return;

Diff for: src/librustc_save_analysis/lib.rs

+29-3
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ extern crate rustc;
2323
#[macro_use]
2424
extern crate log;
2525
extern crate rustc_data_structures;
26+
extern crate rustc_codegen_utils;
2627
extern crate rustc_serialize;
2728
extern crate rustc_target;
2829
extern crate rustc_typeck;
@@ -45,9 +46,10 @@ use rustc::hir::def::Def as HirDef;
4546
use rustc::hir::Node;
4647
use rustc::hir::def_id::{DefId, LOCAL_CRATE};
4748
use rustc::middle::cstore::ExternCrate;
48-
use rustc::session::config::CrateType;
49+
use rustc::session::config::{CrateType, Input, OutputType};
4950
use rustc::ty::{self, TyCtxt};
5051
use rustc_typeck::hir_ty_to_ty;
52+
use rustc_codegen_utils::link::{filename_for_metadata, out_filename};
5153

5254
use std::cell::Cell;
5355
use std::default::Default;
@@ -110,6 +112,24 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
110112
}
111113
}
112114

115+
// Returns path to the compilation output (e.g. libfoo-12345678.rmeta)
116+
pub fn compilation_output(&self, crate_name: &str) -> PathBuf {
117+
let sess = &self.tcx.sess;
118+
// Save-analysis is emitted per whole session, not per each crate type
119+
let crate_type = sess.crate_types.borrow()[0];
120+
let outputs = &*self.tcx.output_filenames(LOCAL_CRATE);
121+
122+
if outputs.outputs.contains_key(&OutputType::Metadata) {
123+
filename_for_metadata(sess, crate_name, outputs)
124+
} else if outputs.outputs.should_codegen() {
125+
out_filename(sess, crate_type, outputs, crate_name)
126+
} else {
127+
// Otherwise it's only a DepInfo, in which case we return early and
128+
// not even reach the analysis stage.
129+
unreachable!()
130+
}
131+
}
132+
113133
// List external crates used by the current crate.
114134
pub fn get_external_crates(&self) -> Vec<ExternalCrateData> {
115135
let mut result = Vec::with_capacity(self.tcx.crates().len());
@@ -126,7 +146,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
126146
result.push(ExternalCrateData {
127147
// FIXME: change file_name field to PathBuf in rls-data
128148
// https://github.com/nrc/rls-data/issues/7
129-
file_name: self.span_utils.make_path_string(&lo_loc.file.name),
149+
file_name: self.span_utils.make_filename_string(&lo_loc.file),
130150
num: n.as_u32(),
131151
id: GlobalCrateId {
132152
name: self.tcx.crate_name(n).to_string(),
@@ -1015,6 +1035,7 @@ pub trait SaveHandler {
10151035
save_ctxt: SaveContext<'l, 'tcx>,
10161036
krate: &ast::Crate,
10171037
cratename: &str,
1038+
input: &'l Input,
10181039
);
10191040
}
10201041

@@ -1080,12 +1101,14 @@ impl<'a> SaveHandler for DumpHandler<'a> {
10801101
save_ctxt: SaveContext<'l, 'tcx>,
10811102
krate: &ast::Crate,
10821103
cratename: &str,
1104+
input: &'l Input,
10831105
) {
10841106
let output = &mut self.output_file(&save_ctxt);
10851107
let mut dumper = JsonDumper::new(output, save_ctxt.config.clone());
10861108
let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
10871109

10881110
visitor.dump_crate_info(cratename, krate);
1111+
visitor.dump_compilation_options(input, cratename);
10891112
visit::walk_crate(&mut visitor, krate);
10901113
}
10911114
}
@@ -1101,6 +1124,7 @@ impl<'b> SaveHandler for CallbackHandler<'b> {
11011124
save_ctxt: SaveContext<'l, 'tcx>,
11021125
krate: &ast::Crate,
11031126
cratename: &str,
1127+
input: &'l Input,
11041128
) {
11051129
// We're using the JsonDumper here because it has the format of the
11061130
// save-analysis results that we will pass to the callback. IOW, we are
@@ -1111,6 +1135,7 @@ impl<'b> SaveHandler for CallbackHandler<'b> {
11111135
let mut visitor = DumpVisitor::new(save_ctxt, &mut dumper);
11121136

11131137
visitor.dump_crate_info(cratename, krate);
1138+
visitor.dump_compilation_options(input, cratename);
11141139
visit::walk_crate(&mut visitor, krate);
11151140
}
11161141
}
@@ -1120,6 +1145,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(
11201145
krate: &ast::Crate,
11211146
analysis: &'l ty::CrateAnalysis,
11221147
cratename: &str,
1148+
input: &'l Input,
11231149
config: Option<Config>,
11241150
mut handler: H,
11251151
) {
@@ -1137,7 +1163,7 @@ pub fn process_crate<'l, 'tcx, H: SaveHandler>(
11371163
impl_counter: Cell::new(0),
11381164
};
11391165

1140-
handler.save(save_ctxt, krate, cratename)
1166+
handler.save(save_ctxt, krate, cratename, input)
11411167
})
11421168
}
11431169

Diff for: src/librustc_save_analysis/span_utils.rs

+18-8
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,24 @@ impl<'a> SpanUtils<'a> {
3535
}
3636
}
3737

38-
pub fn make_path_string(&self, path: &FileName) -> String {
39-
match *path {
40-
FileName::Real(ref path) if !path.is_absolute() =>
41-
self.sess.working_dir.0
42-
.join(&path)
43-
.display()
44-
.to_string(),
45-
_ => path.to_string(),
38+
pub fn make_filename_string(&self, file: &SourceFile) -> String {
39+
match &file.name {
40+
FileName::Real(path) if !file.name_was_remapped => {
41+
if path.is_absolute() {
42+
self.sess.source_map().path_mapping()
43+
.map_prefix(path.clone()).0
44+
.display()
45+
.to_string()
46+
} else {
47+
self.sess.working_dir.0
48+
.join(&path)
49+
.display()
50+
.to_string()
51+
}
52+
},
53+
// If the file name is already remapped, we assume the user
54+
// configured it the way they wanted to, so use that directly
55+
filename => filename.to_string()
4656
}
4757
}
4858

0 commit comments

Comments
 (0)