]> git.lizzy.rs Git - rust.git/commitdiff
Enable use of syntax extensions when cross compiling.
authorDouglas Young <rcxdude@gmail.com>
Thu, 17 Apr 2014 15:52:25 +0000 (16:52 +0100)
committerDouglas Young <rcxdude@gmail.com>
Wed, 23 Apr 2014 19:33:54 +0000 (20:33 +0100)
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.

28 files changed:
mk/tests.mk
src/librustc/back/archive.rs
src/librustc/back/link.rs
src/librustc/back/rpath.rs
src/librustc/driver/driver.rs
src/librustc/driver/session.rs
src/librustc/metadata/common.rs
src/librustc/metadata/creader.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/metadata/loader.rs
src/test/compile-fail/macro-crate-unexported-macro.rs
src/test/compile-fail/phase-syntax-doesnt-resolve.rs
src/test/compile-fail/syntax-extension-fourcc-bad-len.rs
src/test/compile-fail/syntax-extension-fourcc-invalid-endian.rs
src/test/compile-fail/syntax-extension-fourcc-non-ascii-str.rs
src/test/compile-fail/syntax-extension-fourcc-non-literal.rs
src/test/compile-fail/syntax-extension-fourcc-unsupported-literal.rs
src/test/compile-fail/syntax-extension-hexfloat-bad-lits.rs
src/test/compile-fail/syntax-extension-hexfloat-bad-types.rs
src/test/run-pass-fulldeps/issue-13560.rs
src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs
src/test/run-pass-fulldeps/macro-crate.rs
src/test/run-pass-fulldeps/phase-syntax-link-does-resolve.rs
src/test/run-pass-fulldeps/syntax-extension-fourcc.rs
src/test/run-pass-fulldeps/syntax-extension-hexfloat.rs

index b14b5a5152776e838622f31048c4e412a6bbb414..9fc1c7390ccd044eb6f79a5083162e87f713175a 100644 (file)
@@ -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)
index 27211c4779f8eeae3fbf10fec092b07423b5b1d1..7ecea29db2ead761e7bf836eae1542daec53a2e7 100644 (file)
@@ -184,7 +184,7 @@ fn find_library(&self, name: &str) -> Path {
         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());
index 9fd3894d7948e831878505f396eaa662c8478c2d..b7842936af3b0ea22a592881aa13d86d6ff6e89f 100644 (file)
@@ -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);
index d7d86e077de5be702acf9b9ec612309c2c6f67bd..ce79bea5cee7d459b908bc9b64190060e43448c8 100644 (file)
@@ -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)| {
index cf0e7e161c1fc3d89110fbe74134f1cffeb01ef4..95ee250e24c1f080eacbc9879419be5490112ec3 100644 (file)
@@ -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
index e23423bcd0b71fa1d7c1d182c7d2936895fd07b4..950e6bd8ee8333621f3437cbff875083ac8a7f1c 100644 (file)
@@ -319,17 +319,25 @@ pub fn no_landing_pads(&self) -> bool {
     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,
index 4a0b3ea0cf6a03c11b2042e42984c60776cbf1d0..7f05b89dc8471e1707b1bb324b48185653dcf352 100644 (file)
@@ -200,6 +200,8 @@ pub fn from_uint(value : uint) -> Option<astencode_tag> {
 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,
index efbfce1b2bb86c197314d96cc6f3219d2d28be02..916d2a6f07ca28f27517651b37989b95e85ce640 100644 (file)
 
 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;
 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 @@ pub fn new(sess: &'a Session) -> 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
     }
 }
index 4ebf4a52e41847fc4cb3bfbd2800a6fb40c02673..77b4871ea8b6f1c1991fe57171134196e72fbf07 100644 (file)
@@ -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>
index 37d9d3417c9f5ef397a3d9044b685332252122ff..648a18cc09377937d1ba5b356f214bf960ded61d 100644 (file)
@@ -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| {
index 848fd8d362e12a30851a865175c5555bad978b72..9ce1cebf7384999d9cbe205936523cd4ae6d4e4a 100644 (file)
@@ -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 @@ struct Stats {
     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();
index 9b3dce6147b1a045ecb09ae78ac90f6e41a56605..3e1e4e3f2f73df14670e3cf14b37dcbb8574043b 100644 (file)
@@ -30,7 +30,7 @@ pub enum FileMatch { FileMatches, FileDoesntMatch }
 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 @@ pub fn for_each_lib_search_path(&self, f: |&Path| -> FileMatch) {
             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 @@ pub fn for_each_lib_search_path(&self, f: |&Path| -> FileMatch) {
         }
     }
 
-    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 @@ pub fn search(&self, pick: pick) {
     }
 
     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
 }
 
index bd95ba95c70d9c1ee3cdf85b6335ca331b83fd40..4e6f4e2c96520f00b5fd9a8a3df781fbd8f19bf7 100644 (file)
 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::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.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 \\#{}: {}",
-                                    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()));
-                            }
-                        }
+                                    r.ident, i+1, path.display()));
                     }
                 }
