Enable use of syntax extensions when cross compiling.
This adds the target triple to the crate metadata. When searching for a crate the phase (link, syntax) is taken into account. During link phase only crates matching the target triple are considered. During syntax phase, either the target or host triple will be accepted, unless the crate defines a macro_registrar, in which case only the host triple will match.
This commit is contained in:
parent
09bfb92fdc
commit
4ac89cd276
@ -526,8 +526,6 @@ endif
|
||||
# triples). The associated message will be printed as a warning
|
||||
# during attempts to run those tests.
|
||||
|
||||
CTEST_DISABLE_NONSELFHOST_rpass-full = "run-pass-full suite is unavailable when cross-compiling."
|
||||
|
||||
define DEF_CTEST_VARS
|
||||
|
||||
# All the per-stage build rules you might want to call from the
|
||||
@ -573,7 +571,7 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \
|
||||
$$(CTEST_TESTARGS)
|
||||
|
||||
CTEST_DEPS_rpass_$(1)-T-$(2)-H-$(3) = $$(RPASS_TESTS)
|
||||
CTEST_DEPS_rpass-full_$(1)-T-$(2)-H-$(3) = $$(RPASS_FULL_TESTS) $$(CSREQ$(1)_T_$(2)_H_$(3))
|
||||
CTEST_DEPS_rpass-full_$(1)-T-$(2)-H-$(3) = $$(RPASS_FULL_TESTS) $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
|
||||
CTEST_DEPS_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS)
|
||||
CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
|
||||
CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS)
|
||||
|
@ -184,7 +184,7 @@ impl<'a> Archive<'a> {
|
||||
let unixlibname = format!("lib{}.a", name);
|
||||
|
||||
let mut rustpath = filesearch::rust_path();
|
||||
rustpath.push(self.sess.filesearch().get_target_lib_path());
|
||||
rustpath.push(self.sess.target_filesearch().get_lib_path());
|
||||
let search = self.sess.opts.addl_lib_search_paths.borrow();
|
||||
for path in search.iter().chain(rustpath.iter()) {
|
||||
debug!("looking for {} inside {}", name, path.display());
|
||||
|
@ -1088,7 +1088,7 @@ fn link_args(sess: &Session,
|
||||
// The default library location, we need this to find the runtime.
|
||||
// The location of crates will be determined as needed.
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let lib_path = sess.filesearch().get_target_lib_path();
|
||||
let lib_path = sess.target_filesearch().get_lib_path();
|
||||
let stage: ~str = "-L".to_owned() + lib_path.as_str().unwrap();
|
||||
|
||||
let mut args = vec!(stage);
|
||||
|
@ -40,7 +40,7 @@ pub fn get_rpath_flags(sess: &Session, out_filename: &Path) -> Vec<~str> {
|
||||
|
||||
debug!("preparing the RPATH!");
|
||||
|
||||
let sysroot = sess.filesearch().sysroot;
|
||||
let sysroot = sess.sysroot();
|
||||
let output = out_filename;
|
||||
let libs = sess.cstore.get_used_crates(cstore::RequireDynamic);
|
||||
let libs = libs.move_iter().filter_map(|(_, l)| {
|
||||
|
@ -284,9 +284,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
|
||||
let time_passes = sess.time_passes();
|
||||
|
||||
time(time_passes, "external crate/lib resolution", (), |_|
|
||||
creader::read_crates(&sess, krate,
|
||||
session::sess_os_to_meta_os(sess.targ_cfg.os),
|
||||
token::get_ident_interner()));
|
||||
creader::read_crates(&sess, krate));
|
||||
|
||||
let lang_items = time(time_passes, "language item collection", (), |_|
|
||||
middle::lang_items::collect_language_items(krate, &sess));
|
||||
@ -794,7 +792,7 @@ pub fn build_target_config(sopts: &session::Options) -> session::Config {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn host_triple() -> ~str {
|
||||
pub fn host_triple() -> &'static str {
|
||||
// Get the host triple out of the build environment. This ensures that our
|
||||
// idea of the host triple is the same as for the set of libraries we've
|
||||
// actually built. We can't just take LLVM's host triple because they
|
||||
@ -803,7 +801,7 @@ pub fn host_triple() -> ~str {
|
||||
// Instead of grabbing the host triple (for the current host), we grab (at
|
||||
// compile time) the target triple that this rustc is built with and
|
||||
// calling that (at runtime) the host triple.
|
||||
(env!("CFG_COMPILER_HOST_TRIPLE")).to_owned()
|
||||
env!("CFG_COMPILER_HOST_TRIPLE")
|
||||
}
|
||||
|
||||
pub fn build_session_options(matches: &getopts::Matches) -> session::Options {
|
||||
@ -895,7 +893,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> session::Options {
|
||||
}
|
||||
|
||||
let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
|
||||
let target = matches.opt_str("target").unwrap_or(host_triple());
|
||||
let target = matches.opt_str("target").unwrap_or(host_triple().to_owned());
|
||||
let opt_level = {
|
||||
if (debugging_opts & session::NO_OPT) != 0 {
|
||||
No
|
||||
|
@ -319,17 +319,25 @@ impl Session {
|
||||
pub fn show_span(&self) -> bool {
|
||||
self.debugging_opt(SHOW_SPAN)
|
||||
}
|
||||
pub fn filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
|
||||
let sysroot = match self.opts.maybe_sysroot {
|
||||
Some(ref sysroot) => sysroot,
|
||||
pub fn sysroot<'a>(&'a self) -> &'a Path {
|
||||
match self.opts.maybe_sysroot {
|
||||
Some (ref sysroot) => sysroot,
|
||||
None => self.default_sysroot.as_ref()
|
||||
.expect("missing sysroot and default_sysroot in Session")
|
||||
};
|
||||
}
|
||||
}
|
||||
pub fn target_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
|
||||
filesearch::FileSearch::new(
|
||||
sysroot,
|
||||
self.sysroot(),
|
||||
self.opts.target_triple,
|
||||
&self.opts.addl_lib_search_paths)
|
||||
}
|
||||
pub fn host_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
|
||||
filesearch::FileSearch::new(
|
||||
self.sysroot(),
|
||||
host_triple(),
|
||||
&self.opts.addl_lib_search_paths)
|
||||
}
|
||||
}
|
||||
|
||||
/// Some reasonable defaults
|
||||
@ -343,7 +351,7 @@ pub fn basic_options() -> Options {
|
||||
output_types: Vec::new(),
|
||||
addl_lib_search_paths: RefCell::new(HashSet::new()),
|
||||
maybe_sysroot: None,
|
||||
target_triple: host_triple(),
|
||||
target_triple: host_triple().to_owned(),
|
||||
cfg: Vec::new(),
|
||||
test: false,
|
||||
parse_only: false,
|
||||
|
@ -200,6 +200,8 @@ pub static tag_macro_registrar_fn: uint = 0x8b;
|
||||
pub static tag_exported_macros: uint = 0x8c;
|
||||
pub static tag_macro_def: uint = 0x8d;
|
||||
|
||||
pub static tag_crate_triple: uint = 0x66;
|
||||
|
||||
#[deriving(Clone, Show)]
|
||||
pub struct LinkMeta {
|
||||
pub crateid: CrateId,
|
||||
|
@ -14,13 +14,12 @@
|
||||
|
||||
use back::link;
|
||||
use back::svh::Svh;
|
||||
use driver::{driver, session};
|
||||
use driver::session::Session;
|
||||
use driver::{driver, session};
|
||||
use metadata::cstore;
|
||||
use metadata::cstore::CStore;
|
||||
use metadata::decoder;
|
||||
use metadata::loader;
|
||||
use metadata::loader::Os;
|
||||
use metadata::loader::CratePaths;
|
||||
|
||||
use std::rc::Rc;
|
||||
@ -32,29 +31,23 @@ use syntax::attr::AttrMetaMethods;
|
||||
use syntax::codemap::{Span};
|
||||
use syntax::diagnostic::SpanHandler;
|
||||
use syntax::ext::base::{CrateLoader, MacroCrate};
|
||||
use syntax::parse::token::{IdentInterner, InternedString};
|
||||
use syntax::parse::token::InternedString;
|
||||
use syntax::parse::token;
|
||||
use syntax::crateid::CrateId;
|
||||
use syntax::visit;
|
||||
|
||||
struct Env<'a> {
|
||||
sess: &'a Session,
|
||||
os: loader::Os,
|
||||
next_crate_num: ast::CrateNum,
|
||||
intr: Rc<IdentInterner>
|
||||
}
|
||||
|
||||
// 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(sess: &Session,
|
||||
krate: &ast::Crate,
|
||||
os: loader::Os,
|
||||
intr: Rc<IdentInterner>) {
|
||||
krate: &ast::Crate) {
|
||||
let mut e = Env {
|
||||
sess: sess,
|
||||
os: os,
|
||||
next_crate_num: sess.cstore.next_crate_num(),
|
||||
intr: intr
|
||||
};
|
||||
visit_crate(&e, krate);
|
||||
visit::walk_crate(&mut e, krate, ());
|
||||
@ -84,7 +77,6 @@ fn dump_crates(cstore: &CStore) {
|
||||
|
||||
fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
|
||||
let mut map = HashMap::new();
|
||||
|
||||
cstore.iter_crate_data(|cnum, data| {
|
||||
let crateid = data.crate_id();
|
||||
let key = (crateid.name.clone(), crateid.path.clone());
|
||||
@ -129,7 +121,7 @@ fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
|
||||
match extract_crate_info(e, i) {
|
||||
Some(info) => {
|
||||
let (cnum, _, _) = resolve_crate(e, &None, info.ident,
|
||||
&info.crate_id, None, true,
|
||||
&info.crate_id, None,
|
||||
i.span);
|
||||
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
|
||||
}
|
||||
@ -272,13 +264,60 @@ fn existing_match(e: &Env, crate_id: &CrateId,
|
||||
return ret;
|
||||
}
|
||||
|
||||
fn register_crate<'a>(e: &mut Env,
|
||||
root: &Option<CratePaths>,
|
||||
ident: &str,
|
||||
crate_id: &CrateId,
|
||||
span: Span,
|
||||
lib: loader::Library)
|
||||
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
|
||||
cstore::CrateSource) {
|
||||
// Claim this crate number and cache it
|
||||
let cnum = e.next_crate_num;
|
||||
e.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_owned(),
|
||||
dylib: lib.dylib.clone(),
|
||||
rlib: lib.rlib.clone(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
// Maintain a reference to the top most crate.
|
||||
let root = if root.is_some() { root } else { &crate_paths };
|
||||
|
||||
let cnum_map = resolve_crate_deps(e, root, lib.metadata.as_slice(), span);
|
||||
|
||||
let loader::Library{ dylib, rlib, metadata } = lib;
|
||||
|
||||
let cmeta = Rc::new( cstore::crate_metadata {
|
||||
name: crate_id.name.to_owned(),
|
||||
data: metadata,
|
||||
cnum_map: cnum_map,
|
||||
cnum: cnum,
|
||||
span: span,
|
||||
});
|
||||
|
||||
let source = cstore::CrateSource {
|
||||
dylib: dylib,
|
||||
rlib: rlib,
|
||||
cnum: cnum,
|
||||
};
|
||||
|
||||
e.sess.cstore.set_crate_data(cnum, cmeta.clone());
|
||||
e.sess.cstore.add_used_crate_source(source.clone());
|
||||
(cnum, cmeta, source)
|
||||
}
|
||||
|
||||
fn resolve_crate<'a>(e: &mut Env,
|
||||
root: &Option<CratePaths>,
|
||||
ident: &str,
|
||||
crate_id: &CrateId,
|
||||
hash: Option<&Svh>,
|
||||
should_link: bool,
|
||||
span: Span)
|
||||
root: &Option<CratePaths>,
|
||||
ident: &str,
|
||||
crate_id: &CrateId,
|
||||
hash: Option<&Svh>,
|
||||
span: Span)
|
||||
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
|
||||
cstore::CrateSource) {
|
||||
match existing_match(e, crate_id, hash) {
|
||||
@ -291,64 +330,15 @@ fn resolve_crate<'a>(e: &mut Env,
|
||||
crate_id: crate_id,
|
||||
id_hash: id_hash,
|
||||
hash: hash.map(|a| &*a),
|
||||
os: e.os,
|
||||
intr: e.intr.clone(),
|
||||
filesearch: e.sess.target_filesearch(),
|
||||
os: session::sess_os_to_meta_os(e.sess.targ_cfg.os),
|
||||
triple: e.sess.targ_cfg.target_strs.target_triple.as_slice(),
|
||||
root: root,
|
||||
rejected_via_hash: vec!(),
|
||||
rejected_via_triple: vec!(),
|
||||
};
|
||||
let loader::Library {
|
||||
dylib, rlib, metadata
|
||||
} = load_ctxt.load_library_crate(root);
|
||||
|
||||
// Stash paths for top-most crate locally if necessary.
|
||||
let crate_paths = if root.is_none() {
|
||||
Some(CratePaths {
|
||||
ident: load_ctxt.ident.to_owned(),
|
||||
dylib: dylib.clone(),
|
||||
rlib: rlib.clone(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
// Maintain a reference to the top most crate.
|
||||
let root = if root.is_some() { root } else { &crate_paths };
|
||||
|
||||
// Now resolve the crates referenced by this crate
|
||||
let cnum_map = if should_link {
|
||||
resolve_crate_deps(e, root, metadata.as_slice(), span)
|
||||
} else {
|
||||
HashMap::new()
|
||||
};
|
||||
|
||||
// Claim this crate number and cache it if we're linking to the
|
||||
// crate, otherwise it's a syntax-only crate and we don't need to
|
||||
// reserve a number
|
||||
let cnum = if should_link {
|
||||
let n = e.next_crate_num;
|
||||
e.next_crate_num += 1;
|
||||
n
|
||||
} else {
|
||||
-1
|
||||
};
|
||||
|
||||
let cmeta = Rc::new(cstore::crate_metadata {
|
||||
name: load_ctxt.crate_id.name.to_owned(),
|
||||
data: metadata,
|
||||
cnum_map: cnum_map,
|
||||
cnum: cnum,
|
||||
span: span,
|
||||
});
|
||||
|
||||
let source = cstore::CrateSource {
|
||||
dylib: dylib,
|
||||
rlib: rlib,
|
||||
cnum: cnum,
|
||||
};
|
||||
|
||||
if should_link {
|
||||
e.sess.cstore.set_crate_data(cnum, cmeta.clone());
|
||||
e.sess.cstore.add_used_crate_source(source.clone());
|
||||
}
|
||||
(cnum, cmeta, source)
|
||||
let library = load_ctxt.load_library_crate();
|
||||
register_crate(e, root, ident, crate_id, span, library)
|
||||
}
|
||||
Some(cnum) => (cnum,
|
||||
e.sess.cstore.get_crate_data(cnum),
|
||||
@ -370,7 +360,6 @@ fn resolve_crate_deps(e: &mut Env,
|
||||
dep.crate_id.name.as_slice(),
|
||||
&dep.crate_id,
|
||||
Some(&dep.hash),
|
||||
true,
|
||||
span);
|
||||
(dep.cnum, local_cnum)
|
||||
}).collect()
|
||||
@ -382,14 +371,10 @@ pub struct Loader<'a> {
|
||||
|
||||
impl<'a> Loader<'a> {
|
||||
pub fn new(sess: &'a Session) -> Loader<'a> {
|
||||
let os = driver::get_os(driver::host_triple()).unwrap();
|
||||
let os = session::sess_os_to_meta_os(os);
|
||||
Loader {
|
||||
env: Env {
|
||||
sess: sess,
|
||||
os: os,
|
||||
next_crate_num: sess.cstore.next_crate_num(),
|
||||
intr: token::get_ident_interner(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -398,18 +383,63 @@ impl<'a> Loader<'a> {
|
||||
impl<'a> CrateLoader for Loader<'a> {
|
||||
fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
|
||||
let info = extract_crate_info(&self.env, krate).unwrap();
|
||||
let (_, data, library) = resolve_crate(&mut self.env, &None,
|
||||
info.ident, &info.crate_id,
|
||||
None, info.should_link,
|
||||
krate.span);
|
||||
let macros = decoder::get_exported_macros(&*data);
|
||||
let registrar = decoder::get_macro_registrar_fn(&*data).map(|id| {
|
||||
decoder::get_symbol(data.data.as_slice(), id)
|
||||
let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice();
|
||||
let is_cross = target_triple != driver::host_triple();
|
||||
let mut should_link = info.should_link && !is_cross;
|
||||
let id_hash = link::crate_id_hash(&info.crate_id);
|
||||
let os = driver::get_os(driver::host_triple()).unwrap();
|
||||
let mut load_ctxt = loader::Context {
|
||||
sess: self.env.sess,
|
||||
span: krate.span,
|
||||
ident: info.ident,
|
||||
crate_id: &info.crate_id,
|
||||
id_hash: id_hash,
|
||||
hash: None,
|
||||
filesearch: self.env.sess.host_filesearch(),
|
||||
triple: driver::host_triple(),
|
||||
os: session::sess_os_to_meta_os(os),
|
||||
root: &None,
|
||||
rejected_via_hash: vec!(),
|
||||
rejected_via_triple: vec!(),
|
||||
};
|
||||
let library = match load_ctxt.maybe_load_library_crate() {
|
||||
Some (l) => l,
|
||||
None if is_cross => {
|
||||
// try loading from target crates (only valid if there are
|
||||
// no syntax extensions)
|
||||
load_ctxt.triple = target_triple;
|
||||
load_ctxt.os = session::sess_os_to_meta_os(self.env.sess.targ_cfg.os);
|
||||
load_ctxt.filesearch = self.env.sess.target_filesearch();
|
||||
let lib = load_ctxt.load_library_crate();
|
||||
if decoder::get_macro_registrar_fn(lib.metadata.as_slice()).is_some() {
|
||||
let message = format!("crate `{}` contains a macro_registrar fn but \
|
||||
only a version for triple `{}` could be found (need {})",
|
||||
info.ident, target_triple, driver::host_triple());
|
||||
self.env.sess.span_err(krate.span, message);
|
||||
// need to abort now because the syntax expansion
|
||||
// code will shortly attempt to load and execute
|
||||
// code from the found library.
|
||||
self.env.sess.abort_if_errors();
|
||||
}
|
||||
should_link = info.should_link;
|
||||
lib
|
||||
}
|
||||
None => { load_ctxt.report_load_errs(); unreachable!() },
|
||||
};
|
||||
let macros = decoder::get_exported_macros(library.metadata.as_slice());
|
||||
let registrar = decoder::get_macro_registrar_fn(library.metadata.as_slice()).map(|id| {
|
||||
decoder::get_symbol(library.metadata.as_slice(), id)
|
||||
});
|
||||
MacroCrate {
|
||||
lib: library.dylib,
|
||||
let mc = MacroCrate {
|
||||
lib: library.dylib.clone(),
|
||||
macros: macros.move_iter().collect(),
|
||||
registrar_symbol: registrar,
|
||||
};
|
||||
if should_link {
|
||||
// register crate now to avoid double-reading metadata
|
||||
register_crate(&mut self.env, &None, info.ident.as_slice(),
|
||||
&info.crate_id, krate.span, library);
|
||||
}
|
||||
mc
|
||||
}
|
||||
}
|
||||
|
@ -277,20 +277,6 @@ pub fn get_trait_of_method(cstore: &cstore::CStore,
|
||||
decoder::get_trait_of_method(&*cdata, def_id.node, tcx)
|
||||
}
|
||||
|
||||
pub fn get_macro_registrar_fn(cstore: &cstore::CStore,
|
||||
crate_num: ast::CrateNum)
|
||||
-> Option<ast::NodeId> {
|
||||
let cdata = cstore.get_crate_data(crate_num);
|
||||
decoder::get_macro_registrar_fn(&*cdata)
|
||||
}
|
||||
|
||||
pub fn get_exported_macros(cstore: &cstore::CStore,
|
||||
crate_num: ast::CrateNum)
|
||||
-> Vec<~str> {
|
||||
let cdata = cstore.get_crate_data(crate_num);
|
||||
decoder::get_exported_macros(&*cdata)
|
||||
}
|
||||
|
||||
pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
|
||||
def_id: ast::DefId)
|
||||
-> Option<ast::DefId>
|
||||
|
@ -1126,6 +1126,12 @@ pub fn maybe_get_crate_id(data: &[u8]) -> Option<CrateId> {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn get_crate_triple(data: &[u8]) -> ~str {
|
||||
let cratedoc = reader::Doc(data);
|
||||
let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple);
|
||||
triple_doc.expect("No triple in crate").as_str()
|
||||
}
|
||||
|
||||
pub fn get_crate_id(data: &[u8]) -> CrateId {
|
||||
let cratedoc = reader::Doc(data);
|
||||
let hashdoc = reader::get_doc(cratedoc, tag_crate_crateid);
|
||||
@ -1231,13 +1237,13 @@ pub fn get_native_libraries(cdata: Cmd) -> Vec<(cstore::NativeLibaryKind, ~str)>
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn get_macro_registrar_fn(cdata: Cmd) -> Option<ast::NodeId> {
|
||||
reader::maybe_get_doc(reader::Doc(cdata.data()), tag_macro_registrar_fn)
|
||||
pub fn get_macro_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
|
||||
reader::maybe_get_doc(reader::Doc(data), tag_macro_registrar_fn)
|
||||
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
|
||||
}
|
||||
|
||||
pub fn get_exported_macros(cdata: Cmd) -> Vec<~str> {
|
||||
let macros = reader::get_doc(reader::Doc(cdata.data()),
|
||||
pub fn get_exported_macros(data: &[u8]) -> Vec<~str> {
|
||||
let macros = reader::get_doc(reader::Doc(data),
|
||||
tag_exported_macros);
|
||||
let mut result = Vec::new();
|
||||
reader::tagged_docs(macros, tag_macro_def, |macro_doc| {
|
||||
|
@ -1669,6 +1669,12 @@ fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_crate_triple(ebml_w: &mut Encoder, triple: &str) {
|
||||
ebml_w.start_tag(tag_crate_triple);
|
||||
ebml_w.writer.write(triple.as_bytes());
|
||||
ebml_w.end_tag();
|
||||
}
|
||||
|
||||
// NB: Increment this as you change the metadata encoding version.
|
||||
pub static metadata_encoding_version : &'static [u8] =
|
||||
&[0x72, //'r' as u8,
|
||||
@ -1738,6 +1744,7 @@ fn encode_metadata_inner(wr: &mut MemWriter, parms: EncodeParams, krate: &Crate)
|
||||
let mut ebml_w = writer::Encoder(wr);
|
||||
|
||||
encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
|
||||
encode_crate_triple(&mut ebml_w, tcx.sess.targ_cfg.target_strs.target_triple);
|
||||
encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
|
||||
|
||||
let mut i = ebml_w.writer.tell().unwrap();
|
||||
|
@ -30,7 +30,7 @@ pub type pick<'a> = |path: &Path|: 'a -> FileMatch;
|
||||
pub struct FileSearch<'a> {
|
||||
pub sysroot: &'a Path,
|
||||
pub addl_lib_search_paths: &'a RefCell<HashSet<Path>>,
|
||||
pub target_triple: &'a str
|
||||
pub triple: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> FileSearch<'a> {
|
||||
@ -48,22 +48,23 @@ impl<'a> FileSearch<'a> {
|
||||
visited_dirs.insert(path.as_vec().to_owned());
|
||||
}
|
||||
|
||||
debug!("filesearch: searching target lib path");
|
||||
debug!("filesearch: searching lib path");
|
||||
let tlib_path = make_target_lib_path(self.sysroot,
|
||||
self.target_triple);
|
||||
self.triple);
|
||||
if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
|
||||
match f(&tlib_path) {
|
||||
FileMatches => found = true,
|
||||
FileDoesntMatch => ()
|
||||
}
|
||||
}
|
||||
|
||||
visited_dirs.insert(tlib_path.as_vec().to_owned());
|
||||
// Try RUST_PATH
|
||||
if !found {
|
||||
let rustpath = rust_path();
|
||||
for path in rustpath.iter() {
|
||||
let tlib_path = make_rustpkg_target_lib_path(
|
||||
self.sysroot, path, self.target_triple);
|
||||
let tlib_path = make_rustpkg_lib_path(
|
||||
self.sysroot, path, self.triple);
|
||||
debug!("is {} in visited_dirs? {:?}", tlib_path.display(),
|
||||
visited_dirs.contains_equiv(&tlib_path.as_vec().to_owned()));
|
||||
|
||||
@ -82,8 +83,8 @@ impl<'a> FileSearch<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_target_lib_path(&self) -> Path {
|
||||
make_target_lib_path(self.sysroot, self.target_triple)
|
||||
pub fn get_lib_path(&self) -> Path {
|
||||
make_target_lib_path(self.sysroot, self.triple)
|
||||
}
|
||||
|
||||
pub fn search(&self, pick: pick) {
|
||||
@ -122,13 +123,13 @@ impl<'a> FileSearch<'a> {
|
||||
}
|
||||
|
||||
pub fn new(sysroot: &'a Path,
|
||||
target_triple: &'a str,
|
||||
triple: &'a str,
|
||||
addl_lib_search_paths: &'a RefCell<HashSet<Path>>) -> FileSearch<'a> {
|
||||
debug!("using sysroot = {}", sysroot.display());
|
||||
debug!("using sysroot = {}, triple = {}", sysroot.display(), triple);
|
||||
FileSearch {
|
||||
sysroot: sysroot,
|
||||
addl_lib_search_paths: addl_lib_search_paths,
|
||||
target_triple: target_triple
|
||||
triple: triple,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -147,11 +148,11 @@ fn make_target_lib_path(sysroot: &Path,
|
||||
sysroot.join(&relative_target_lib_path(sysroot, target_triple))
|
||||
}
|
||||
|
||||
fn make_rustpkg_target_lib_path(sysroot: &Path,
|
||||
dir: &Path,
|
||||
target_triple: &str) -> Path {
|
||||
fn make_rustpkg_lib_path(sysroot: &Path,
|
||||
dir: &Path,
|
||||
triple: &str) -> Path {
|
||||
let mut p = dir.join(find_libdir(sysroot));
|
||||
p.push(target_triple);
|
||||
p.push(triple);
|
||||
p
|
||||
}
|
||||
|
||||
|
@ -17,10 +17,9 @@ use lib::llvm::{False, llvm, ObjectFile, mk_section_iter};
|
||||
use metadata::cstore::{MetadataBlob, MetadataVec, MetadataArchive};
|
||||
use metadata::decoder;
|
||||
use metadata::encoder;
|
||||
use metadata::filesearch::{FileMatches, FileDoesntMatch};
|
||||
use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
|
||||
use syntax::codemap::Span;
|
||||
use syntax::diagnostic::SpanHandler;
|
||||
use syntax::parse::token::IdentInterner;
|
||||
use syntax::crateid::CrateId;
|
||||
use syntax::attr::AttrMetaMethods;
|
||||
|
||||
@ -30,7 +29,6 @@ use std::cmp;
|
||||
use std::io;
|
||||
use std::os::consts::{macos, freebsd, linux, android, win32};
|
||||
use std::ptr;
|
||||
use std::rc::Rc;
|
||||
use std::slice;
|
||||
use std::str;
|
||||
|
||||
@ -46,8 +44,9 @@ pub enum Os {
|
||||
OsFreebsd
|
||||
}
|
||||
|
||||
pub struct HashMismatch {
|
||||
pub struct CrateMismatch {
|
||||
path: Path,
|
||||
got: ~str,
|
||||
}
|
||||
|
||||
pub struct Context<'a> {
|
||||
@ -57,9 +56,12 @@ pub struct Context<'a> {
|
||||
pub crate_id: &'a CrateId,
|
||||
pub id_hash: &'a str,
|
||||
pub hash: Option<&'a Svh>,
|
||||
pub triple: &'a str,
|
||||
pub os: Os,
|
||||
pub intr: Rc<IdentInterner>,
|
||||
pub rejected_via_hash: Vec<HashMismatch>
|
||||
pub filesearch: FileSearch<'a>,
|
||||
pub root: &'a Option<CratePaths>,
|
||||
pub rejected_via_hash: Vec<CrateMismatch>,
|
||||
pub rejected_via_triple: Vec<CrateMismatch>,
|
||||
}
|
||||
|
||||
pub struct Library {
|
||||
@ -104,52 +106,69 @@ fn realpath(p: &Path) -> Path {
|
||||
}
|
||||
|
||||
impl<'a> Context<'a> {
|
||||
pub fn load_library_crate(&mut self, root: &Option<CratePaths>) -> Library {
|
||||
pub fn maybe_load_library_crate(&mut self) -> Option<Library> {
|
||||
self.find_library_crate()
|
||||
}
|
||||
|
||||
pub fn load_library_crate(&mut self) -> Library {
|
||||
match self.find_library_crate() {
|
||||
Some(t) => t,
|
||||
None => {
|
||||
self.sess.abort_if_errors();
|
||||
let message = if self.rejected_via_hash.len() > 0 {
|
||||
format!("found possibly newer version of crate `{}`",
|
||||
self.ident)
|
||||
} else {
|
||||
format!("can't find crate for `{}`", self.ident)
|
||||
};
|
||||
let message = match root {
|
||||
&None => message,
|
||||
&Some(ref r) => format!("{} which `{}` depends on",
|
||||
message, r.ident)
|
||||
};
|
||||
self.sess.span_err(self.span, message);
|
||||
|
||||
if self.rejected_via_hash.len() > 0 {
|
||||
self.sess.span_note(self.span, "perhaps this crate needs \
|
||||
to be recompiled?");
|
||||
let mismatches = self.rejected_via_hash.iter();
|
||||
for (i, &HashMismatch{ ref path }) in mismatches.enumerate() {
|
||||
self.sess.fileline_note(self.span,
|
||||
format!("crate `{}` path \\#{}: {}",
|
||||
self.ident, i+1, path.display()));
|
||||
}
|
||||
match root {
|
||||
&None => {}
|
||||
&Some(ref r) => {
|
||||
for (i, path) in r.paths().iter().enumerate() {
|
||||
self.sess.fileline_note(self.span,
|
||||
format!("crate `{}` path \\#{}: {}",
|
||||
r.ident, i+1, path.display()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.sess.abort_if_errors();
|
||||
self.report_load_errs();
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn report_load_errs(&mut self) {
|
||||
let message = if self.rejected_via_hash.len() > 0 {
|
||||
format!("found possibly newer version of crate `{}`",
|
||||
self.ident)
|
||||
} else if self.rejected_via_triple.len() > 0 {
|
||||
format!("found incorrect triple for crate `{}`", self.ident)
|
||||
} else {
|
||||
format!("can't find crate for `{}`", self.ident)
|
||||
};
|
||||
let message = match self.root {
|
||||
&None => message,
|
||||
&Some(ref r) => format!("{} which `{}` depends on",
|
||||
message, r.ident)
|
||||
};
|
||||
self.sess.span_err(self.span, message);
|
||||
|
||||
let mismatches = self.rejected_via_triple.iter();
|
||||
if self.rejected_via_triple.len() > 0 {
|
||||
self.sess.span_note(self.span, format!("expected triple of {}", self.triple));
|
||||
for (i, &CrateMismatch{ ref path, ref got }) in mismatches.enumerate() {
|
||||
self.sess.fileline_note(self.span,
|
||||
format!("crate `{}` path \\#{}, triple {}: {}",
|
||||
self.ident, i+1, got, path.display()));
|
||||
}
|
||||
}
|
||||
if self.rejected_via_hash.len() > 0 {
|
||||
self.sess.span_note(self.span, "perhaps this crate needs \
|
||||
to be recompiled?");
|
||||
let mismatches = self.rejected_via_hash.iter();
|
||||
for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
|
||||
self.sess.fileline_note(self.span,
|
||||
format!("crate `{}` path \\#{}: {}",
|
||||
self.ident, i+1, path.display()));
|
||||
}
|
||||
match self.root {
|
||||
&None => {}
|
||||
&Some(ref r) => {
|
||||
for (i, path) in r.paths().iter().enumerate() {
|
||||
self.sess.fileline_note(self.span,
|
||||
format!("crate `{}` path \\#{}: {}",
|
||||
r.ident, i+1, path.display()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.sess.abort_if_errors();
|
||||
}
|
||||
|
||||
fn find_library_crate(&mut self) -> Option<Library> {
|
||||
let filesearch = self.sess.filesearch();
|
||||
let (dyprefix, dysuffix) = self.dylibname();
|
||||
|
||||
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
|
||||
@ -171,11 +190,12 @@ impl<'a> Context<'a> {
|
||||
// of the crate id (path/name/id).
|
||||
//
|
||||
// The goal of this step is to look at as little metadata as possible.
|
||||
filesearch.search(|path| {
|
||||
self.filesearch.search(|path| {
|
||||
let file = match path.filename_str() {
|
||||
None => return FileDoesntMatch,
|
||||
Some(file) => file,
|
||||
};
|
||||
info!("file: {}", file);
|
||||
if file.starts_with(rlib_prefix) && file.ends_with(".rlib") {
|
||||
info!("rlib candidate: {}", path.display());
|
||||
match self.try_match(file, rlib_prefix, ".rlib") {
|
||||
@ -376,16 +396,30 @@ impl<'a> Context<'a> {
|
||||
fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
|
||||
match decoder::maybe_get_crate_id(crate_data) {
|
||||
Some(ref id) if self.crate_id.matches(id) => {}
|
||||
_ => return false
|
||||
_ => { info!("Rejecting via crate_id"); return false }
|
||||
}
|
||||
let hash = match decoder::maybe_get_crate_hash(crate_data) {
|
||||
Some(hash) => hash, None => return false
|
||||
Some(hash) => hash, None => {
|
||||
info!("Rejecting via lack of crate hash");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
let triple = decoder::get_crate_triple(crate_data);
|
||||
if triple.as_slice() != self.triple {
|
||||
info!("Rejecting via crate triple: expected {} got {}", self.triple, triple);
|
||||
self.rejected_via_triple.push(CrateMismatch{ path: libpath.clone(),
|
||||
got: triple.to_owned() });
|
||||
return false;
|
||||
}
|
||||
|
||||
match self.hash {
|
||||
None => true,
|
||||
Some(myhash) => {
|
||||
if *myhash != hash {
|
||||
self.rejected_via_hash.push(HashMismatch{ path: libpath.clone() });
|
||||
info!("Rejecting via hash: expected {} got {}", *myhash, hash);
|
||||
self.rejected_via_hash.push(CrateMismatch{ path: libpath.clone(),
|
||||
got: myhash.as_str().to_owned() });
|
||||
false
|
||||
} else {
|
||||
true
|
||||
@ -394,6 +428,7 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Returns the corresponding (prefix, suffix) that files need to have for
|
||||
// dynamic libraries
|
||||
fn dylibname(&self) -> (&'static str, &'static str) {
|
||||
@ -405,6 +440,7 @@ impl<'a> Context<'a> {
|
||||
OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) {
|
||||
|
@ -11,7 +11,6 @@
|
||||
// aux-build:macro_crate_test.rs
|
||||
// ignore-stage1
|
||||
// ignore-android
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
// aux-build:macro_crate_test.rs
|
||||
// ignore-stage1
|
||||
// ignore-android
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -12,8 +12,6 @@
|
||||
// aux-build:issue-13560-2.rs
|
||||
// aux-build:issue-13560-3.rs
|
||||
// ignore-stage1
|
||||
// ignore-android
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
// Regression test for issue #13560, the test itself is all in the dependent
|
||||
// libraries. The fail which previously failed to compile is the one numbered 3.
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
// aux-build:macro_crate_outlive_expansion_phase.rs
|
||||
// ignore-stage1
|
||||
// ignore-android
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
// aux-build:macro_crate_test.rs
|
||||
// ignore-stage1
|
||||
// ignore-android
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,17 +10,10 @@
|
||||
|
||||
// aux-build:macro_crate_test.rs
|
||||
// ignore-stage1
|
||||
// ignore-android
|
||||
// force-host
|
||||
|
||||
// You'll note that there's lots of directives above. This is a very particular
|
||||
// test in which we're both linking to a macro crate and loading macros from it.
|
||||
// This implies that both versions are the host architecture, meaning this test
|
||||
// must also be compiled with the host arch.
|
||||
// ignore-cross-compile
|
||||
//
|
||||
// because this doesn't work with that test runner, ignore-android because it
|
||||
// can't run host binaries, and force-host to make this test build as the host
|
||||
// arch.
|
||||
// macro_crate_test will not compile on a cross-compiled target because
|
||||
// libsyntax is not compiled for it.
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
#[phase(syntax)]
|
||||
|
Loading…
Reference in New Issue
Block a user