diff --git a/mk/tests.mk b/mk/tests.mk index b14b5a51527..9fc1c7390cc 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -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) diff --git a/src/librustc/back/archive.rs b/src/librustc/back/archive.rs index 27211c4779f..7ecea29db2e 100644 --- a/src/librustc/back/archive.rs +++ b/src/librustc/back/archive.rs @@ -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()); diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index 9fd3894d794..b7842936af3 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -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); diff --git a/src/librustc/back/rpath.rs b/src/librustc/back/rpath.rs index d7d86e077de..ce79bea5cee 100644 --- a/src/librustc/back/rpath.rs +++ b/src/librustc/back/rpath.rs @@ -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)| { diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index cf0e7e161c1..95ee250e24c 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -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 diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index e23423bcd0b..950e6bd8ee8 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -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, diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 4a0b3ea0cf6..7f05b89dc84 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -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, diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index efbfce1b2bb..916d2a6f07c 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -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 } // 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) { + 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, + ident: &str, + crate_id: &CrateId, + span: Span, + lib: loader::Library) + -> (ast::CrateNum, Rc, + 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, - ident: &str, - crate_id: &CrateId, - hash: Option<&Svh>, - should_link: bool, - span: Span) + root: &Option, + ident: &str, + crate_id: &CrateId, + hash: Option<&Svh>, + span: Span) -> (ast::CrateNum, Rc, 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 } } diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index 4ebf4a52e41..77b4871ea8b 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -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 { - 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 diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 37d9d3417c9..648a18cc093 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -1126,6 +1126,12 @@ pub fn maybe_get_crate_id(data: &[u8]) -> Option { }) } +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 { - reader::maybe_get_doc(reader::Doc(cdata.data()), tag_macro_registrar_fn) +pub fn get_macro_registrar_fn(data: &[u8]) -> Option { + 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| { diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 848fd8d362e..9ce1cebf738 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -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(); diff --git a/src/librustc/metadata/filesearch.rs b/src/librustc/metadata/filesearch.rs index 9b3dce6147b..3e1e4e3f2f7 100644 --- a/src/librustc/metadata/filesearch.rs +++ b/src/librustc/metadata/filesearch.rs @@ -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>, - 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>) -> 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 } diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index bd95ba95c70..4e6f4e2c965 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -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, - pub rejected_via_hash: Vec + pub filesearch: FileSearch<'a>, + pub root: &'a Option, + pub rejected_via_hash: Vec, + pub rejected_via_triple: Vec, } 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) -> Library { + pub fn maybe_load_library_crate(&mut self) -> Option { + 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 { - 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) { diff --git a/src/test/compile-fail/macro-crate-unexported-macro.rs b/src/test/compile-fail/macro-crate-unexported-macro.rs index 6f4c450940e..f8eb9868a5b 100644 --- a/src/test/compile-fail/macro-crate-unexported-macro.rs +++ b/src/test/compile-fail/macro-crate-unexported-macro.rs @@ -11,7 +11,6 @@ // aux-build:macro_crate_test.rs // ignore-stage1 // ignore-android -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/compile-fail/phase-syntax-doesnt-resolve.rs b/src/test/compile-fail/phase-syntax-doesnt-resolve.rs index 9bfc7fc34bb..2053f81683d 100644 --- a/src/test/compile-fail/phase-syntax-doesnt-resolve.rs +++ b/src/test/compile-fail/phase-syntax-doesnt-resolve.rs @@ -11,7 +11,6 @@ // aux-build:macro_crate_test.rs // ignore-stage1 // ignore-android -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/compile-fail/syntax-extension-fourcc-bad-len.rs b/src/test/compile-fail/syntax-extension-fourcc-bad-len.rs index 865ab7e6e84..fbcdf55f1ac 100644 --- a/src/test/compile-fail/syntax-extension-fourcc-bad-len.rs +++ b/src/test/compile-fail/syntax-extension-fourcc-bad-len.rs @@ -10,7 +10,6 @@ // ignore-stage1 // ignore-pretty -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/compile-fail/syntax-extension-fourcc-invalid-endian.rs b/src/test/compile-fail/syntax-extension-fourcc-invalid-endian.rs index c127035bf1e..569b54b93fb 100644 --- a/src/test/compile-fail/syntax-extension-fourcc-invalid-endian.rs +++ b/src/test/compile-fail/syntax-extension-fourcc-invalid-endian.rs @@ -10,7 +10,6 @@ // ignore-stage1 // ignore-pretty -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/compile-fail/syntax-extension-fourcc-non-ascii-str.rs b/src/test/compile-fail/syntax-extension-fourcc-non-ascii-str.rs index 28b146635f1..c0e2304354c 100644 --- a/src/test/compile-fail/syntax-extension-fourcc-non-ascii-str.rs +++ b/src/test/compile-fail/syntax-extension-fourcc-non-ascii-str.rs @@ -10,7 +10,6 @@ // ignore-stage1 // ignore-pretty -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/compile-fail/syntax-extension-fourcc-non-literal.rs b/src/test/compile-fail/syntax-extension-fourcc-non-literal.rs index 1f1a7ab80f9..536594f3063 100644 --- a/src/test/compile-fail/syntax-extension-fourcc-non-literal.rs +++ b/src/test/compile-fail/syntax-extension-fourcc-non-literal.rs @@ -10,7 +10,6 @@ // ignore-stage1 // ignore-pretty -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/compile-fail/syntax-extension-fourcc-unsupported-literal.rs b/src/test/compile-fail/syntax-extension-fourcc-unsupported-literal.rs index a745c227fb1..8a0b0856d24 100644 --- a/src/test/compile-fail/syntax-extension-fourcc-unsupported-literal.rs +++ b/src/test/compile-fail/syntax-extension-fourcc-unsupported-literal.rs @@ -10,7 +10,6 @@ // ignore-stage1 // ignore-pretty -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/compile-fail/syntax-extension-hexfloat-bad-lits.rs b/src/test/compile-fail/syntax-extension-hexfloat-bad-lits.rs index 04b34c85b78..1cd4f654d2e 100644 --- a/src/test/compile-fail/syntax-extension-hexfloat-bad-lits.rs +++ b/src/test/compile-fail/syntax-extension-hexfloat-bad-lits.rs @@ -10,7 +10,6 @@ // ignore-stage1 // ignore-pretty -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/compile-fail/syntax-extension-hexfloat-bad-types.rs b/src/test/compile-fail/syntax-extension-hexfloat-bad-types.rs index 6b2f8067ccc..4a6475cea96 100644 --- a/src/test/compile-fail/syntax-extension-hexfloat-bad-types.rs +++ b/src/test/compile-fail/syntax-extension-hexfloat-bad-types.rs @@ -10,7 +10,6 @@ // ignore-stage1 // ignore-pretty -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/run-pass-fulldeps/issue-13560.rs b/src/test/run-pass-fulldeps/issue-13560.rs index 24010c7c8b1..d72c82852dd 100644 --- a/src/test/run-pass-fulldeps/issue-13560.rs +++ b/src/test/run-pass-fulldeps/issue-13560.rs @@ -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. diff --git a/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs b/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs index f61cddace82..58663bb44c7 100644 --- a/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs +++ b/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs @@ -10,8 +10,6 @@ // aux-build:macro_crate_outlive_expansion_phase.rs // ignore-stage1 -// ignore-android -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/run-pass-fulldeps/macro-crate.rs b/src/test/run-pass-fulldeps/macro-crate.rs index 24d416a416c..0c086ae99f7 100644 --- a/src/test/run-pass-fulldeps/macro-crate.rs +++ b/src/test/run-pass-fulldeps/macro-crate.rs @@ -10,8 +10,6 @@ // aux-build:macro_crate_test.rs // ignore-stage1 -// ignore-android -// ignore-cross-compile #12102 #![feature(phase)] diff --git a/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs b/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs index 1700ceaec4f..b8d3ab23831 100644 --- a/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs +++ b/src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs @@ -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)] diff --git a/src/test/run-pass-fulldeps/syntax-extension-fourcc.rs b/src/test/run-pass-fulldeps/syntax-extension-fourcc.rs index 53ea4fbe0c3..0681ec63b9e 100644 --- a/src/test/run-pass-fulldeps/syntax-extension-fourcc.rs +++ b/src/test/run-pass-fulldeps/syntax-extension-fourcc.rs @@ -10,7 +10,6 @@ // ignore-stage1 // ignore-pretty -// ignore-cross-compile #![feature(phase)] diff --git a/src/test/run-pass-fulldeps/syntax-extension-hexfloat.rs b/src/test/run-pass-fulldeps/syntax-extension-hexfloat.rs index 5eb6a30c015..3601b610115 100644 --- a/src/test/run-pass-fulldeps/syntax-extension-hexfloat.rs +++ b/src/test/run-pass-fulldeps/syntax-extension-hexfloat.rs @@ -10,7 +10,6 @@ // ignore-stage1 // ignore-pretty -// ignore-cross-compile #12102 #![feature(phase)] #[phase(syntax)]