Enable use of syntax extensions when cross compiling.

This adds the target triple to the crate metadata.
When searching for a crate the phase (link, syntax) is taken into account.
During link phase only crates matching the target triple are considered.
During syntax phase, either the target or host triple will be accepted, unless
the crate defines a macro_registrar, in which case only the host triple will
match.
This commit is contained in:
Douglas Young 2014-04-17 16:52:25 +01:00
parent 09bfb92fdc
commit 4ac89cd276
28 changed files with 260 additions and 212 deletions

View File

@ -526,8 +526,6 @@ endif
# triples). The associated message will be printed as a warning # triples). The associated message will be printed as a warning
# during attempts to run those tests. # during attempts to run those tests.
CTEST_DISABLE_NONSELFHOST_rpass-full = "run-pass-full suite is unavailable when cross-compiling."
define DEF_CTEST_VARS define DEF_CTEST_VARS
# All the per-stage build rules you might want to call from the # 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_TESTARGS)
CTEST_DEPS_rpass_$(1)-T-$(2)-H-$(3) = $$(RPASS_TESTS) 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_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS)
CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS) CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS) CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS)

View File

@ -184,7 +184,7 @@ impl<'a> Archive<'a> {
let unixlibname = format!("lib{}.a", name); let unixlibname = format!("lib{}.a", name);
let mut rustpath = filesearch::rust_path(); 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(); let search = self.sess.opts.addl_lib_search_paths.borrow();
for path in search.iter().chain(rustpath.iter()) { for path in search.iter().chain(rustpath.iter()) {
debug!("looking for {} inside {}", name, path.display()); debug!("looking for {} inside {}", name, path.display());

View File

@ -1088,7 +1088,7 @@ fn link_args(sess: &Session,
// The default library location, we need this to find the runtime. // The default library location, we need this to find the runtime.
// The location of crates will be determined as needed. // The location of crates will be determined as needed.
// FIXME (#9639): This needs to handle non-utf8 paths // 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 stage: ~str = "-L".to_owned() + lib_path.as_str().unwrap();
let mut args = vec!(stage); let mut args = vec!(stage);

View File

@ -40,7 +40,7 @@ pub fn get_rpath_flags(sess: &Session, out_filename: &Path) -> Vec<~str> {
debug!("preparing the RPATH!"); debug!("preparing the RPATH!");
let sysroot = sess.filesearch().sysroot; let sysroot = sess.sysroot();
let output = out_filename; let output = out_filename;
let libs = sess.cstore.get_used_crates(cstore::RequireDynamic); let libs = sess.cstore.get_used_crates(cstore::RequireDynamic);
let libs = libs.move_iter().filter_map(|(_, l)| { let libs = libs.move_iter().filter_map(|(_, l)| {

View File

@ -284,9 +284,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
let time_passes = sess.time_passes(); let time_passes = sess.time_passes();
time(time_passes, "external crate/lib resolution", (), |_| time(time_passes, "external crate/lib resolution", (), |_|
creader::read_crates(&sess, krate, creader::read_crates(&sess, krate));
session::sess_os_to_meta_os(sess.targ_cfg.os),
token::get_ident_interner()));
let lang_items = time(time_passes, "language item collection", (), |_| let lang_items = time(time_passes, "language item collection", (), |_|
middle::lang_items::collect_language_items(krate, &sess)); 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 // 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 // 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 // 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 // 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 // compile time) the target triple that this rustc is built with and
// calling that (at runtime) the host triple. // 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 { 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 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 = { let opt_level = {
if (debugging_opts & session::NO_OPT) != 0 { if (debugging_opts & session::NO_OPT) != 0 {
No No

View File

@ -319,17 +319,25 @@ impl Session {
pub fn show_span(&self) -> bool { pub fn show_span(&self) -> bool {
self.debugging_opt(SHOW_SPAN) self.debugging_opt(SHOW_SPAN)
} }
pub fn filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> { pub fn sysroot<'a>(&'a self) -> &'a Path {
let sysroot = match self.opts.maybe_sysroot { match self.opts.maybe_sysroot {
Some(ref sysroot) => sysroot, Some (ref sysroot) => sysroot,
None => self.default_sysroot.as_ref() None => self.default_sysroot.as_ref()
.expect("missing sysroot and default_sysroot in Session") .expect("missing sysroot and default_sysroot in Session")
}; }
}
pub fn target_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
filesearch::FileSearch::new( filesearch::FileSearch::new(
sysroot, self.sysroot(),
self.opts.target_triple, self.opts.target_triple,
&self.opts.addl_lib_search_paths) &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 /// Some reasonable defaults
@ -343,7 +351,7 @@ pub fn basic_options() -> Options {
output_types: Vec::new(), output_types: Vec::new(),
addl_lib_search_paths: RefCell::new(HashSet::new()), addl_lib_search_paths: RefCell::new(HashSet::new()),
maybe_sysroot: None, maybe_sysroot: None,
target_triple: host_triple(), target_triple: host_triple().to_owned(),
cfg: Vec::new(), cfg: Vec::new(),
test: false, test: false,
parse_only: false, parse_only: false,

View File

@ -200,6 +200,8 @@ pub static tag_macro_registrar_fn: uint = 0x8b;
pub static tag_exported_macros: uint = 0x8c; pub static tag_exported_macros: uint = 0x8c;
pub static tag_macro_def: uint = 0x8d; pub static tag_macro_def: uint = 0x8d;
pub static tag_crate_triple: uint = 0x66;
#[deriving(Clone, Show)] #[deriving(Clone, Show)]
pub struct LinkMeta { pub struct LinkMeta {
pub crateid: CrateId, pub crateid: CrateId,

View File

@ -14,13 +14,12 @@
use back::link; use back::link;
use back::svh::Svh; use back::svh::Svh;
use driver::{driver, session};
use driver::session::Session; use driver::session::Session;
use driver::{driver, session};
use metadata::cstore; use metadata::cstore;
use metadata::cstore::CStore; use metadata::cstore::CStore;
use metadata::decoder; use metadata::decoder;
use metadata::loader; use metadata::loader;
use metadata::loader::Os;
use metadata::loader::CratePaths; use metadata::loader::CratePaths;
use std::rc::Rc; use std::rc::Rc;
@ -32,29 +31,23 @@ use syntax::attr::AttrMetaMethods;
use syntax::codemap::{Span}; use syntax::codemap::{Span};
use syntax::diagnostic::SpanHandler; use syntax::diagnostic::SpanHandler;
use syntax::ext::base::{CrateLoader, MacroCrate}; use syntax::ext::base::{CrateLoader, MacroCrate};
use syntax::parse::token::{IdentInterner, InternedString}; use syntax::parse::token::InternedString;
use syntax::parse::token; use syntax::parse::token;
use syntax::crateid::CrateId; use syntax::crateid::CrateId;
use syntax::visit; use syntax::visit;
struct Env<'a> { struct Env<'a> {
sess: &'a Session, sess: &'a Session,
os: loader::Os,
next_crate_num: ast::CrateNum, next_crate_num: ast::CrateNum,
intr: Rc<IdentInterner>
} }
// Traverses an AST, reading all the information about use'd crates and extern // Traverses an AST, reading all the information about use'd crates and extern
// libraries necessary for later resolving, typechecking, linking, etc. // libraries necessary for later resolving, typechecking, linking, etc.
pub fn read_crates(sess: &Session, pub fn read_crates(sess: &Session,
krate: &ast::Crate, krate: &ast::Crate) {
os: loader::Os,
intr: Rc<IdentInterner>) {
let mut e = Env { let mut e = Env {
sess: sess, sess: sess,
os: os,
next_crate_num: sess.cstore.next_crate_num(), next_crate_num: sess.cstore.next_crate_num(),
intr: intr
}; };
visit_crate(&e, krate); visit_crate(&e, krate);
visit::walk_crate(&mut 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) { fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
let mut map = HashMap::new(); let mut map = HashMap::new();
cstore.iter_crate_data(|cnum, data| { cstore.iter_crate_data(|cnum, data| {
let crateid = data.crate_id(); let crateid = data.crate_id();
let key = (crateid.name.clone(), crateid.path.clone()); 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) { match extract_crate_info(e, i) {
Some(info) => { Some(info) => {
let (cnum, _, _) = resolve_crate(e, &None, info.ident, let (cnum, _, _) = resolve_crate(e, &None, info.ident,
&info.crate_id, None, true, &info.crate_id, None,
i.span); i.span);
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum); 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; 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, fn resolve_crate<'a>(e: &mut Env,
root: &Option<CratePaths>, root: &Option<CratePaths>,
ident: &str, ident: &str,
crate_id: &CrateId, crate_id: &CrateId,
hash: Option<&Svh>, hash: Option<&Svh>,
should_link: bool, span: Span)
span: Span)
-> (ast::CrateNum, Rc<cstore::crate_metadata>, -> (ast::CrateNum, Rc<cstore::crate_metadata>,
cstore::CrateSource) { cstore::CrateSource) {
match existing_match(e, crate_id, hash) { match existing_match(e, crate_id, hash) {
@ -291,64 +330,15 @@ fn resolve_crate<'a>(e: &mut Env,
crate_id: crate_id, crate_id: crate_id,
id_hash: id_hash, id_hash: id_hash,
hash: hash.map(|a| &*a), hash: hash.map(|a| &*a),
os: e.os, filesearch: e.sess.target_filesearch(),
intr: e.intr.clone(), 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_hash: vec!(),
rejected_via_triple: vec!(),
}; };
let loader::Library { let library = load_ctxt.load_library_crate();
dylib, rlib, metadata register_crate(e, root, ident, crate_id, span, library)
} = 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)
} }
Some(cnum) => (cnum, Some(cnum) => (cnum,
e.sess.cstore.get_crate_data(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.name.as_slice(),
&dep.crate_id, &dep.crate_id,
Some(&dep.hash), Some(&dep.hash),
true,
span); span);
(dep.cnum, local_cnum) (dep.cnum, local_cnum)
}).collect() }).collect()
@ -382,14 +371,10 @@ pub struct Loader<'a> {
impl<'a> Loader<'a> { impl<'a> Loader<'a> {
pub fn new(sess: &'a Session) -> 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 { Loader {
env: Env { env: Env {
sess: sess, sess: sess,
os: os,
next_crate_num: sess.cstore.next_crate_num(), 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> { impl<'a> CrateLoader for Loader<'a> {
fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate { fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
let info = extract_crate_info(&self.env, krate).unwrap(); let info = extract_crate_info(&self.env, krate).unwrap();
let (_, data, library) = resolve_crate(&mut self.env, &None, let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice();
info.ident, &info.crate_id, let is_cross = target_triple != driver::host_triple();
None, info.should_link, let mut should_link = info.should_link && !is_cross;
krate.span); let id_hash = link::crate_id_hash(&info.crate_id);
let macros = decoder::get_exported_macros(&*data); let os = driver::get_os(driver::host_triple()).unwrap();
let registrar = decoder::get_macro_registrar_fn(&*data).map(|id| { let mut load_ctxt = loader::Context {
decoder::get_symbol(data.data.as_slice(), id) 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 { let mc = MacroCrate {
lib: library.dylib, lib: library.dylib.clone(),
macros: macros.move_iter().collect(), macros: macros.move_iter().collect(),
registrar_symbol: registrar, 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
} }
} }

View File

@ -277,20 +277,6 @@ pub fn get_trait_of_method(cstore: &cstore::CStore,
decoder::get_trait_of_method(&*cdata, def_id.node, tcx) 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, pub fn get_tuple_struct_definition_if_ctor(cstore: &cstore::CStore,
def_id: ast::DefId) def_id: ast::DefId)
-> Option<ast::DefId> -> Option<ast::DefId>

View 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 { pub fn get_crate_id(data: &[u8]) -> CrateId {
let cratedoc = reader::Doc(data); let cratedoc = reader::Doc(data);
let hashdoc = reader::get_doc(cratedoc, tag_crate_crateid); 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; return result;
} }
pub fn get_macro_registrar_fn(cdata: Cmd) -> Option<ast::NodeId> { pub fn get_macro_registrar_fn(data: &[u8]) -> Option<ast::NodeId> {
reader::maybe_get_doc(reader::Doc(cdata.data()), tag_macro_registrar_fn) reader::maybe_get_doc(reader::Doc(data), tag_macro_registrar_fn)
.map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap()) .map(|doc| FromPrimitive::from_u32(reader::doc_as_u32(doc)).unwrap())
} }
pub fn get_exported_macros(cdata: Cmd) -> Vec<~str> { pub fn get_exported_macros(data: &[u8]) -> Vec<~str> {
let macros = reader::get_doc(reader::Doc(cdata.data()), let macros = reader::get_doc(reader::Doc(data),
tag_exported_macros); tag_exported_macros);
let mut result = Vec::new(); let mut result = Vec::new();
reader::tagged_docs(macros, tag_macro_def, |macro_doc| { reader::tagged_docs(macros, tag_macro_def, |macro_doc| {

View File

@ -1669,6 +1669,12 @@ fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
ebml_w.end_tag(); 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. // NB: Increment this as you change the metadata encoding version.
pub static metadata_encoding_version : &'static [u8] = pub static metadata_encoding_version : &'static [u8] =
&[0x72, //'r' as 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); let mut ebml_w = writer::Encoder(wr);
encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid); 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); encode_hash(&mut ebml_w, &ecx.link_meta.crate_hash);
let mut i = ebml_w.writer.tell().unwrap(); let mut i = ebml_w.writer.tell().unwrap();

View File

@ -30,7 +30,7 @@ pub type pick<'a> = |path: &Path|: 'a -> FileMatch;
pub struct FileSearch<'a> { pub struct FileSearch<'a> {
pub sysroot: &'a Path, pub sysroot: &'a Path,
pub addl_lib_search_paths: &'a RefCell<HashSet<Path>>, pub addl_lib_search_paths: &'a RefCell<HashSet<Path>>,
pub target_triple: &'a str pub triple: &'a str,
} }
impl<'a> FileSearch<'a> { impl<'a> FileSearch<'a> {
@ -48,22 +48,23 @@ impl<'a> FileSearch<'a> {
visited_dirs.insert(path.as_vec().to_owned()); 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, let tlib_path = make_target_lib_path(self.sysroot,
self.target_triple); self.triple);
if !visited_dirs.contains_equiv(&tlib_path.as_vec()) { if !visited_dirs.contains_equiv(&tlib_path.as_vec()) {
match f(&tlib_path) { match f(&tlib_path) {
FileMatches => found = true, FileMatches => found = true,
FileDoesntMatch => () FileDoesntMatch => ()
} }
} }
visited_dirs.insert(tlib_path.as_vec().to_owned()); visited_dirs.insert(tlib_path.as_vec().to_owned());
// Try RUST_PATH // Try RUST_PATH
if !found { if !found {
let rustpath = rust_path(); let rustpath = rust_path();
for path in rustpath.iter() { for path in rustpath.iter() {
let tlib_path = make_rustpkg_target_lib_path( let tlib_path = make_rustpkg_lib_path(
self.sysroot, path, self.target_triple); self.sysroot, path, self.triple);
debug!("is {} in visited_dirs? {:?}", tlib_path.display(), debug!("is {} in visited_dirs? {:?}", tlib_path.display(),
visited_dirs.contains_equiv(&tlib_path.as_vec().to_owned())); 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 { pub fn get_lib_path(&self) -> Path {
make_target_lib_path(self.sysroot, self.target_triple) make_target_lib_path(self.sysroot, self.triple)
} }
pub fn search(&self, pick: pick) { pub fn search(&self, pick: pick) {
@ -122,13 +123,13 @@ impl<'a> FileSearch<'a> {
} }
pub fn new(sysroot: &'a Path, pub fn new(sysroot: &'a Path,
target_triple: &'a str, triple: &'a str,
addl_lib_search_paths: &'a RefCell<HashSet<Path>>) -> FileSearch<'a> { addl_lib_search_paths: &'a RefCell<HashSet<Path>>) -> FileSearch<'a> {
debug!("using sysroot = {}", sysroot.display()); debug!("using sysroot = {}, triple = {}", sysroot.display(), triple);
FileSearch { FileSearch {
sysroot: sysroot, sysroot: sysroot,
addl_lib_search_paths: addl_lib_search_paths, 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)) sysroot.join(&relative_target_lib_path(sysroot, target_triple))
} }
fn make_rustpkg_target_lib_path(sysroot: &Path, fn make_rustpkg_lib_path(sysroot: &Path,
dir: &Path, dir: &Path,
target_triple: &str) -> Path { triple: &str) -> Path {
let mut p = dir.join(find_libdir(sysroot)); let mut p = dir.join(find_libdir(sysroot));
p.push(target_triple); p.push(triple);
p p
} }

View File

@ -17,10 +17,9 @@ use lib::llvm::{False, llvm, ObjectFile, mk_section_iter};
use metadata::cstore::{MetadataBlob, MetadataVec, MetadataArchive}; use metadata::cstore::{MetadataBlob, MetadataVec, MetadataArchive};
use metadata::decoder; use metadata::decoder;
use metadata::encoder; use metadata::encoder;
use metadata::filesearch::{FileMatches, FileDoesntMatch}; use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::diagnostic::SpanHandler; use syntax::diagnostic::SpanHandler;
use syntax::parse::token::IdentInterner;
use syntax::crateid::CrateId; use syntax::crateid::CrateId;
use syntax::attr::AttrMetaMethods; use syntax::attr::AttrMetaMethods;
@ -30,7 +29,6 @@ use std::cmp;
use std::io; use std::io;
use std::os::consts::{macos, freebsd, linux, android, win32}; use std::os::consts::{macos, freebsd, linux, android, win32};
use std::ptr; use std::ptr;
use std::rc::Rc;
use std::slice; use std::slice;
use std::str; use std::str;
@ -46,8 +44,9 @@ pub enum Os {
OsFreebsd OsFreebsd
} }
pub struct HashMismatch { pub struct CrateMismatch {
path: Path, path: Path,
got: ~str,
} }
pub struct Context<'a> { pub struct Context<'a> {
@ -57,9 +56,12 @@ pub struct Context<'a> {
pub crate_id: &'a CrateId, pub crate_id: &'a CrateId,
pub id_hash: &'a str, pub id_hash: &'a str,
pub hash: Option<&'a Svh>, pub hash: Option<&'a Svh>,
pub triple: &'a str,
pub os: Os, pub os: Os,
pub intr: Rc<IdentInterner>, pub filesearch: FileSearch<'a>,
pub rejected_via_hash: Vec<HashMismatch> pub root: &'a Option<CratePaths>,
pub rejected_via_hash: Vec<CrateMismatch>,
pub rejected_via_triple: Vec<CrateMismatch>,
} }
pub struct Library { pub struct Library {
@ -104,52 +106,69 @@ fn realpath(p: &Path) -> Path {
} }
impl<'a> Context<'a> { 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() { match self.find_library_crate() {
Some(t) => t, Some(t) => t,
None => { None => {
self.sess.abort_if_errors(); self.report_load_errs();
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();
unreachable!() unreachable!()
} }
} }
} }
pub fn report_load_errs(&mut self) {
let message = if self.rejected_via_hash.len() > 0 {
format!("found possibly newer version of crate `{}`",
self.ident)
} else if self.rejected_via_triple.len() > 0 {
format!("found incorrect triple for crate `{}`", self.ident)
} else {
format!("can't find crate for `{}`", self.ident)
};
let message = match self.root {
&None => message,
&Some(ref r) => format!("{} which `{}` depends on",
message, r.ident)
};
self.sess.span_err(self.span, message);
let mismatches = self.rejected_via_triple.iter();
if self.rejected_via_triple.len() > 0 {
self.sess.span_note(self.span, format!("expected triple of {}", self.triple));
for (i, &CrateMismatch{ ref path, ref got }) in mismatches.enumerate() {
self.sess.fileline_note(self.span,
format!("crate `{}` path \\#{}, triple {}: {}",
self.ident, i+1, got, path.display()));
}
}
if self.rejected_via_hash.len() > 0 {
self.sess.span_note(self.span, "perhaps this crate needs \
to be recompiled?");
let mismatches = self.rejected_via_hash.iter();
for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
self.sess.fileline_note(self.span,
format!("crate `{}` path \\#{}: {}",
self.ident, i+1, path.display()));
}
match self.root {
&None => {}
&Some(ref r) => {
for (i, path) in r.paths().iter().enumerate() {
self.sess.fileline_note(self.span,
format!("crate `{}` path \\#{}: {}",
r.ident, i+1, path.display()));
}
}
}
}
self.sess.abort_if_errors();
}
fn find_library_crate(&mut self) -> Option<Library> { fn find_library_crate(&mut self) -> Option<Library> {
let filesearch = self.sess.filesearch();
let (dyprefix, dysuffix) = self.dylibname(); let (dyprefix, dysuffix) = self.dylibname();
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-" // 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). // of the crate id (path/name/id).
// //
// The goal of this step is to look at as little metadata as possible. // 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() { let file = match path.filename_str() {
None => return FileDoesntMatch, None => return FileDoesntMatch,
Some(file) => file, Some(file) => file,
}; };
info!("file: {}", file);
if file.starts_with(rlib_prefix) && file.ends_with(".rlib") { if file.starts_with(rlib_prefix) && file.ends_with(".rlib") {
info!("rlib candidate: {}", path.display()); info!("rlib candidate: {}", path.display());
match self.try_match(file, rlib_prefix, ".rlib") { 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 { fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
match decoder::maybe_get_crate_id(crate_data) { match decoder::maybe_get_crate_id(crate_data) {
Some(ref id) if self.crate_id.matches(id) => {} 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) { 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 { match self.hash {
None => true, None => true,
Some(myhash) => { Some(myhash) => {
if *myhash != hash { 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 false
} else { } else {
true true
@ -394,6 +428,7 @@ impl<'a> Context<'a> {
} }
} }
// Returns the corresponding (prefix, suffix) that files need to have for // Returns the corresponding (prefix, suffix) that files need to have for
// dynamic libraries // dynamic libraries
fn dylibname(&self) -> (&'static str, &'static str) { fn dylibname(&self) -> (&'static str, &'static str) {
@ -405,6 +440,7 @@ impl<'a> Context<'a> {
OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX), OsFreebsd => (freebsd::DLL_PREFIX, freebsd::DLL_SUFFIX),
} }
} }
} }
pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) { pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) {

View File

@ -11,7 +11,6 @@
// aux-build:macro_crate_test.rs // aux-build:macro_crate_test.rs
// ignore-stage1 // ignore-stage1
// ignore-android // ignore-android
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -11,7 +11,6 @@
// aux-build:macro_crate_test.rs // aux-build:macro_crate_test.rs
// ignore-stage1 // ignore-stage1
// ignore-android // ignore-android
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -10,7 +10,6 @@
// ignore-stage1 // ignore-stage1
// ignore-pretty // ignore-pretty
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -10,7 +10,6 @@
// ignore-stage1 // ignore-stage1
// ignore-pretty // ignore-pretty
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -10,7 +10,6 @@
// ignore-stage1 // ignore-stage1
// ignore-pretty // ignore-pretty
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -10,7 +10,6 @@
// ignore-stage1 // ignore-stage1
// ignore-pretty // ignore-pretty
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -10,7 +10,6 @@
// ignore-stage1 // ignore-stage1
// ignore-pretty // ignore-pretty
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -10,7 +10,6 @@
// ignore-stage1 // ignore-stage1
// ignore-pretty // ignore-pretty
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -10,7 +10,6 @@
// ignore-stage1 // ignore-stage1
// ignore-pretty // ignore-pretty
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -12,8 +12,6 @@
// aux-build:issue-13560-2.rs // aux-build:issue-13560-2.rs
// aux-build:issue-13560-3.rs // aux-build:issue-13560-3.rs
// ignore-stage1 // ignore-stage1
// ignore-android
// ignore-cross-compile #12102
// Regression test for issue #13560, the test itself is all in the dependent // 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. // libraries. The fail which previously failed to compile is the one numbered 3.

View File

@ -10,8 +10,6 @@
// aux-build:macro_crate_outlive_expansion_phase.rs // aux-build:macro_crate_outlive_expansion_phase.rs
// ignore-stage1 // ignore-stage1
// ignore-android
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -10,8 +10,6 @@
// aux-build:macro_crate_test.rs // aux-build:macro_crate_test.rs
// ignore-stage1 // ignore-stage1
// ignore-android
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]

View File

@ -10,17 +10,10 @@
// aux-build:macro_crate_test.rs // aux-build:macro_crate_test.rs
// ignore-stage1 // ignore-stage1
// ignore-android // ignore-cross-compile
// 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.
// //
// because this doesn't work with that test runner, ignore-android because it // macro_crate_test will not compile on a cross-compiled target because
// can't run host binaries, and force-host to make this test build as the host // libsyntax is not compiled for it.
// arch.
#![feature(phase)] #![feature(phase)]

View File

@ -10,7 +10,6 @@
// ignore-stage1 // ignore-stage1
// ignore-pretty // ignore-pretty
// ignore-cross-compile
#![feature(phase)] #![feature(phase)]

View File

@ -10,7 +10,6 @@
// ignore-stage1 // ignore-stage1
// ignore-pretty // ignore-pretty
// ignore-cross-compile #12102
#![feature(phase)] #![feature(phase)]
#[phase(syntax)] #[phase(syntax)]