-                self.sess.abort_if_errors();
-                unreachable!()
             }
         }
+        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 @@ fn find_library_crate(&mut self) -> Option<Library> {
         // 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 @@ fn extract_one(&mut self, m: HashSet<Path>, flavor: &str,
     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 @@ fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
         }
     }
 
+
     // Returns the corresponding (prefix, suffix) that files need to have for
     // dynamic libraries
     fn dylibname(&self) -> (&'static str, &'static str) {
@@ -405,6 +440,7 @@ fn dylibname(&self) -> (&'static str, &'static str) {
             OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
         }
     }
+
 }
 
 pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) {
index 6f4c450940e0f5b47947b87f138383acd6bd3612..f8eb9868a5b69413047261f344dfd11aeb957be9 100644 (file)
@@ -11,7 +11,6 @@
 // aux-build:macro_crate_test.rs
 // ignore-stage1
 // ignore-android
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index 9bfc7fc34bb5b25408a99de50822b53b25afdb89..2053f81683d7a3d50582dc9276c74da5cbd5766d 100644 (file)
@@ -11,7 +11,6 @@
 // aux-build:macro_crate_test.rs
 // ignore-stage1
 // ignore-android
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index 865ab7e6e84b68468e9a41f16b6a151a4a76a491..fbcdf55f1acbfca0380ef9f9861feaf62fda58e3 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-stage1
 // ignore-pretty
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index c127035bf1e45fb020e471c11223d61d0889c8c2..569b54b93fb097f346853b3e4839b7efd4dfbfc9 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-stage1
 // ignore-pretty
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index 28b146635f1458366be64fbf7983372f3c7596ba..c0e2304354cc478d74260c3a32fb9c5054bbbef5 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-stage1
 // ignore-pretty
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index 1f1a7ab80f96679958f609b99a4b4452bd13ed68..536594f3063111ce1c0345418322999de5bbd8b6 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-stage1
 // ignore-pretty
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index a745c227fb14dcc4ef8ccb4b43f689865cb5d8bf..8a0b0856d24de8897e0b03b22d7ffd615c5c41e1 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-stage1
 // ignore-pretty
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index 04b34c85b78f7959c19dfc7bebe92f16726ad7e8..1cd4f654d2e37106192cca90b5fd161cabcdcccd 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-stage1
 // ignore-pretty
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index 6b2f8067ccc44324df22e3027a2f959e7ee72721..4a6475cea96722b2998d4a7bb4120d1b3952da9b 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-stage1
 // ignore-pretty
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index 24010c7c8b18cec8e241f4ba63904159a2f91d0f..d72c82852dd72cc50f04600f041bed0b77171982 100644 (file)
@@ -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.
index f61cddace825d7613834e94f6744934294a96c85..58663bb44c7440efac69ba493d6155b520240a29 100644 (file)
@@ -10,8 +10,6 @@
 
 // aux-build:macro_crate_outlive_expansion_phase.rs
 // ignore-stage1
-// ignore-android
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index 24d416a416c1e34d24b6f247714329adae3a2cdd..0c086ae99f74ebe9f140be7e66062566f8c14776 100644 (file)
@@ -10,8 +10,6 @@
 
 // aux-build:macro_crate_test.rs
 // ignore-stage1
-// ignore-android
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 
index 1700ceaec4ffe6eaea982aa37c9edc16df043d59..b8d3ab2383100010a96a9f97a6426885838c74e0 100644 (file)
 
 // 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)]
 
index 53ea4fbe0c35d08f263c3b2c44c48d985e0e6f45..0681ec63b9ed08c7ac61964ef6964ee490919db2 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-stage1
 // ignore-pretty
-// ignore-cross-compile
 
 #![feature(phase)]
 
index 5eb6a30c015623f4c81a93d3980252b467e5cf5e..3601b6101159890dd577389652af4372d693fd5b 100644 (file)
@@ -10,7 +10,6 @@
 
 // ignore-stage1
 // ignore-pretty
-// ignore-cross-compile #12102
 
 #![feature(phase)]
 #[phase(syntax)]