From 4ac89cd27613ffe574a6fc6009793c1900e5cfca Mon Sep 17 00:00:00 2001 From: Douglas Young Date: Thu, 17 Apr 2014 16:52:25 +0100 Subject: [PATCH] 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. --- mk/tests.mk | 4 +- src/librustc/back/archive.rs | 2 +- src/librustc/back/link.rs | 2 +- src/librustc/back/rpath.rs | 2 +- src/librustc/driver/driver.rs | 10 +- src/librustc/driver/session.rs | 20 +- src/librustc/metadata/common.rs | 2 + src/librustc/metadata/creader.rs | 206 ++++++++++-------- src/librustc/metadata/csearch.rs | 14 -- src/librustc/metadata/decoder.rs | 14 +- src/librustc/metadata/encoder.rs | 7 + src/librustc/metadata/filesearch.rs | 29 +-- src/librustc/metadata/loader.rs | 130 +++++++---- .../macro-crate-unexported-macro.rs | 1 - .../phase-syntax-doesnt-resolve.rs | 1 - .../syntax-extension-fourcc-bad-len.rs | 1 - .../syntax-extension-fourcc-invalid-endian.rs | 1 - .../syntax-extension-fourcc-non-ascii-str.rs | 1 - .../syntax-extension-fourcc-non-literal.rs | 1 - ...ax-extension-fourcc-unsupported-literal.rs | 1 - .../syntax-extension-hexfloat-bad-lits.rs | 1 - .../syntax-extension-hexfloat-bad-types.rs | 1 - src/test/run-pass-fulldeps/issue-13560.rs | 2 - .../macro-crate-outlive-expansion-phase.rs | 2 - src/test/run-pass-fulldeps/macro-crate.rs | 2 - .../phase-syntax-link-does-resolve.rs | 13 +- .../syntax-extension-fourcc.rs | 1 - .../syntax-extension-hexfloat.rs | 1 - 28 files changed, 260 insertions(+), 212 deletions(-) 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)]