Skip to content

Commit c3c1c8d

Browse files
committed
Allow linking to a proc macro on the target in metadata and still use a host proc macro to execute them
1 parent 97431a4 commit c3c1c8d

File tree

4 files changed

+122
-56
lines changed

4 files changed

+122
-56
lines changed

src/librustc/session/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
12321232
Use with RUST_REGION_GRAPH=help for more info"),
12331233
parse_only: bool = (false, parse_bool, [UNTRACKED],
12341234
"parse only; do not compile, assemble, or link"),
1235+
dual_proc_macros: bool = (false, parse_bool, [TRACKED],
1236+
"load proc macros for both target and host, but only link to the target"),
12351237
no_codegen: bool = (false, parse_bool, [TRACKED],
12361238
"run all passes except codegen; no output"),
12371239
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],

src/librustc/session/filesearch.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub enum FileMatch {
1818

1919
// A module for searching for libraries
2020

21+
#[derive(Clone)]
2122
pub struct FileSearch<'a> {
2223
sysroot: &'a Path,
2324
triple: &'a str,

src/librustc_metadata/creader.rs

Lines changed: 106 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -188,13 +188,15 @@ impl<'a> CrateLoader<'a> {
188188
});
189189
}
190190

191-
fn register_crate(&mut self,
192-
root: &Option<CratePaths>,
193-
ident: Symbol,
194-
span: Span,
195-
lib: Library,
196-
dep_kind: DepKind)
197-
-> (CrateNum, Lrc<cstore::CrateMetadata>) {
191+
fn register_crate(
192+
&mut self,
193+
host_lib: Option<Library>,
194+
root: &Option<CratePaths>,
195+
ident: Symbol,
196+
span: Span,
197+
lib: Library,
198+
dep_kind: DepKind
199+
) -> (CrateNum, Lrc<cstore::CrateMetadata>) {
198200
let crate_root = lib.metadata.get_root();
199201
info!("register crate `extern crate {} as {}`", crate_root.name, ident);
200202
self.verify_no_symbol_conflicts(span, &crate_root);
@@ -222,7 +224,16 @@ impl<'a> CrateLoader<'a> {
222224
let dependencies: Vec<CrateNum> = cnum_map.iter().cloned().collect();
223225

224226
let proc_macros = crate_root.proc_macro_decls_static.map(|_| {
225-
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
227+
if self.sess.opts.debugging_opts.dual_proc_macros {
228+
let host_lib = host_lib.unwrap();
229+
self.load_derive_macros(
230+
&host_lib.metadata.get_root(),
231+
host_lib.dylib.clone().map(|p| p.0),
232+
span
233+
)
234+
} else {
235+
self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span)
236+
}
226237
});
227238

228239
let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
@@ -269,6 +280,61 @@ impl<'a> CrateLoader<'a> {
269280
(cnum, cmeta)
270281
}
271282

283+
fn load_proc_macro<'b> (
284+
&mut self,
285+
locate_ctxt: &mut locator::Context<'b>,
286+
path_kind: PathKind,
287+
) -> Option<(LoadResult, Option<Library>)>
288+
where
289+
'a: 'b
290+
{
291+
// Use a new locator Context so trying to load a proc macro doesn't affect the error
292+
// message we emit
293+
let mut proc_macro_locator = locate_ctxt.clone();
294+
295+
// Try to load a proc macro
296+
proc_macro_locator.is_proc_macro = Some(true);
297+
298+
// Load the proc macro crate for the target
299+
let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros {
300+
proc_macro_locator.reset();
301+
let result = match self.load(&mut proc_macro_locator)? {
302+
LoadResult::Previous(cnum) => return Some((LoadResult::Previous(cnum), None)),
303+
LoadResult::Loaded(library) => Some(LoadResult::Loaded(library))
304+
};
305+
// Don't look for a matching hash when looking for the host crate.
306+
// It won't be the same as the target crate hash
307+
locate_ctxt.hash = None;
308+
// Use the locate_ctxt when looking for the host proc macro crate, as that is required
309+
// so we want it to affect the error message
310+
(locate_ctxt, result)
311+
} else {
312+
(&mut proc_macro_locator, None)
313+
};
314+
315+
// Load the proc macro crate for the host
316+
317+
locator.reset();
318+
locator.is_proc_macro = Some(true);
319+
locator.target = &self.sess.host;
320+
locator.triple = TargetTriple::from_triple(config::host_triple());
321+
locator.filesearch = self.sess.host_filesearch(path_kind);
322+
323+
let host_result = self.load(locator)?;
324+
325+
Some(if self.sess.opts.debugging_opts.dual_proc_macros {
326+
let host_result = match host_result {
327+
LoadResult::Previous(..) => {
328+
panic!("host and target proc macros must be loaded in lock-step")
329+
}
330+
LoadResult::Loaded(library) => library
331+
};
332+
(target_result.unwrap(), Some(host_result))
333+
} else {
334+
(host_result, None)
335+
})
336+
}
337+
272338
fn resolve_crate<'b>(
273339
&'b mut self,
274340
root: &'b Option<CratePaths>,
@@ -281,53 +347,39 @@ impl<'a> CrateLoader<'a> {
281347
mut dep_kind: DepKind,
282348
) -> Result<(CrateNum, Lrc<cstore::CrateMetadata>), LoadError<'b>> {
283349
info!("resolving crate `extern crate {} as {}`", name, ident);
350+
let mut locate_ctxt = locator::Context {
351+
sess: self.sess,
352+
span,
353+
ident,
354+
crate_name: name,
355+
hash: hash.map(|a| &*a),
356+
extra_filename: extra_filename,
357+
filesearch: self.sess.target_filesearch(path_kind),
358+
target: &self.sess.target.target,
359+
triple: self.sess.opts.target_triple.clone(),
360+
root,
361+
rejected_via_hash: vec![],
362+
rejected_via_triple: vec![],
363+
rejected_via_kind: vec![],
364+
rejected_via_version: vec![],
365+
rejected_via_filename: vec![],
366+
should_match_name: true,
367+
is_proc_macro: Some(false),
368+
metadata_loader: &*self.cstore.metadata_loader,
369+
};
370+
284371
let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) {
285-
LoadResult::Previous(cnum)
372+
(LoadResult::Previous(cnum), None)
286373
} else {
287374
info!("falling back to a load");
288-
let mut locate_ctxt = locator::Context {
289-
sess: self.sess,
290-
span,
291-
ident,
292-
crate_name: name,
293-
hash: hash.map(|a| &*a),
294-
extra_filename: extra_filename,
295-
filesearch: self.sess.target_filesearch(path_kind),
296-
target: &self.sess.target.target,
297-
triple: &self.sess.opts.target_triple,
298-
root,
299-
rejected_via_hash: vec![],
300-
rejected_via_triple: vec![],
301-
rejected_via_kind: vec![],
302-
rejected_via_version: vec![],
303-
rejected_via_filename: vec![],
304-
should_match_name: true,
305-
is_proc_macro: Some(false),
306-
metadata_loader: &*self.cstore.metadata_loader,
307-
};
308-
309-
self.load(&mut locate_ctxt).or_else(|| {
375+
self.load(&mut locate_ctxt).map(|r| (r, None)).or_else(|| {
310376
dep_kind = DepKind::UnexportedMacrosOnly;
311-
312-
let mut proc_macro_locator = locator::Context {
313-
target: &self.sess.host,
314-
triple: &TargetTriple::from_triple(config::host_triple()),
315-
filesearch: self.sess.host_filesearch(path_kind),
316-
rejected_via_hash: vec![],
317-
rejected_via_triple: vec![],
318-
rejected_via_kind: vec![],
319-
rejected_via_version: vec![],
320-
rejected_via_filename: vec![],
321-
is_proc_macro: Some(true),
322-
..locate_ctxt
323-
};
324-
325-
self.load(&mut proc_macro_locator)
377+
self.load_proc_macro(&mut locate_ctxt, path_kind)
326378
}).ok_or_else(move || LoadError::LocatorError(locate_ctxt))?
327379
};
328380

329381
match result {
330-
LoadResult::Previous(cnum) => {
382+
(LoadResult::Previous(cnum), None) => {
331383
let data = self.cstore.get_crate_data(cnum);
332384
if data.root.proc_macro_decls_static.is_some() {
333385
dep_kind = DepKind::UnexportedMacrosOnly;
@@ -337,9 +389,10 @@ impl<'a> CrateLoader<'a> {
337389
});
338390
Ok((cnum, data))
339391
}
340-
LoadResult::Loaded(library) => {
341-
Ok(self.register_crate(root, ident, span, library, dep_kind))
392+
(LoadResult::Loaded(library), host_library) => {
393+
Ok(self.register_crate(host_library, root, ident, span, library, dep_kind))
342394
}
395+
_ => panic!()
343396
}
344397
}
345398

@@ -355,7 +408,7 @@ impl<'a> CrateLoader<'a> {
355408
// don't want to match a host crate against an equivalent target one
356409
// already loaded.
357410
let root = library.metadata.get_root();
358-
if locate_ctxt.triple == &self.sess.opts.target_triple {
411+
if locate_ctxt.triple == self.sess.opts.target_triple {
359412
let mut result = LoadResult::Loaded(library);
360413
self.cstore.iter_crate_data(|cnum, data| {
361414
if data.root.name == root.name && root.hash == data.root.hash {
@@ -451,9 +504,9 @@ impl<'a> CrateLoader<'a> {
451504
fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol)
452505
-> ExtensionCrate {
453506
info!("read extension crate `extern crate {} as {}`", orig_name, rename);
454-
let target_triple = &self.sess.opts.target_triple;
507+
let target_triple = self.sess.opts.target_triple.clone();
455508
let host_triple = TargetTriple::from_triple(config::host_triple());
456-
let is_cross = target_triple != &host_triple;
509+
let is_cross = target_triple != host_triple;
457510
let mut target_only = false;
458511
let mut locate_ctxt = locator::Context {
459512
sess: self.sess,
@@ -464,7 +517,7 @@ impl<'a> CrateLoader<'a> {
464517
extra_filename: None,
465518
filesearch: self.sess.host_filesearch(PathKind::Crate),
466519
target: &self.sess.host,
467-
triple: &host_triple,
520+
triple: host_triple,
468521
root: &None,
469522
rejected_via_hash: vec![],
470523
rejected_via_triple: vec![],

src/librustc_metadata/locator.rs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,11 +244,13 @@ use rustc_data_structures::owning_ref::OwningRef;
244244

245245
use log::{debug, info, warn};
246246

247+
#[derive(Clone)]
247248
pub struct CrateMismatch {
248249
path: PathBuf,
249250
got: String,
250251
}
251252

253+
#[derive(Clone)]
252254
pub struct Context<'a> {
253255
pub sess: &'a Session,
254256
pub span: Span,
@@ -258,7 +260,7 @@ pub struct Context<'a> {
258260
pub extra_filename: Option<&'a str>,
259261
// points to either self.sess.target.target or self.sess.host, must match triple
260262
pub target: &'a Target,
261-
pub triple: &'a TargetTriple,
263+
pub triple: TargetTriple,
262264
pub filesearch: FileSearch<'a>,
263265
pub root: &'a Option<CratePaths>,
264266
pub rejected_via_hash: Vec<CrateMismatch>,
@@ -302,6 +304,14 @@ impl CratePaths {
302304
}
303305

304306
impl<'a> Context<'a> {
307+
pub fn reset(&mut self) {
308+
self.rejected_via_hash.clear();
309+
self.rejected_via_triple.clear();
310+
self.rejected_via_kind.clear();
311+
self.rejected_via_version.clear();
312+
self.rejected_via_filename.clear();
313+
}
314+
305315
pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
306316
let mut seen_paths = FxHashSet::default();
307317
match self.extra_filename {
@@ -399,7 +409,7 @@ impl<'a> Context<'a> {
399409
add);
400410

401411
if (self.ident == "std" || self.ident == "core")
402-
&& self.triple != &TargetTriple::from_triple(config::host_triple()) {
412+
&& self.triple != TargetTriple::from_triple(config::host_triple()) {
403413
err.note(&format!("the `{}` target may not be installed", self.triple));
404414
}
405415
err.span_label(self.span, "can't find crate");
@@ -718,7 +728,7 @@ impl<'a> Context<'a> {
718728
}
719729
}
720730

721-
if &root.triple != self.triple {
731+
if root.triple != self.triple {
722732
info!("Rejecting via crate triple: expected {} got {}",
723733
self.triple,
724734
root.triple);

0 commit comments

Comments
 (0)