]> git.proxmox.com Git - rustc.git/blob - src/librustc_metadata/creader.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / librustc_metadata / creader.rs
1 // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! Validates all used crates and extern libraries and loads their metadata
12
13 use cstore::{self, CStore, CrateSource, MetadataBlob};
14 use locator::{self, CratePaths};
15 use schema::CrateRoot;
16
17 use rustc::hir::def_id::{CrateNum, DefIndex};
18 use rustc::hir::svh::Svh;
19 use rustc::middle::cstore::LoadedMacros;
20 use rustc::session::{config, Session};
21 use rustc_back::PanicStrategy;
22 use rustc::session::search_paths::PathKind;
23 use rustc::middle;
24 use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
25 use rustc::util::nodemap::{FnvHashMap, FnvHashSet};
26 use rustc::hir::map::Definitions;
27
28 use std::cell::{RefCell, Cell};
29 use std::ops::Deref;
30 use std::path::PathBuf;
31 use std::rc::Rc;
32 use std::fs;
33
34 use syntax::ast;
35 use syntax::abi::Abi;
36 use syntax::parse;
37 use syntax::attr;
38 use syntax::ext::base::SyntaxExtension;
39 use syntax::parse::token::{InternedString, intern};
40 use syntax_pos::{self, Span, mk_sp};
41 use log;
42
43 pub struct Library {
44 pub dylib: Option<(PathBuf, PathKind)>,
45 pub rlib: Option<(PathBuf, PathKind)>,
46 pub metadata: MetadataBlob,
47 }
48
49 pub struct CrateLoader<'a> {
50 pub sess: &'a Session,
51 cstore: &'a CStore,
52 next_crate_num: CrateNum,
53 foreign_item_map: FnvHashMap<String, Vec<ast::NodeId>>,
54 local_crate_name: String,
55 }
56
57 fn dump_crates(cstore: &CStore) {
58 info!("resolved crates:");
59 cstore.iter_crate_data_origins(|_, data, opt_source| {
60 info!(" name: {}", data.name());
61 info!(" cnum: {}", data.cnum);
62 info!(" hash: {}", data.hash());
63 info!(" reqd: {}", data.explicitly_linked.get());
64 opt_source.map(|cs| {
65 let CrateSource { dylib, rlib, cnum: _ } = cs;
66 dylib.map(|dl| info!(" dylib: {}", dl.0.display()));
67 rlib.map(|rl| info!(" rlib: {}", rl.0.display()));
68 });
69 })
70 }
71
72 fn should_link(i: &ast::Item) -> bool {
73 !attr::contains_name(&i.attrs, "no_link")
74 }
75
76 #[derive(Debug)]
77 struct ExternCrateInfo {
78 ident: String,
79 name: String,
80 id: ast::NodeId,
81 should_link: bool,
82 }
83
84 fn register_native_lib(sess: &Session,
85 cstore: &CStore,
86 span: Option<Span>,
87 name: String,
88 kind: cstore::NativeLibraryKind) {
89 if name.is_empty() {
90 match span {
91 Some(span) => {
92 struct_span_err!(sess, span, E0454,
93 "#[link(name = \"\")] given with empty name")
94 .span_label(span, &format!("empty name given"))
95 .emit();
96 }
97 None => {
98 sess.err("empty library name given via `-l`");
99 }
100 }
101 return
102 }
103 let is_osx = sess.target.target.options.is_like_osx;
104 if kind == cstore::NativeFramework && !is_osx {
105 let msg = "native frameworks are only available on OSX targets";
106 match span {
107 Some(span) => {
108 span_err!(sess, span, E0455,
109 "{}", msg)
110 }
111 None => sess.err(msg),
112 }
113 }
114 cstore.add_used_library(name, kind);
115 }
116
117 // Extra info about a crate loaded for plugins or exported macros.
118 struct ExtensionCrate {
119 metadata: PMDSource,
120 dylib: Option<PathBuf>,
121 target_only: bool,
122 }
123
124 enum PMDSource {
125 Registered(Rc<cstore::CrateMetadata>),
126 Owned(Library),
127 }
128
129 impl Deref for PMDSource {
130 type Target = MetadataBlob;
131
132 fn deref(&self) -> &MetadataBlob {
133 match *self {
134 PMDSource::Registered(ref cmd) => &cmd.blob,
135 PMDSource::Owned(ref lib) => &lib.metadata
136 }
137 }
138 }
139
140 enum LoadResult {
141 Previous(CrateNum),
142 Loaded(Library),
143 }
144
145 impl<'a> CrateLoader<'a> {
146 pub fn new(sess: &'a Session, cstore: &'a CStore, local_crate_name: &str) -> Self {
147 CrateLoader {
148 sess: sess,
149 cstore: cstore,
150 next_crate_num: cstore.next_crate_num(),
151 foreign_item_map: FnvHashMap(),
152 local_crate_name: local_crate_name.to_owned(),
153 }
154 }
155
156 fn extract_crate_info(&self, i: &ast::Item) -> Option<ExternCrateInfo> {
157 match i.node {
158 ast::ItemKind::ExternCrate(ref path_opt) => {
159 debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
160 i.ident, path_opt);
161 let name = match *path_opt {
162 Some(name) => {
163 validate_crate_name(Some(self.sess), &name.as_str(),
164 Some(i.span));
165 name.to_string()
166 }
167 None => i.ident.to_string(),
168 };
169 Some(ExternCrateInfo {
170 ident: i.ident.to_string(),
171 name: name,
172 id: i.id,
173 should_link: should_link(i),
174 })
175 }
176 _ => None
177 }
178 }
179
180 fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
181 -> Option<CrateNum> {
182 let mut ret = None;
183 self.cstore.iter_crate_data(|cnum, data| {
184 if data.name != name { return }
185
186 match hash {
187 Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
188 Some(..) => return,
189 None => {}
190 }
191
192 // When the hash is None we're dealing with a top-level dependency
193 // in which case we may have a specification on the command line for
194 // this library. Even though an upstream library may have loaded
195 // something of the same name, we have to make sure it was loaded
196 // from the exact same location as well.
197 //
198 // We're also sure to compare *paths*, not actual byte slices. The
199 // `source` stores paths which are normalized which may be different
200 // from the strings on the command line.
201 let source = self.cstore.used_crate_source(cnum);
202 if let Some(locs) = self.sess.opts.externs.get(name) {
203 let found = locs.iter().any(|l| {
204 let l = fs::canonicalize(l).ok();
205 source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
206 source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
207 });
208 if found {
209 ret = Some(cnum);
210 }
211 return
212 }
213
214 // Alright, so we've gotten this far which means that `data` has the
215 // right name, we don't have a hash, and we don't have a --extern
216 // pointing for ourselves. We're still not quite yet done because we
217 // have to make sure that this crate was found in the crate lookup
218 // path (this is a top-level dependency) as we don't want to
219 // implicitly load anything inside the dependency lookup path.
220 let prev_kind = source.dylib.as_ref().or(source.rlib.as_ref())
221 .unwrap().1;
222 if ret.is_none() && (prev_kind == kind || prev_kind == PathKind::All) {
223 ret = Some(cnum);
224 }
225 });
226 return ret;
227 }
228
229 fn verify_no_symbol_conflicts(&self,
230 span: Span,
231 root: &CrateRoot) {
232 // Check for (potential) conflicts with the local crate
233 if self.local_crate_name == root.name &&
234 self.sess.local_crate_disambiguator() == &root.disambiguator[..] {
235 span_fatal!(self.sess, span, E0519,
236 "the current crate is indistinguishable from one of its \
237 dependencies: it has the same crate-name `{}` and was \
238 compiled with the same `-C metadata` arguments. This \
239 will result in symbol conflicts between the two.",
240 root.name)
241 }
242
243 // Check for conflicts with any crate loaded so far
244 self.cstore.iter_crate_data(|_, other| {
245 if other.name() == root.name && // same crate-name
246 other.disambiguator() == root.disambiguator && // same crate-disambiguator
247 other.hash() != root.hash { // but different SVH
248 span_fatal!(self.sess, span, E0523,
249 "found two different crates with name `{}` that are \
250 not distinguished by differing `-C metadata`. This \
251 will result in symbol conflicts between the two.",
252 root.name)
253 }
254 });
255 }
256
257 fn register_crate(&mut self,
258 root: &Option<CratePaths>,
259 ident: &str,
260 name: &str,
261 span: Span,
262 lib: Library,
263 explicitly_linked: bool)
264 -> (CrateNum, Rc<cstore::CrateMetadata>,
265 cstore::CrateSource) {
266 info!("register crate `extern crate {} as {}`", name, ident);
267 let crate_root = lib.metadata.get_root();
268 self.verify_no_symbol_conflicts(span, &crate_root);
269
270 // Claim this crate number and cache it
271 let cnum = self.next_crate_num;
272 self.next_crate_num = CrateNum::from_u32(cnum.as_u32() + 1);
273
274 // Stash paths for top-most crate locally if necessary.
275 let crate_paths = if root.is_none() {
276 Some(CratePaths {
277 ident: ident.to_string(),
278 dylib: lib.dylib.clone().map(|p| p.0),
279 rlib: lib.rlib.clone().map(|p| p.0),
280 })
281 } else {
282 None
283 };
284 // Maintain a reference to the top most crate.
285 let root = if root.is_some() { root } else { &crate_paths };
286
287 let Library { dylib, rlib, metadata } = lib;
288
289 let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span);
290
291 if crate_root.macro_derive_registrar.is_some() {
292 self.sess.span_err(span, "crates of the `proc-macro` crate type \
293 cannot be linked at runtime");
294 }
295
296 let cmeta = Rc::new(cstore::CrateMetadata {
297 name: name.to_string(),
298 extern_crate: Cell::new(None),
299 key_map: metadata.load_key_map(crate_root.index),
300 root: crate_root,
301 blob: metadata,
302 cnum_map: RefCell::new(cnum_map),
303 cnum: cnum,
304 codemap_import_info: RefCell::new(vec![]),
305 explicitly_linked: Cell::new(explicitly_linked),
306 });
307
308 let source = cstore::CrateSource {
309 dylib: dylib,
310 rlib: rlib,
311 cnum: cnum,
312 };
313
314 self.cstore.set_crate_data(cnum, cmeta.clone());
315 self.cstore.add_used_crate_source(source.clone());
316 (cnum, cmeta, source)
317 }
318
319 fn resolve_crate(&mut self,
320 root: &Option<CratePaths>,
321 ident: &str,
322 name: &str,
323 hash: Option<&Svh>,
324 span: Span,
325 kind: PathKind,
326 explicitly_linked: bool)
327 -> (CrateNum, Rc<cstore::CrateMetadata>, cstore::CrateSource) {
328 info!("resolving crate `extern crate {} as {}`", name, ident);
329 let result = match self.existing_match(name, hash, kind) {
330 Some(cnum) => LoadResult::Previous(cnum),
331 None => {
332 info!("falling back to a load");
333 let mut locate_ctxt = locator::Context {
334 sess: self.sess,
335 span: span,
336 ident: ident,
337 crate_name: name,
338 hash: hash.map(|a| &*a),
339 filesearch: self.sess.target_filesearch(kind),
340 target: &self.sess.target.target,
341 triple: &self.sess.opts.target_triple,
342 root: root,
343 rejected_via_hash: vec![],
344 rejected_via_triple: vec![],
345 rejected_via_kind: vec![],
346 rejected_via_version: vec![],
347 should_match_name: true,
348 };
349 match self.load(&mut locate_ctxt) {
350 Some(result) => result,
351 None => locate_ctxt.report_errs(),
352 }
353 }
354 };
355
356 match result {
357 LoadResult::Previous(cnum) => {
358 let data = self.cstore.get_crate_data(cnum);
359 if explicitly_linked && !data.explicitly_linked.get() {
360 data.explicitly_linked.set(explicitly_linked);
361 }
362 (cnum, data, self.cstore.used_crate_source(cnum))
363 }
364 LoadResult::Loaded(library) => {
365 self.register_crate(root, ident, name, span, library,
366 explicitly_linked)
367 }
368 }
369 }
370
371 fn load(&mut self, locate_ctxt: &mut locator::Context) -> Option<LoadResult> {
372 let library = match locate_ctxt.maybe_load_library_crate() {
373 Some(lib) => lib,
374 None => return None,
375 };
376
377 // In the case that we're loading a crate, but not matching
378 // against a hash, we could load a crate which has the same hash
379 // as an already loaded crate. If this is the case prevent
380 // duplicates by just using the first crate.
381 //
382 // Note that we only do this for target triple crates, though, as we
383 // don't want to match a host crate against an equivalent target one
384 // already loaded.
385 let root = library.metadata.get_root();
386 if locate_ctxt.triple == self.sess.opts.target_triple {
387 let mut result = LoadResult::Loaded(library);
388 self.cstore.iter_crate_data(|cnum, data| {
389 if data.name() == root.name && root.hash == data.hash() {
390 assert!(locate_ctxt.hash.is_none());
391 info!("load success, going to previous cnum: {}", cnum);
392 result = LoadResult::Previous(cnum);
393 }
394 });
395 Some(result)
396 } else {
397 Some(LoadResult::Loaded(library))
398 }
399 }
400
401 fn update_extern_crate(&mut self,
402 cnum: CrateNum,
403 mut extern_crate: ExternCrate,
404 visited: &mut FnvHashSet<(CrateNum, bool)>)
405 {
406 if !visited.insert((cnum, extern_crate.direct)) { return }
407
408 let cmeta = self.cstore.get_crate_data(cnum);
409 let old_extern_crate = cmeta.extern_crate.get();
410
411 // Prefer:
412 // - something over nothing (tuple.0);
413 // - direct extern crate to indirect (tuple.1);
414 // - shorter paths to longer (tuple.2).
415 let new_rank = (true, extern_crate.direct, !extern_crate.path_len);
416 let old_rank = match old_extern_crate {
417 None => (false, false, !0),
418 Some(ref c) => (true, c.direct, !c.path_len),
419 };
420
421 if old_rank >= new_rank {
422 return; // no change needed
423 }
424
425 cmeta.extern_crate.set(Some(extern_crate));
426 // Propagate the extern crate info to dependencies.
427 extern_crate.direct = false;
428 for &dep_cnum in cmeta.cnum_map.borrow().iter() {
429 self.update_extern_crate(dep_cnum, extern_crate, visited);
430 }
431 }
432
433 // Go through the crate metadata and load any crates that it references
434 fn resolve_crate_deps(&mut self,
435 root: &Option<CratePaths>,
436 crate_root: &CrateRoot,
437 metadata: &MetadataBlob,
438 krate: CrateNum,
439 span: Span)
440 -> cstore::CrateNumMap {
441 debug!("resolving deps of external crate");
442 // The map from crate numbers in the crate we're resolving to local crate
443 // numbers
444 let deps = crate_root.crate_deps.decode(metadata);
445 let map: FnvHashMap<_, _> = deps.enumerate().map(|(crate_num, dep)| {
446 debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
447 let (local_cnum, ..) = self.resolve_crate(root,
448 &dep.name.as_str(),
449 &dep.name.as_str(),
450 Some(&dep.hash),
451 span,
452 PathKind::Dependency,
453 dep.explicitly_linked);
454 (CrateNum::new(crate_num + 1), local_cnum)
455 }).collect();
456
457 let max_cnum = map.values().cloned().max().map(|cnum| cnum.as_u32()).unwrap_or(0);
458
459 // we map 0 and all other holes in the map to our parent crate. The "additional"
460 // self-dependencies should be harmless.
461 (0..max_cnum+1).map(|cnum| {
462 map.get(&CrateNum::from_u32(cnum)).cloned().unwrap_or(krate)
463 }).collect()
464 }
465
466 fn read_extension_crate(&mut self, span: Span, info: &ExternCrateInfo) -> ExtensionCrate {
467 info!("read extension crate {} `extern crate {} as {}` linked={}",
468 info.id, info.name, info.ident, info.should_link);
469 let target_triple = &self.sess.opts.target_triple[..];
470 let is_cross = target_triple != config::host_triple();
471 let mut target_only = false;
472 let ident = info.ident.clone();
473 let name = info.name.clone();
474 let mut locate_ctxt = locator::Context {
475 sess: self.sess,
476 span: span,
477 ident: &ident[..],
478 crate_name: &name[..],
479 hash: None,
480 filesearch: self.sess.host_filesearch(PathKind::Crate),
481 target: &self.sess.host,
482 triple: config::host_triple(),
483 root: &None,
484 rejected_via_hash: vec![],
485 rejected_via_triple: vec![],
486 rejected_via_kind: vec![],
487 rejected_via_version: vec![],
488 should_match_name: true,
489 };
490 let library = self.load(&mut locate_ctxt).or_else(|| {
491 if !is_cross {
492 return None
493 }
494 // Try loading from target crates. This will abort later if we
495 // try to load a plugin registrar function,
496 target_only = true;
497
498 locate_ctxt.target = &self.sess.target.target;
499 locate_ctxt.triple = target_triple;
500 locate_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate);
501
502 self.load(&mut locate_ctxt)
503 });
504 let library = match library {
505 Some(l) => l,
506 None => locate_ctxt.report_errs(),
507 };
508
509 let (dylib, metadata) = match library {
510 LoadResult::Previous(cnum) => {
511 let dylib = self.cstore.opt_used_crate_source(cnum).unwrap().dylib;
512 let data = self.cstore.get_crate_data(cnum);
513 (dylib, PMDSource::Registered(data))
514 }
515 LoadResult::Loaded(library) => {
516 let dylib = library.dylib.clone();
517 let metadata = PMDSource::Owned(library);
518 (dylib, metadata)
519 }
520 };
521
522 ExtensionCrate {
523 metadata: metadata,
524 dylib: dylib.map(|p| p.0),
525 target_only: target_only,
526 }
527 }
528
529 fn read_macros(&mut self, item: &ast::Item, ekrate: &ExtensionCrate) -> LoadedMacros {
530 let root = ekrate.metadata.get_root();
531 let source_name = format!("<{} macros>", item.ident);
532 let mut macro_rules = Vec::new();
533
534 for def in root.macro_defs.decode(&*ekrate.metadata) {
535 // NB: Don't use parse::parse_tts_from_source_str because it parses with
536 // quote_depth > 0.
537 let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess,
538 source_name.clone(),
539 def.body);
540 let lo = p.span.lo;
541 let body = match p.parse_all_token_trees() {
542 Ok(body) => body,
543 Err(mut err) => {
544 err.emit();
545 self.sess.abort_if_errors();
546 unreachable!();
547 }
548 };
549 let local_span = mk_sp(lo, p.prev_span.hi);
550
551 // Mark the attrs as used
552 for attr in &def.attrs {
553 attr::mark_used(attr);
554 }
555
556 macro_rules.push(ast::MacroDef {
557 ident: ast::Ident::with_empty_ctxt(def.name),
558 id: ast::DUMMY_NODE_ID,
559 span: local_span,
560 imported_from: Some(item.ident),
561 allow_internal_unstable: attr::contains_name(&def.attrs, "allow_internal_unstable"),
562 attrs: def.attrs,
563 body: body,
564 });
565 self.sess.imported_macro_spans.borrow_mut()
566 .insert(local_span, (def.name.as_str().to_string(), def.span));
567 }
568
569 if let Some(id) = root.macro_derive_registrar {
570 let dylib = match ekrate.dylib.clone() {
571 Some(dylib) => dylib,
572 None => span_bug!(item.span, "proc-macro crate not dylib"),
573 };
574 if ekrate.target_only {
575 let message = format!("proc-macro crate is not available for \
576 triple `{}` (only found {})",
577 config::host_triple(),
578 self.sess.opts.target_triple);
579 self.sess.span_fatal(item.span, &message);
580 }
581
582 // custom derive crates currently should not have any macro_rules!
583 // exported macros, enforced elsewhere
584 assert_eq!(macro_rules.len(), 0);
585 LoadedMacros::ProcMacros(self.load_derive_macros(item, id, root.hash, dylib))
586 } else {
587 LoadedMacros::MacroRules(macro_rules)
588 }
589 }
590
591 /// Load custom derive macros.
592 ///
593 /// Note that this is intentionally similar to how we load plugins today,
594 /// but also intentionally separate. Plugins are likely always going to be
595 /// implemented as dynamic libraries, but we have a possible future where
596 /// custom derive (and other macro-1.1 style features) are implemented via
597 /// executables and custom IPC.
598 fn load_derive_macros(&mut self, item: &ast::Item, index: DefIndex, svh: Svh, path: PathBuf)
599 -> Vec<(ast::Name, SyntaxExtension)> {
600 use std::{env, mem};
601 use proc_macro::TokenStream;
602 use proc_macro::__internal::Registry;
603 use rustc_back::dynamic_lib::DynamicLibrary;
604 use syntax_ext::deriving::custom::CustomDerive;
605
606 // Make sure the path contains a / or the linker will search for it.
607 let path = env::current_dir().unwrap().join(path);
608 let lib = match DynamicLibrary::open(Some(&path)) {
609 Ok(lib) => lib,
610 Err(err) => self.sess.span_fatal(item.span, &err),
611 };
612
613 let sym = self.sess.generate_derive_registrar_symbol(&svh, index);
614 let registrar = unsafe {
615 let sym = match lib.symbol(&sym) {
616 Ok(f) => f,
617 Err(err) => self.sess.span_fatal(item.span, &err),
618 };
619 mem::transmute::<*mut u8, fn(&mut Registry)>(sym)
620 };
621
622 struct MyRegistrar(Vec<(ast::Name, SyntaxExtension)>);
623
624 impl Registry for MyRegistrar {
625 fn register_custom_derive(&mut self,
626 trait_name: &str,
627 expand: fn(TokenStream) -> TokenStream) {
628 let derive = SyntaxExtension::CustomDerive(Box::new(CustomDerive::new(expand)));
629 self.0.push((intern(trait_name), derive));
630 }
631 }
632
633 let mut my_registrar = MyRegistrar(Vec::new());
634 registrar(&mut my_registrar);
635
636 // Intentionally leak the dynamic library. We can't ever unload it
637 // since the library can make things that will live arbitrarily long.
638 mem::forget(lib);
639 my_registrar.0
640 }
641
642 /// Look for a plugin registrar. Returns library path, crate
643 /// SVH and DefIndex of the registrar function.
644 pub fn find_plugin_registrar(&mut self, span: Span, name: &str)
645 -> Option<(PathBuf, Svh, DefIndex)> {
646 let ekrate = self.read_extension_crate(span, &ExternCrateInfo {
647 name: name.to_string(),
648 ident: name.to_string(),
649 id: ast::DUMMY_NODE_ID,
650 should_link: false,
651 });
652
653 if ekrate.target_only {
654 // Need to abort before syntax expansion.
655 let message = format!("plugin `{}` is not available for triple `{}` \
656 (only found {})",
657 name,
658 config::host_triple(),
659 self.sess.opts.target_triple);
660 span_fatal!(self.sess, span, E0456, "{}", &message[..]);
661 }
662
663 let root = ekrate.metadata.get_root();
664 match (ekrate.dylib.as_ref(), root.plugin_registrar_fn) {
665 (Some(dylib), Some(reg)) => {
666 Some((dylib.to_path_buf(), root.hash, reg))
667 }
668 (None, Some(_)) => {
669 span_err!(self.sess, span, E0457,
670 "plugin `{}` only found in rlib format, but must be available \
671 in dylib format",
672 name);
673 // No need to abort because the loading code will just ignore this
674 // empty dylib.
675 None
676 }
677 _ => None,
678 }
679 }
680
681 fn register_statically_included_foreign_items(&mut self) {
682 let libs = self.cstore.get_used_libraries();
683 for (lib, list) in self.foreign_item_map.iter() {
684 let is_static = libs.borrow().iter().any(|&(ref name, kind)| {
685 lib == name && kind == cstore::NativeStatic
686 });
687 if is_static {
688 for id in list {
689 self.cstore.add_statically_included_foreign_item(*id);
690 }
691 }
692 }
693 }
694
695 fn inject_panic_runtime(&mut self, krate: &ast::Crate) {
696 // If we're only compiling an rlib, then there's no need to select a
697 // panic runtime, so we just skip this section entirely.
698 let any_non_rlib = self.sess.crate_types.borrow().iter().any(|ct| {
699 *ct != config::CrateTypeRlib
700 });
701 if !any_non_rlib {
702 info!("panic runtime injection skipped, only generating rlib");
703 return
704 }
705
706 // If we need a panic runtime, we try to find an existing one here. At
707 // the same time we perform some general validation of the DAG we've got
708 // going such as ensuring everything has a compatible panic strategy.
709 //
710 // The logic for finding the panic runtime here is pretty much the same
711 // as the allocator case with the only addition that the panic strategy
712 // compilation mode also comes into play.
713 let desired_strategy = self.sess.panic_strategy();
714 let mut runtime_found = false;
715 let mut needs_panic_runtime = attr::contains_name(&krate.attrs,
716 "needs_panic_runtime");
717 self.cstore.iter_crate_data(|cnum, data| {
718 needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime();
719 if data.is_panic_runtime() {
720 // Inject a dependency from all #![needs_panic_runtime] to this
721 // #![panic_runtime] crate.
722 self.inject_dependency_if(cnum, "a panic runtime",
723 &|data| data.needs_panic_runtime());
724 runtime_found = runtime_found || data.explicitly_linked.get();
725 }
726 });
727
728 // If an explicitly linked and matching panic runtime was found, or if
729 // we just don't need one at all, then we're done here and there's
730 // nothing else to do.
731 if !needs_panic_runtime || runtime_found {
732 return
733 }
734
735 // By this point we know that we (a) need a panic runtime and (b) no
736 // panic runtime was explicitly linked. Here we just load an appropriate
737 // default runtime for our panic strategy and then inject the
738 // dependencies.
739 //
740 // We may resolve to an already loaded crate (as the crate may not have
741 // been explicitly linked prior to this) and we may re-inject
742 // dependencies again, but both of those situations are fine.
743 //
744 // Also note that we have yet to perform validation of the crate graph
745 // in terms of everyone has a compatible panic runtime format, that's
746 // performed later as part of the `dependency_format` module.
747 let name = match desired_strategy {
748 PanicStrategy::Unwind => "panic_unwind",
749 PanicStrategy::Abort => "panic_abort",
750 };
751 info!("panic runtime not found -- loading {}", name);
752
753 let (cnum, data, _) = self.resolve_crate(&None, name, name, None,
754 syntax_pos::DUMMY_SP,
755 PathKind::Crate, false);
756
757 // Sanity check the loaded crate to ensure it is indeed a panic runtime
758 // and the panic strategy is indeed what we thought it was.
759 if !data.is_panic_runtime() {
760 self.sess.err(&format!("the crate `{}` is not a panic runtime",
761 name));
762 }
763 if data.panic_strategy() != desired_strategy {
764 self.sess.err(&format!("the crate `{}` does not have the panic \
765 strategy `{}`",
766 name, desired_strategy.desc()));
767 }
768
769 self.sess.injected_panic_runtime.set(Some(cnum));
770 self.inject_dependency_if(cnum, "a panic runtime",
771 &|data| data.needs_panic_runtime());
772 }
773
774 fn inject_allocator_crate(&mut self) {
775 // Make sure that we actually need an allocator, if none of our
776 // dependencies need one then we definitely don't!
777 //
778 // Also, if one of our dependencies has an explicit allocator, then we
779 // also bail out as we don't need to implicitly inject one.
780 let mut needs_allocator = false;
781 let mut found_required_allocator = false;
782 self.cstore.iter_crate_data(|cnum, data| {
783 needs_allocator = needs_allocator || data.needs_allocator();
784 if data.is_allocator() {
785 info!("{} required by rlib and is an allocator", data.name());
786 self.inject_dependency_if(cnum, "an allocator",
787 &|data| data.needs_allocator());
788 found_required_allocator = found_required_allocator ||
789 data.explicitly_linked.get();
790 }
791 });
792 if !needs_allocator || found_required_allocator { return }
793
794 // At this point we've determined that we need an allocator and no
795 // previous allocator has been activated. We look through our outputs of
796 // crate types to see what kind of allocator types we may need.
797 //
798 // The main special output type here is that rlibs do **not** need an
799 // allocator linked in (they're just object files), only final products
800 // (exes, dylibs, staticlibs) need allocators.
801 let mut need_lib_alloc = false;
802 let mut need_exe_alloc = false;
803 for ct in self.sess.crate_types.borrow().iter() {
804 match *ct {
805 config::CrateTypeExecutable => need_exe_alloc = true,
806 config::CrateTypeDylib |
807 config::CrateTypeProcMacro |
808 config::CrateTypeCdylib |
809 config::CrateTypeStaticlib => need_lib_alloc = true,
810 config::CrateTypeRlib => {}
811 }
812 }
813 if !need_lib_alloc && !need_exe_alloc { return }
814
815 // The default allocator crate comes from the custom target spec, and we
816 // choose between the standard library allocator or exe allocator. This
817 // distinction exists because the default allocator for binaries (where
818 // the world is Rust) is different than library (where the world is
819 // likely *not* Rust).
820 //
821 // If a library is being produced, but we're also flagged with `-C
822 // prefer-dynamic`, then we interpret this as a *Rust* dynamic library
823 // is being produced so we use the exe allocator instead.
824 //
825 // What this boils down to is:
826 //
827 // * Binaries use jemalloc
828 // * Staticlibs and Rust dylibs use system malloc
829 // * Rust dylibs used as dependencies to rust use jemalloc
830 let name = if need_lib_alloc && !self.sess.opts.cg.prefer_dynamic {
831 &self.sess.target.target.options.lib_allocation_crate
832 } else {
833 &self.sess.target.target.options.exe_allocation_crate
834 };
835 let (cnum, data, _) = self.resolve_crate(&None, name, name, None,
836 syntax_pos::DUMMY_SP,
837 PathKind::Crate, false);
838
839 // Sanity check the crate we loaded to ensure that it is indeed an
840 // allocator.
841 if !data.is_allocator() {
842 self.sess.err(&format!("the allocator crate `{}` is not tagged \
843 with #![allocator]", data.name()));
844 }
845
846 self.sess.injected_allocator.set(Some(cnum));
847 self.inject_dependency_if(cnum, "an allocator",
848 &|data| data.needs_allocator());
849 }
850
851 fn inject_dependency_if(&self,
852 krate: CrateNum,
853 what: &str,
854 needs_dep: &Fn(&cstore::CrateMetadata) -> bool) {
855 // don't perform this validation if the session has errors, as one of
856 // those errors may indicate a circular dependency which could cause
857 // this to stack overflow.
858 if self.sess.has_errors() {
859 return
860 }
861
862 // Before we inject any dependencies, make sure we don't inject a
863 // circular dependency by validating that this crate doesn't
864 // transitively depend on any crates satisfying `needs_dep`.
865 for dep in self.cstore.crate_dependencies_in_rpo(krate) {
866 let data = self.cstore.get_crate_data(dep);
867 if needs_dep(&data) {
868 self.sess.err(&format!("the crate `{}` cannot depend \
869 on a crate that needs {}, but \
870 it depends on `{}`",
871 self.cstore.get_crate_data(krate).name(),
872 what,
873 data.name()));
874 }
875 }
876
877 // All crates satisfying `needs_dep` do not explicitly depend on the
878 // crate provided for this compile, but in order for this compilation to
879 // be successfully linked we need to inject a dependency (to order the
880 // crates on the command line correctly).
881 self.cstore.iter_crate_data(|cnum, data| {
882 if !needs_dep(data) {
883 return
884 }
885
886 info!("injecting a dep from {} to {}", cnum, krate);
887 data.cnum_map.borrow_mut().push(krate);
888 });
889 }
890 }
891
892 impl<'a> CrateLoader<'a> {
893 pub fn preprocess(&mut self, krate: &ast::Crate) {
894 for attr in krate.attrs.iter().filter(|m| m.name() == "link_args") {
895 if let Some(ref linkarg) = attr.value_str() {
896 self.cstore.add_used_link_args(&linkarg);
897 }
898 }
899 }
900
901 fn process_foreign_mod(&mut self, i: &ast::Item, fm: &ast::ForeignMod) {
902 if fm.abi == Abi::Rust || fm.abi == Abi::RustIntrinsic || fm.abi == Abi::PlatformIntrinsic {
903 return;
904 }
905
906 // First, add all of the custom #[link_args] attributes
907 for m in i.attrs.iter().filter(|a| a.check_name("link_args")) {
908 if let Some(linkarg) = m.value_str() {
909 self.cstore.add_used_link_args(&linkarg);
910 }
911 }
912
913 // Next, process all of the #[link(..)]-style arguments
914 for m in i.attrs.iter().filter(|a| a.check_name("link")) {
915 let items = match m.meta_item_list() {
916 Some(item) => item,
917 None => continue,
918 };
919 let kind = items.iter().find(|k| {
920 k.check_name("kind")
921 }).and_then(|a| a.value_str());
922 let kind = match kind.as_ref().map(|s| &s[..]) {
923 Some("static") => cstore::NativeStatic,
924 Some("dylib") => cstore::NativeUnknown,
925 Some("framework") => cstore::NativeFramework,
926 Some(k) => {
927 struct_span_err!(self.sess, m.span, E0458,
928 "unknown kind: `{}`", k)
929 .span_label(m.span, &format!("unknown kind")).emit();
930 cstore::NativeUnknown
931 }
932 None => cstore::NativeUnknown
933 };
934 let n = items.iter().find(|n| {
935 n.check_name("name")
936 }).and_then(|a| a.value_str());
937 let n = match n {
938 Some(n) => n,
939 None => {
940 struct_span_err!(self.sess, m.span, E0459,
941 "#[link(...)] specified without `name = \"foo\"`")
942 .span_label(m.span, &format!("missing `name` argument")).emit();
943 InternedString::new("foo")
944 }
945 };
946 register_native_lib(self.sess, self.cstore, Some(m.span), n.to_string(), kind);
947 }
948
949 // Finally, process the #[linked_from = "..."] attribute
950 for m in i.attrs.iter().filter(|a| a.check_name("linked_from")) {
951 let lib_name = match m.value_str() {
952 Some(name) => name,
953 None => continue,
954 };
955 let list = self.foreign_item_map.entry(lib_name.to_string())
956 .or_insert(Vec::new());
957 list.extend(fm.items.iter().map(|it| it.id));
958 }
959 }
960 }
961
962 impl<'a> middle::cstore::CrateLoader for CrateLoader<'a> {
963 fn postprocess(&mut self, krate: &ast::Crate) {
964 self.inject_allocator_crate();
965 self.inject_panic_runtime(krate);
966
967 if log_enabled!(log::INFO) {
968 dump_crates(&self.cstore);
969 }
970
971 for &(ref name, kind) in &self.sess.opts.libs {
972 register_native_lib(self.sess, self.cstore, None, name.clone(), kind);
973 }
974 self.register_statically_included_foreign_items();
975 }
976
977 fn process_item(&mut self, item: &ast::Item, definitions: &Definitions, load_macros: bool)
978 -> Option<LoadedMacros> {
979 match item.node {
980 ast::ItemKind::ExternCrate(_) => {}
981 ast::ItemKind::ForeignMod(ref fm) => {
982 self.process_foreign_mod(item, fm);
983 return None;
984 }
985 _ => return None,
986 }
987
988 let info = self.extract_crate_info(item).unwrap();
989 let loaded_macros = if load_macros {
990 let ekrate = self.read_extension_crate(item.span, &info);
991 let loaded_macros = self.read_macros(item, &ekrate);
992
993 // If this is a proc-macro crate or `#[no_link]` crate, it is only used at compile time,
994 // so we return here to avoid registering the crate.
995 if loaded_macros.is_proc_macros() || !info.should_link {
996 return Some(loaded_macros);
997 }
998
999 // Register crate now to avoid double-reading metadata
1000 if let PMDSource::Owned(lib) = ekrate.metadata {
1001 if ekrate.target_only || config::host_triple() == self.sess.opts.target_triple {
1002 let ExternCrateInfo { ref ident, ref name, .. } = info;
1003 self.register_crate(&None, ident, name, item.span, lib, true);
1004 }
1005 }
1006
1007 Some(loaded_macros)
1008 } else {
1009 if !info.should_link {
1010 return None;
1011 }
1012 None
1013 };
1014
1015 let (cnum, ..) = self.resolve_crate(
1016 &None, &info.ident, &info.name, None, item.span, PathKind::Crate, true,
1017 );
1018
1019 let def_id = definitions.opt_local_def_id(item.id).unwrap();
1020 let len = definitions.def_path(def_id.index).data.len();
1021
1022 let extern_crate =
1023 ExternCrate { def_id: def_id, span: item.span, direct: true, path_len: len };
1024 self.update_extern_crate(cnum, extern_crate, &mut FnvHashSet());
1025 self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
1026
1027 loaded_macros
1028 }
1029 }