2015-02-05 14:28:17 -06:00
|
|
|
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
|
2012-12-03 18:48:01 -06:00
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2014-03-21 20:05:05 -05:00
|
|
|
#![allow(non_camel_case_types)]
|
2014-02-10 08:36:31 -06:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
//! Validates all used crates and extern libraries and loads their metadata
|
2011-03-15 18:30:43 -05:00
|
|
|
|
2014-02-24 21:45:20 -06:00
|
|
|
use back::svh::Svh;
|
2014-11-15 19:30:33 -06:00
|
|
|
use session::{config, Session};
|
2014-12-16 16:32:02 -06:00
|
|
|
use session::search_paths::PathKind;
|
2012-12-23 16:41:37 -06:00
|
|
|
use metadata::cstore;
|
2014-12-31 21:48:39 -06:00
|
|
|
use metadata::cstore::{CStore, CrateSource, MetadataBlob};
|
2012-12-23 16:41:37 -06:00
|
|
|
use metadata::decoder;
|
|
|
|
use metadata::loader;
|
2014-04-03 10:43:57 -05:00
|
|
|
use metadata::loader::CratePaths;
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2014-03-27 12:28:38 -05:00
|
|
|
use std::rc::Rc;
|
2013-07-19 20:42:11 -05:00
|
|
|
use syntax::ast;
|
2013-11-30 13:39:55 -06:00
|
|
|
use syntax::abi;
|
2012-09-04 13:54:36 -05:00
|
|
|
use syntax::attr;
|
2013-07-19 06:51:37 -05:00
|
|
|
use syntax::attr::AttrMetaMethods;
|
2015-02-06 15:56:38 -06:00
|
|
|
use syntax::codemap::{Span, mk_sp};
|
2014-12-30 21:10:46 -06:00
|
|
|
use syntax::parse;
|
2014-04-17 10:52:25 -05:00
|
|
|
use syntax::parse::token::InternedString;
|
2013-06-04 14:34:25 -05:00
|
|
|
use syntax::parse::token;
|
2013-08-26 04:01:39 -05:00
|
|
|
use syntax::visit;
|
2014-08-14 16:42:37 -05:00
|
|
|
use util::fs;
|
2014-12-21 00:36:50 -06:00
|
|
|
use log;
|
2011-03-15 18:30:43 -05:00
|
|
|
|
2014-12-21 01:02:38 -06:00
|
|
|
pub struct CrateReader<'a> {
|
2014-04-07 14:14:33 -05:00
|
|
|
sess: &'a Session,
|
|
|
|
next_crate_num: ast::CrateNum,
|
|
|
|
}
|
|
|
|
|
2014-12-21 01:02:38 -06:00
|
|
|
impl<'a, 'v> visit::Visitor<'v> for CrateReader<'a> {
|
2014-09-12 05:10:30 -05:00
|
|
|
fn visit_item(&mut self, a: &ast::Item) {
|
2014-12-21 00:36:50 -06:00
|
|
|
self.process_item(a);
|
2014-09-12 05:10:30 -05:00
|
|
|
visit::walk_item(self, a);
|
2013-08-26 04:01:39 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-07 14:14:33 -05:00
|
|
|
fn dump_crates(cstore: &CStore) {
|
2013-10-21 15:08:31 -05:00
|
|
|
debug!("resolved crates:");
|
2014-04-25 11:06:49 -05:00
|
|
|
cstore.iter_crate_data_origins(|_, data, opt_source| {
|
2014-06-06 15:21:18 -05:00
|
|
|
debug!(" name: {}", data.name());
|
2014-04-07 14:14:33 -05:00
|
|
|
debug!(" cnum: {}", data.cnum);
|
|
|
|
debug!(" hash: {}", data.hash());
|
2014-04-25 11:06:49 -05:00
|
|
|
opt_source.map(|cs| {
|
|
|
|
let CrateSource { dylib, rlib, cnum: _ } = cs;
|
2015-01-06 10:46:07 -06:00
|
|
|
dylib.map(|dl| debug!(" dylib: {}", dl.0.display()));
|
|
|
|
rlib.map(|rl| debug!(" rlib: {}", rl.0.display()));
|
2014-04-25 11:06:49 -05:00
|
|
|
});
|
2014-04-07 14:14:33 -05:00
|
|
|
})
|
2012-04-09 17:06:38 -05:00
|
|
|
}
|
|
|
|
|
2014-12-23 13:33:44 -06:00
|
|
|
fn should_link(i: &ast::Item) -> bool {
|
2015-01-07 10:58:31 -06:00
|
|
|
!attr::contains_name(&i.attrs[], "no_link")
|
2014-04-07 14:16:43 -05:00
|
|
|
}
|
2013-12-25 12:10:33 -06:00
|
|
|
|
|
|
|
struct CrateInfo {
|
2014-05-22 18:57:53 -05:00
|
|
|
ident: String,
|
2014-06-06 15:21:18 -05:00
|
|
|
name: String,
|
2013-12-25 12:10:33 -06:00
|
|
|
id: ast::NodeId,
|
2014-04-07 14:16:43 -05:00
|
|
|
should_link: bool,
|
2013-12-25 12:10:33 -06:00
|
|
|
}
|
|
|
|
|
2014-06-06 15:21:18 -05:00
|
|
|
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
|
2015-02-01 11:44:15 -06:00
|
|
|
let err = |s: &str| {
|
2014-06-06 15:21:18 -05:00
|
|
|
match (sp, sess) {
|
2014-10-09 14:17:22 -05:00
|
|
|
(_, None) => panic!("{}", s),
|
2014-06-06 15:21:18 -05:00
|
|
|
(Some(sp), Some(sess)) => sess.span_err(sp, s),
|
|
|
|
(None, Some(sess)) => sess.err(s),
|
|
|
|
}
|
|
|
|
};
|
|
|
|
if s.len() == 0 {
|
|
|
|
err("crate name must not be empty");
|
|
|
|
}
|
|
|
|
for c in s.chars() {
|
|
|
|
if c.is_alphanumeric() { continue }
|
|
|
|
if c == '_' || c == '-' { continue }
|
2015-01-07 10:58:31 -06:00
|
|
|
err(&format!("invalid character `{}` in crate name: `{}`", c, s)[]);
|
2014-06-06 15:21:18 -05:00
|
|
|
}
|
|
|
|
match sess {
|
|
|
|
Some(sess) => sess.abort_if_errors(),
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-01 18:56:28 -06:00
|
|
|
|
librustc: Make `Copy` opt-in.
This change makes the compiler no longer infer whether types (structures
and enumerations) implement the `Copy` trait (and thus are implicitly
copyable). Rather, you must implement `Copy` yourself via `impl Copy for
MyType {}`.
A new warning has been added, `missing_copy_implementations`, to warn
you if a non-generic public type has been added that could have
implemented `Copy` but didn't.
For convenience, you may *temporarily* opt out of this behavior by using
`#![feature(opt_out_copy)]`. Note though that this feature gate will never be
accepted and will be removed by the time that 1.0 is released, so you should
transition your code away from using it.
This breaks code like:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
Change this code to:
#[deriving(Show)]
struct Point2D {
x: int,
y: int,
}
impl Copy for Point2D {}
fn main() {
let mypoint = Point2D {
x: 1,
y: 1,
};
let otherpoint = mypoint;
println!("{}{}", mypoint, otherpoint);
}
This is the backwards-incompatible part of #13231.
Part of RFC #3.
[breaking-change]
2014-12-05 19:01:33 -06:00
|
|
|
fn register_native_lib(sess: &Session,
|
|
|
|
span: Option<Span>,
|
|
|
|
name: String,
|
|
|
|
kind: cstore::NativeLibraryKind) {
|
2014-11-27 12:53:34 -06:00
|
|
|
if name.is_empty() {
|
2014-10-21 01:04:16 -05:00
|
|
|
match span {
|
|
|
|
Some(span) => {
|
|
|
|
sess.span_err(span, "#[link(name = \"\")] given with \
|
|
|
|
empty name");
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
sess.err("empty library name given via `-l`");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
2014-07-23 13:56:36 -05:00
|
|
|
let is_osx = sess.target.target.options.is_like_osx;
|
2014-10-21 01:04:16 -05:00
|
|
|
if kind == cstore::NativeFramework && !is_osx {
|
|
|
|
let msg = "native frameworks are only available on OSX targets";
|
|
|
|
match span {
|
|
|
|
Some(span) => sess.span_err(span, msg),
|
|
|
|
None => sess.err(msg),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
sess.cstore.add_used_library(name, kind);
|
|
|
|
}
|
|
|
|
|
2014-12-31 21:48:39 -06:00
|
|
|
pub struct PluginMetadata<'a> {
|
|
|
|
sess: &'a Session,
|
|
|
|
metadata: PMDSource,
|
|
|
|
dylib: Option<Path>,
|
|
|
|
info: CrateInfo,
|
|
|
|
vi_span: Span,
|
|
|
|
target_only: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum PMDSource {
|
|
|
|
Registered(Rc<cstore::crate_metadata>),
|
|
|
|
Owned(MetadataBlob),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PMDSource {
|
|
|
|
pub fn as_slice<'a>(&'a self) -> &'a [u8] {
|
|
|
|
match *self {
|
|
|
|
PMDSource::Registered(ref cmd) => cmd.data(),
|
|
|
|
PMDSource::Owned(ref mdb) => mdb.as_slice(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-21 01:02:38 -06:00
|
|
|
impl<'a> CrateReader<'a> {
|
|
|
|
pub fn new(sess: &'a Session) -> CrateReader<'a> {
|
|
|
|
CrateReader {
|
|
|
|
sess: sess,
|
|
|
|
next_crate_num: sess.cstore.next_crate_num(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Traverses an AST, reading all the information about use'd crates and extern
|
|
|
|
// libraries necessary for later resolving, typechecking, linking, etc.
|
|
|
|
pub fn read_crates(&mut self, krate: &ast::Crate) {
|
|
|
|
self.process_crate(krate);
|
|
|
|
visit::walk_crate(self, krate);
|
|
|
|
|
|
|
|
if log_enabled!(log::DEBUG) {
|
|
|
|
dump_crates(&self.sess.cstore);
|
|
|
|
}
|
|
|
|
|
2015-01-31 11:20:46 -06:00
|
|
|
for &(ref name, kind) in &self.sess.opts.libs {
|
2014-12-21 01:02:38 -06:00
|
|
|
register_native_lib(self.sess, None, name.clone(), kind);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn process_crate(&self, c: &ast::Crate) {
|
2014-12-21 00:36:50 -06:00
|
|
|
for a in c.attrs.iter().filter(|m| m.name() == "link_args") {
|
|
|
|
match a.value_str() {
|
2015-02-04 14:48:12 -06:00
|
|
|
Some(ref linkarg) => self.sess.cstore.add_used_link_args(&linkarg),
|
2014-12-21 00:36:50 -06:00
|
|
|
None => { /* fallthrough */ }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-23 13:33:44 -06:00
|
|
|
fn extract_crate_info(&self, i: &ast::Item) -> Option<CrateInfo> {
|
2014-12-21 00:36:50 -06:00
|
|
|
match i.node {
|
2014-12-23 13:33:44 -06:00
|
|
|
ast::ItemExternCrate(ref path_opt) => {
|
|
|
|
let ident = token::get_ident(i.ident);
|
2015-01-06 18:16:35 -06:00
|
|
|
debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
|
2014-12-21 00:36:50 -06:00
|
|
|
ident, path_opt);
|
|
|
|
let name = match *path_opt {
|
|
|
|
Some((ref path_str, _)) => {
|
2015-02-03 17:03:39 -06:00
|
|
|
let name = path_str.to_string();
|
2015-01-07 10:58:31 -06:00
|
|
|
validate_crate_name(Some(self.sess), &name[],
|
2014-12-21 00:36:50 -06:00
|
|
|
Some(i.span));
|
|
|
|
name
|
|
|
|
}
|
2015-02-03 17:03:39 -06:00
|
|
|
None => ident.to_string(),
|
2014-12-21 00:36:50 -06:00
|
|
|
};
|
|
|
|
Some(CrateInfo {
|
2015-02-03 17:03:39 -06:00
|
|
|
ident: ident.to_string(),
|
2014-12-21 00:36:50 -06:00
|
|
|
name: name,
|
2014-12-23 13:33:44 -06:00
|
|
|
id: i.id,
|
2014-12-21 00:36:50 -06:00
|
|
|
should_link: should_link(i),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
_ => None
|
2014-07-01 10:37:54 -05:00
|
|
|
}
|
2014-12-21 00:36:50 -06:00
|
|
|
}
|
|
|
|
|
2014-12-23 13:33:44 -06:00
|
|
|
fn process_item(&mut self, i: &ast::Item) {
|
2014-12-21 00:36:50 -06:00
|
|
|
match i.node {
|
2014-12-23 13:33:44 -06:00
|
|
|
ast::ItemExternCrate(_) => {
|
|
|
|
if !should_link(i) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
match self.extract_crate_info(i) {
|
|
|
|
Some(info) => {
|
|
|
|
let (cnum, _, _) = self.resolve_crate(&None,
|
|
|
|
&info.ident[],
|
|
|
|
&info.name[],
|
|
|
|
None,
|
|
|
|
i.span,
|
|
|
|
PathKind::Crate);
|
|
|
|
self.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
|
|
|
|
}
|
|
|
|
None => ()
|
|
|
|
}
|
|
|
|
}
|
2014-12-21 00:36:50 -06:00
|
|
|
ast::ItemForeignMod(ref fm) => {
|
|
|
|
if fm.abi == abi::Rust || fm.abi == abi::RustIntrinsic {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// First, add all of the custom link_args attributes
|
|
|
|
let link_args = i.attrs.iter()
|
|
|
|
.filter_map(|at| if at.name() == "link_args" {
|
|
|
|
Some(at)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
})
|
|
|
|
.collect::<Vec<&ast::Attribute>>();
|
2015-01-31 11:20:46 -06:00
|
|
|
for m in &link_args {
|
2014-12-21 00:36:50 -06:00
|
|
|
match m.value_str() {
|
2015-02-04 14:48:12 -06:00
|
|
|
Some(linkarg) => self.sess.cstore.add_used_link_args(&linkarg),
|
2014-12-21 00:36:50 -06:00
|
|
|
None => { /* fallthrough */ }
|
|
|
|
}
|
|
|
|
}
|
2014-07-01 10:37:54 -05:00
|
|
|
|
2014-12-21 00:36:50 -06:00
|
|
|
// Next, process all of the #[link(..)]-style arguments
|
|
|
|
let link_args = i.attrs.iter()
|
|
|
|
.filter_map(|at| if at.name() == "link" {
|
|
|
|
Some(at)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
})
|
|
|
|
.collect::<Vec<&ast::Attribute>>();
|
2015-01-31 11:20:46 -06:00
|
|
|
for m in &link_args {
|
2014-12-21 00:36:50 -06:00
|
|
|
match m.meta_item_list() {
|
|
|
|
Some(items) => {
|
|
|
|
let kind = items.iter().find(|k| {
|
|
|
|
k.name() == "kind"
|
|
|
|
}).and_then(|a| a.value_str());
|
|
|
|
let kind = match kind {
|
|
|
|
Some(k) => {
|
|
|
|
if k == "static" {
|
|
|
|
cstore::NativeStatic
|
|
|
|
} else if self.sess.target.target.options.is_like_osx
|
|
|
|
&& k == "framework" {
|
|
|
|
cstore::NativeFramework
|
|
|
|
} else if k == "framework" {
|
|
|
|
cstore::NativeFramework
|
|
|
|
} else if k == "dylib" {
|
|
|
|
cstore::NativeUnknown
|
|
|
|
} else {
|
|
|
|
self.sess.span_err(m.span,
|
2015-01-07 10:58:31 -06:00
|
|
|
&format!("unknown kind: `{}`",
|
|
|
|
k)[]);
|
2014-12-21 00:36:50 -06:00
|
|
|
cstore::NativeUnknown
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None => cstore::NativeUnknown
|
|
|
|
};
|
|
|
|
let n = items.iter().find(|n| {
|
|
|
|
n.name() == "name"
|
|
|
|
}).and_then(|a| a.value_str());
|
|
|
|
let n = match n {
|
|
|
|
Some(n) => n,
|
|
|
|
None => {
|
|
|
|
self.sess.span_err(m.span,
|
|
|
|
"#[link(...)] specified without \
|
|
|
|
`name = \"foo\"`");
|
|
|
|
InternedString::new("foo")
|
|
|
|
}
|
|
|
|
};
|
|
|
|
register_native_lib(self.sess, Some(m.span),
|
2015-02-03 17:03:39 -06:00
|
|
|
n.to_string(), kind);
|
2014-12-21 00:36:50 -06:00
|
|
|
}
|
|
|
|
None => {}
|
|
|
|
}
|
2014-07-01 10:37:54 -05:00
|
|
|
}
|
2014-04-07 14:14:33 -05:00
|
|
|
}
|
2014-12-21 00:36:50 -06:00
|
|
|
_ => { }
|
2012-06-04 10:03:14 -05:00
|
|
|
}
|
2014-12-21 00:36:50 -06:00
|
|
|
}
|
2012-04-05 20:31:03 -05:00
|
|
|
|
2015-01-06 10:46:07 -06:00
|
|
|
fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
|
|
|
|
-> Option<ast::CrateNum> {
|
2014-12-21 00:36:50 -06:00
|
|
|
let mut ret = None;
|
|
|
|
self.sess.cstore.iter_crate_data(|cnum, data| {
|
|
|
|
if data.name != name { return }
|
|
|
|
|
|
|
|
match hash {
|
|
|
|
Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
|
|
|
|
Some(..) => return,
|
|
|
|
None => {}
|
|
|
|
}
|
|
|
|
|
2015-01-06 10:46:07 -06:00
|
|
|
// When the hash is None we're dealing with a top-level dependency
|
|
|
|
// in which case we may have a specification on the command line for
|
|
|
|
// this library. Even though an upstream library may have loaded
|
|
|
|
// something of the same name, we have to make sure it was loaded
|
|
|
|
// from the exact same location as well.
|
2014-12-21 00:36:50 -06:00
|
|
|
//
|
|
|
|
// We're also sure to compare *paths*, not actual byte slices. The
|
|
|
|
// `source` stores paths which are normalized which may be different
|
|
|
|
// from the strings on the command line.
|
|
|
|
let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
|
2015-01-06 10:46:07 -06:00
|
|
|
if let Some(locs) = self.sess.opts.externs.get(name) {
|
|
|
|
let found = locs.iter().any(|l| {
|
|
|
|
let l = fs::realpath(&Path::new(&l[])).ok();
|
|
|
|
source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
|
|
|
|
source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
|
|
|
|
});
|
|
|
|
if found {
|
|
|
|
ret = Some(cnum);
|
2014-12-21 00:36:50 -06:00
|
|
|
}
|
2015-01-30 11:48:23 -06:00
|
|
|
return
|
2015-01-06 10:46:07 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Alright, so we've gotten this far which means that `data` has the
|
|
|
|
// right name, we don't have a hash, and we don't have a --extern
|
|
|
|
// pointing for ourselves. We're still not quite yet done because we
|
|
|
|
// have to make sure that this crate was found in the crate lookup
|
|
|
|
// path (this is a top-level dependency) as we don't want to
|
|
|
|
// implicitly load anything inside the dependency lookup path.
|
|
|
|
let prev_kind = source.dylib.as_ref().or(source.rlib.as_ref())
|
|
|
|
.unwrap().1;
|
|
|
|
if ret.is_none() && (prev_kind == kind || prev_kind == PathKind::All) {
|
|
|
|
ret = Some(cnum);
|
2014-12-21 00:36:50 -06:00
|
|
|
}
|
|
|
|
});
|
|
|
|
return ret;
|
|
|
|
}
|
2014-04-17 10:52:25 -05:00
|
|
|
|
2014-12-21 00:36:50 -06:00
|
|
|
fn register_crate(&mut self,
|
|
|
|
root: &Option<CratePaths>,
|
|
|
|
ident: &str,
|
|
|
|
name: &str,
|
|
|
|
span: Span,
|
|
|
|
lib: loader::Library)
|
|
|
|
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
|
|
|
|
cstore::CrateSource) {
|
|
|
|
// Claim this crate number and cache it
|
|
|
|
let cnum = self.next_crate_num;
|
|
|
|
self.next_crate_num += 1;
|
|
|
|
|
|
|
|
// Stash paths for top-most crate locally if necessary.
|
|
|
|
let crate_paths = if root.is_none() {
|
|
|
|
Some(CratePaths {
|
|
|
|
ident: ident.to_string(),
|
2015-01-06 10:46:07 -06:00
|
|
|
dylib: lib.dylib.clone().map(|p| p.0),
|
|
|
|
rlib: lib.rlib.clone().map(|p| p.0),
|
2014-12-21 00:36:50 -06:00
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
// Maintain a reference to the top most crate.
|
|
|
|
let root = if root.is_some() { root } else { &crate_paths };
|
2014-04-17 10:52:25 -05:00
|
|
|
|
2014-12-21 00:36:50 -06:00
|
|
|
let cnum_map = self.resolve_crate_deps(root, lib.metadata.as_slice(), span);
|
2014-04-17 10:52:25 -05:00
|
|
|
|
2014-12-21 00:36:50 -06:00
|
|
|
let loader::Library{ dylib, rlib, metadata } = lib;
|
2014-04-17 10:52:25 -05:00
|
|
|
|
2014-12-21 00:36:50 -06:00
|
|
|
let cmeta = Rc::new( cstore::crate_metadata {
|
|
|
|
name: name.to_string(),
|
|
|
|
data: metadata,
|
|
|
|
cnum_map: cnum_map,
|
|
|
|
cnum: cnum,
|
|
|
|
span: span,
|
|
|
|
});
|
2014-04-17 10:52:25 -05:00
|
|
|
|
2014-12-21 00:36:50 -06:00
|
|
|
let source = cstore::CrateSource {
|
|
|
|
dylib: dylib,
|
|
|
|
rlib: rlib,
|
|
|
|
cnum: cnum,
|
|
|
|
};
|
|
|
|
|
|
|
|
self.sess.cstore.set_crate_data(cnum, cmeta.clone());
|
|
|
|
self.sess.cstore.add_used_crate_source(source.clone());
|
|
|
|
(cnum, cmeta, source)
|
|
|
|
}
|
2014-04-17 10:52:25 -05:00
|
|
|
|
2014-12-21 00:36:50 -06:00
|
|
|
fn resolve_crate(&mut self,
|
|
|
|
root: &Option<CratePaths>,
|
|
|
|
ident: &str,
|
|
|
|
name: &str,
|
|
|
|
hash: Option<&Svh>,
|
|
|
|
span: Span,
|
|
|
|
kind: PathKind)
|
|
|
|
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
|
|
|
|
cstore::CrateSource) {
|
2015-01-06 10:46:07 -06:00
|
|
|
match self.existing_match(name, hash, kind) {
|
2014-12-21 00:36:50 -06:00
|
|
|
None => {
|
|
|
|
let mut load_ctxt = loader::Context {
|
|
|
|
sess: self.sess,
|
|
|
|
span: span,
|
|
|
|
ident: ident,
|
|
|
|
crate_name: name,
|
|
|
|
hash: hash.map(|a| &*a),
|
|
|
|
filesearch: self.sess.target_filesearch(kind),
|
2015-01-08 19:14:10 -06:00
|
|
|
target: &self.sess.target.target,
|
2015-01-07 10:58:31 -06:00
|
|
|
triple: &self.sess.opts.target_triple[],
|
2014-12-21 00:36:50 -06:00
|
|
|
root: root,
|
|
|
|
rejected_via_hash: vec!(),
|
|
|
|
rejected_via_triple: vec!(),
|
2015-02-05 14:28:17 -06:00
|
|
|
rejected_via_kind: vec!(),
|
2014-12-21 00:36:50 -06:00
|
|
|
should_match_name: true,
|
|
|
|
};
|
|
|
|
let library = load_ctxt.load_library_crate();
|
|
|
|
self.register_crate(root, ident, name, span, library)
|
|
|
|
}
|
|
|
|
Some(cnum) => (cnum,
|
|
|
|
self.sess.cstore.get_crate_data(cnum),
|
|
|
|
self.sess.cstore.get_used_crate_source(cnum).unwrap())
|
2014-02-24 20:13:51 -06:00
|
|
|
}
|
2012-04-05 20:31:03 -05:00
|
|
|
}
|
2011-05-26 19:16:54 -05:00
|
|
|
|
2014-12-21 00:36:50 -06:00
|
|
|
// Go through the crate metadata and load any crates that it references
|
|
|
|
fn resolve_crate_deps(&mut self,
|
|
|
|
root: &Option<CratePaths>,
|
|
|
|
cdata: &[u8], span : Span)
|
|
|
|
-> cstore::cnum_map {
|
|
|
|
debug!("resolving deps of external crate");
|
|
|
|
// The map from crate numbers in the crate we're resolving to local crate
|
|
|
|
// numbers
|
|
|
|
decoder::get_crate_deps(cdata).iter().map(|dep| {
|
|
|
|
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
|
|
|
|
let (local_cnum, _, _) = self.resolve_crate(root,
|
2015-01-07 10:58:31 -06:00
|
|
|
&dep.name[],
|
|
|
|
&dep.name[],
|
2014-12-21 00:36:50 -06:00
|
|
|
Some(&dep.hash),
|
|
|
|
span,
|
|
|
|
PathKind::Dependency);
|
|
|
|
(dep.cnum, local_cnum)
|
|
|
|
}).collect()
|
|
|
|
}
|
2013-12-25 12:10:33 -06:00
|
|
|
|
2014-12-31 21:48:39 -06:00
|
|
|
pub fn read_plugin_metadata<'b>(&'b mut self,
|
2014-12-09 10:03:05 -06:00
|
|
|
krate: CrateOrString<'b>) -> PluginMetadata<'b> {
|
|
|
|
let (info, span) = match krate {
|
|
|
|
CrateOrString::Krate(c) => {
|
|
|
|
(self.extract_crate_info(c).unwrap(), c.span)
|
|
|
|
}
|
2015-02-06 15:56:38 -06:00
|
|
|
CrateOrString::Str(sp, s) => {
|
2014-12-09 10:03:05 -06:00
|
|
|
(CrateInfo {
|
|
|
|
name: s.to_string(),
|
|
|
|
ident: s.to_string(),
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
2015-02-11 18:13:27 -06:00
|
|
|
should_link: false,
|
2015-02-06 15:56:38 -06:00
|
|
|
}, sp)
|
2014-12-09 10:03:05 -06:00
|
|
|
}
|
|
|
|
};
|
2015-01-07 10:58:31 -06:00
|
|
|
let target_triple = &self.sess.opts.target_triple[];
|
2014-11-15 19:30:33 -06:00
|
|
|
let is_cross = target_triple != config::host_triple();
|
2014-04-17 10:52:25 -05:00
|
|
|
let mut should_link = info.should_link && !is_cross;
|
2014-12-31 21:48:39 -06:00
|
|
|
let mut target_only = false;
|
|
|
|
let ident = info.ident.clone();
|
|
|
|
let name = info.name.clone();
|
2014-04-17 10:52:25 -05:00
|
|
|
let mut load_ctxt = loader::Context {
|
2014-12-21 01:02:38 -06:00
|
|
|
sess: self.sess,
|
2014-12-09 10:03:05 -06:00
|
|
|
span: span,
|
2015-01-07 10:58:31 -06:00
|
|
|
ident: &ident[],
|
|
|
|
crate_name: &name[],
|
2014-04-17 10:52:25 -05:00
|
|
|
hash: None,
|
2014-12-21 01:02:38 -06:00
|
|
|
filesearch: self.sess.host_filesearch(PathKind::Crate),
|
2015-01-08 19:14:10 -06:00
|
|
|
target: &self.sess.host,
|
2014-11-15 19:30:33 -06:00
|
|
|
triple: config::host_triple(),
|
2014-04-17 10:52:25 -05:00
|
|
|
root: &None,
|
|
|
|
rejected_via_hash: vec!(),
|
|
|
|
rejected_via_triple: vec!(),
|
2015-02-05 14:28:17 -06:00
|
|
|
rejected_via_kind: vec!(),
|
2014-07-01 10:37:54 -05:00
|
|
|
should_match_name: true,
|
2014-04-17 10:52:25 -05:00
|
|
|
};
|
|
|
|
let library = match load_ctxt.maybe_load_library_crate() {
|
2014-07-09 21:13:28 -05:00
|
|
|
Some(l) => l,
|
2014-04-17 10:52:25 -05:00
|
|
|
None if is_cross => {
|
2015-01-06 10:46:07 -06:00
|
|
|
// Try loading from target crates. This will abort later if we
|
|
|
|
// try to load a plugin registrar function,
|
2014-12-31 21:48:39 -06:00
|
|
|
target_only = true;
|
|
|
|
should_link = info.should_link;
|
|
|
|
|
2015-01-08 19:14:10 -06:00
|
|
|
load_ctxt.target = &self.sess.target.target;
|
2014-04-17 10:52:25 -05:00
|
|
|
load_ctxt.triple = target_triple;
|
2014-12-21 01:02:38 -06:00
|
|
|
load_ctxt.filesearch = self.sess.target_filesearch(PathKind::Crate);
|
2014-12-31 21:48:39 -06:00
|
|
|
load_ctxt.load_library_crate()
|
2014-04-17 10:52:25 -05:00
|
|
|
}
|
|
|
|
None => { load_ctxt.report_load_errs(); unreachable!() },
|
|
|
|
};
|
2014-12-30 21:10:46 -06:00
|
|
|
|
2014-12-31 21:48:39 -06:00
|
|
|
let dylib = library.dylib.clone();
|
2015-01-06 10:46:07 -06:00
|
|
|
let register = should_link && self.existing_match(info.name.as_slice(),
|
|
|
|
None,
|
|
|
|
PathKind::Crate).is_none();
|
2014-12-31 21:48:39 -06:00
|
|
|
let metadata = if register {
|
|
|
|
// Register crate now to avoid double-reading metadata
|
2014-12-19 20:39:43 -06:00
|
|
|
let (_, cmd, _) = self.register_crate(&None, &info.ident[],
|
|
|
|
&info.name[], span, library);
|
2014-12-31 21:48:39 -06:00
|
|
|
PMDSource::Registered(cmd)
|
|
|
|
} else {
|
|
|
|
// Not registering the crate; just hold on to the metadata
|
|
|
|
PMDSource::Owned(library.metadata)
|
|
|
|
};
|
|
|
|
|
|
|
|
PluginMetadata {
|
|
|
|
sess: self.sess,
|
|
|
|
metadata: metadata,
|
2015-01-06 10:46:07 -06:00
|
|
|
dylib: dylib.map(|p| p.0),
|
2014-12-31 21:48:39 -06:00
|
|
|
info: info,
|
2014-12-09 10:03:05 -06:00
|
|
|
vi_span: span,
|
2014-12-31 21:48:39 -06:00
|
|
|
target_only: target_only,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-09 11:25:37 -06:00
|
|
|
#[derive(Copy)]
|
2014-12-09 10:03:05 -06:00
|
|
|
pub enum CrateOrString<'a> {
|
2014-12-23 13:33:44 -06:00
|
|
|
Krate(&'a ast::Item),
|
2015-02-06 15:56:38 -06:00
|
|
|
Str(Span, &'a str)
|
2014-12-09 10:03:05 -06:00
|
|
|
}
|
|
|
|
|
2014-12-31 21:48:39 -06:00
|
|
|
impl<'a> PluginMetadata<'a> {
|
|
|
|
/// Read exported macros
|
|
|
|
pub fn exported_macros(&self) -> Vec<ast::MacroDef> {
|
2015-01-07 10:58:31 -06:00
|
|
|
let imported_from = Some(token::intern(&self.info.ident[]).ident());
|
|
|
|
let source_name = format!("<{} macros>", &self.info.ident[]);
|
2014-12-30 21:10:46 -06:00
|
|
|
let mut macros = vec![];
|
2014-12-31 21:48:39 -06:00
|
|
|
decoder::each_exported_macro(self.metadata.as_slice(),
|
|
|
|
&*self.sess.cstore.intr,
|
2014-12-30 21:10:46 -06:00
|
|
|
|name, attrs, body| {
|
|
|
|
// NB: Don't use parse::parse_tts_from_source_str because it parses with
|
|
|
|
// quote_depth > 0.
|
|
|
|
let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess,
|
|
|
|
self.sess.opts.cfg.clone(),
|
|
|
|
source_name.clone(),
|
|
|
|
body);
|
|
|
|
let lo = p.span.lo;
|
|
|
|
let body = p.parse_all_token_trees();
|
|
|
|
let span = mk_sp(lo, p.last_span.hi);
|
|
|
|
p.abort_if_errors();
|
|
|
|
macros.push(ast::MacroDef {
|
|
|
|
ident: name.ident(),
|
|
|
|
attrs: attrs,
|
|
|
|
id: ast::DUMMY_NODE_ID,
|
|
|
|
span: span,
|
|
|
|
imported_from: imported_from,
|
2015-01-02 14:50:45 -06:00
|
|
|
// overridden in plugin/load.rs
|
|
|
|
export: false,
|
|
|
|
use_locally: false,
|
|
|
|
|
2014-12-30 21:10:46 -06:00
|
|
|
body: body,
|
|
|
|
});
|
|
|
|
true
|
|
|
|
}
|
|
|
|
);
|
2014-12-31 21:48:39 -06:00
|
|
|
macros
|
|
|
|
}
|
2014-12-30 21:10:46 -06:00
|
|
|
|
2014-12-31 21:48:39 -06:00
|
|
|
/// Look for a plugin registrar. Returns library path and symbol name.
|
|
|
|
pub fn plugin_registrar(&self) -> Option<(Path, String)> {
|
|
|
|
if self.target_only {
|
|
|
|
// Need to abort before syntax expansion.
|
|
|
|
let message = format!("plugin crate `{}` is not available for triple `{}` \
|
|
|
|
(only found {})",
|
|
|
|
self.info.ident,
|
|
|
|
config::host_triple(),
|
|
|
|
self.sess.opts.target_triple);
|
2015-01-07 10:58:31 -06:00
|
|
|
self.sess.span_err(self.vi_span, &message[]);
|
2014-12-31 21:48:39 -06:00
|
|
|
self.sess.abort_if_errors();
|
2014-07-09 21:13:28 -05:00
|
|
|
}
|
2014-12-31 21:48:39 -06:00
|
|
|
|
|
|
|
let registrar = decoder::get_plugin_registrar_fn(self.metadata.as_slice())
|
|
|
|
.map(|id| decoder::get_symbol(self.metadata.as_slice(), id));
|
|
|
|
|
|
|
|
match (self.dylib.as_ref(), registrar) {
|
|
|
|
(Some(dylib), Some(reg)) => Some((dylib.clone(), reg)),
|
|
|
|
(None, Some(_)) => {
|
|
|
|
let message = format!("plugin crate `{}` only found in rlib format, \
|
|
|
|
but must be available in dylib format",
|
|
|
|
self.info.ident);
|
2015-01-07 10:58:31 -06:00
|
|
|
self.sess.span_err(self.vi_span, &message[]);
|
2014-12-31 21:48:39 -06:00
|
|
|
// No need to abort because the loading code will just ignore this
|
|
|
|
// empty dylib.
|
|
|
|
None
|
|
|
|
}
|
|
|
|
_ => None,
|
2013-12-25 12:10:33 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|