auto merge of #13584 : rcxdude/rust/cross-syntax-ext, r=alexcrichton

This allows the use of syntax extensions when cross-compiling (fixing #12102). It does this by encoding the target triple in the crate metadata and checking it when searching for files. Currently the crate triple must match the host triple when there is a macro_registrar_fn, it must match the target triple when linking, and can match either when only macro_rules! macros are used.

due to carelessness, this is pretty much a duplicate of https://github.com/mozilla/rust/pull/13450.
This commit is contained in:
bors 2014-04-23 13:11:37 -07:00
commit 07aef98a32
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
# 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)

View file

@ -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());

View 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);

View 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)| {

View 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

View file

@ -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,

View file

@ -201,6 +201,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,

View file

@ -14,13 +14,12 @@
use back::link;
use back::svh::Svh;
use driver::{driver, session};
use driver::session::Session;
use driver::{driver, session};
use metadata::cstore;
use metadata::cstore::CStore;
use metadata::decoder;
use metadata::loader;
use metadata::loader::Os;
use metadata::loader::CratePaths;
use std::rc::Rc;
@ -32,29 +31,23 @@ use syntax::attr::AttrMetaMethods;
use syntax::codemap::{Span};
use syntax::diagnostic::SpanHandler;
use syntax::ext::base::{CrateLoader, MacroCrate};
use syntax::parse::token::{IdentInterner, InternedString};
use syntax::parse::token::InternedString;
use syntax::parse::token;
use syntax::crateid::CrateId;
use syntax::visit;
struct Env<'a> {
sess: &'a Session,
os: loader::Os,
next_crate_num: ast::CrateNum,
intr: Rc<IdentInterner>
}
// Traverses an AST, reading all the information about use'd crates and extern
// libraries necessary for later resolving, typechecking, linking, etc.
pub fn read_crates(sess: &Session,
krate: &ast::Crate,
os: loader::Os,
intr: Rc<IdentInterner>) {
krate: &ast::Crate) {
let mut e = Env {
sess: sess,
os: os,
next_crate_num: sess.cstore.next_crate_num(),
intr: intr
};
visit_crate(&e, krate);
visit::walk_crate(&mut e, krate, ());
@ -84,7 +77,6 @@ fn dump_crates(cstore: &CStore) {
fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
let mut map = HashMap::new();
cstore.iter_crate_data(|cnum, data| {
let crateid = data.crate_id();
let key = (crateid.name.clone(), crateid.path.clone());
@ -129,7 +121,7 @@ fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
match extract_crate_info(e, i) {
Some(info) => {
let (cnum, _, _) = resolve_crate(e, &None, info.ident,
&info.crate_id, None, true,
&info.crate_id, None,
i.span);
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
}
@ -272,13 +264,60 @@ fn existing_match(e: &Env, crate_id: &CrateId,
return ret;
}
fn register_crate<'a>(e: &mut Env,
root: &Option<CratePaths>,
ident: &str,
crate_id: &CrateId,
span: Span,
lib: loader::Library)
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
cstore::CrateSource) {
// Claim this crate number and cache it
let cnum = e.next_crate_num;
e.next_crate_num += 1;
// Stash paths for top-most crate locally if necessary.
let crate_paths = if root.is_none() {
Some(CratePaths {
ident: ident.to_owned(),
dylib: lib.dylib.clone(),
rlib: lib.rlib.clone(),
})
} else {
None
};
// Maintain a reference to the top most crate.
let root = if root.is_some() { root } else { &crate_paths };
let cnum_map = resolve_crate_deps(e, root, lib.metadata.as_slice(), span);
let loader::Library{ dylib, rlib, metadata } = lib;
let cmeta = Rc::new( cstore::crate_metadata {
name: crate_id.name.to_owned(),
data: metadata,
cnum_map: cnum_map,
cnum: cnum,
span: span,
});
let source = cstore::CrateSource {
dylib: dylib,
rlib: rlib,
cnum: cnum,
};
e.sess.cstore.set_crate_data(cnum, cmeta.clone());
e.sess.cstore.add_used_crate_source(source.clone());
(cnum, cmeta, source)
}
fn resolve_crate<'a>(e: &mut Env,
root: &Option<CratePaths>,
ident: &str,
crate_id: &CrateId,
hash: Option<&Svh>,
should_link: bool,
span: Span)
root: &Option<CratePaths>,
ident: &str,
crate_id: &CrateId,
hash: Option<&Svh>,
span: Span)
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
cstore::CrateSource) {
match existing_match(e, crate_id, hash) {
@ -291,64 +330,15 @@ fn resolve_crate<'a>(e: &mut Env,
crate_id: crate_id,
id_hash: id_hash,
hash: hash.map(|a| &*a),
os: e.os,
intr: e.intr.clone(),
filesearch: e.sess.target_filesearch(),
os: session::sess_os_to_meta_os(e.sess.targ_cfg.os),
triple: e.sess.targ_cfg.target_strs.target_triple.as_slice(),
root: root,
rejected_via_hash: vec!(),
rejected_via_triple: vec!(),
};
let loader::Library {
dylib, rlib, metadata
} = load_ctxt.load_library_crate(root);
// Stash paths for top-most crate locally if necessary.
let crate_paths = if root.is_none() {
Some(CratePaths {
ident: load_ctxt.ident.to_owned(),
dylib: dylib.clone(),
rlib: rlib.clone(),
})
} else {
None
};
// Maintain a reference to the top most crate.
let root = if root.is_some() { root } else { &crate_paths };
// Now resolve the crates referenced by this crate
let cnum_map = if should_link {
resolve_crate_deps(e, root, metadata.as_slice(), span)
} else {
HashMap::new()
};
// Claim this crate number and cache it if we're linking to the
// crate, otherwise it's a syntax-only crate and we don't need to
// reserve a number
let cnum = if should_link {
let n = e.next_crate_num;
e.next_crate_num += 1;
n
} else {
-1
};
let cmeta = Rc::new(cstore::crate_metadata {
name: load_ctxt.crate_id.name.to_owned(),
data: metadata,
cnum_map: cnum_map,
cnum: cnum,
span: span,
});
let source = cstore::CrateSource {
dylib: dylib,
rlib: rlib,
cnum: cnum,
};
if should_link {
e.sess.cstore.set_crate_data(cnum, cmeta.clone());
e.sess.cstore.add_used_crate_source(source.clone());
}
(cnum, cmeta, source)
let library = load_ctxt.load_library_crate();
register_crate(e, root, ident, crate_id, span, library)
}
Some(cnum) => (cnum,
e.sess.cstore.get_crate_data(cnum),
@ -370,7 +360,6 @@ fn resolve_crate_deps(e: &mut Env,
dep.crate_id.name.as_slice(),
&dep.crate_id,
Some(&dep.hash),
true,
span);
(dep.cnum, local_cnum)
}).collect()
@ -382,14 +371,10 @@ pub struct Loader<'a> {
impl<'a> Loader<'a> {
pub fn new(sess: &'a Session) -> Loader<'a> {
let os = driver::get_os(driver::host_triple()).unwrap();
let os = session::sess_os_to_meta_os(os);
Loader {
env: Env {
sess: sess,
os: os,
next_crate_num: sess.cstore.next_crate_num(),
intr: token::get_ident_interner(),
}
}
}
@ -398,18 +383,63 @@ impl<'a> Loader<'a> {
impl<'a> CrateLoader for Loader<'a> {
fn load_crate(&mut self, krate: &ast::ViewItem) -> MacroCrate {
let info = extract_crate_info(&self.env, krate).unwrap();
let (_, data, library) = resolve_crate(&mut self.env, &None,
info.ident, &info.crate_id,
None, info.should_link,
krate.span);
let macros = decoder::get_exported_macros(&*data);
let registrar = decoder::get_macro_registrar_fn(&*data).map(|id| {
decoder::get_symbol(data.data.as_slice(), id)
let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice();
let is_cross = target_triple != driver::host_triple();
let mut should_link = info.should_link && !is_cross;
let id_hash = link::crate_id_hash(&info.crate_id);
let os = driver::get_os(driver::host_triple()).unwrap();
let mut load_ctxt = loader::Context {
sess: self.env.sess,
span: krate.span,
ident: info.ident,
crate_id: &info.crate_id,
id_hash: id_hash,
hash: None,
filesearch: self.env.sess.host_filesearch(),
triple: driver::host_triple(),
os: session::sess_os_to_meta_os(os),
root: &None,
rejected_via_hash: vec!(),
rejected_via_triple: vec!(),
};
let library = match load_ctxt.maybe_load_library_crate() {
Some (l) => l,
None if is_cross => {
// try loading from target crates (only valid if there are
// no syntax extensions)
load_ctxt.triple = target_triple;
load_ctxt.os = session::sess_os_to_meta_os(self.env.sess.targ_cfg.os);
load_ctxt.filesearch = self.env.sess.target_filesearch();
let lib = load_ctxt.load_library_crate();
if decoder::get_macro_registrar_fn(lib.metadata.as_slice()).is_some() {
let message = format!("crate `{}` contains a macro_registrar fn but \
only a version for triple `{}` could be found (need {})",
info.ident, target_triple, driver::host_triple());
self.env.sess.span_err(krate.span, message);
// need to abort now because the syntax expansion
// code will shortly attempt to load and execute
// code from the found library.
self.env.sess.abort_if_errors();
}
should_link = info.should_link;
lib
}
None => { load_ctxt.report_load_errs(); unreachable!() },
};
let macros = decoder::get_exported_macros(library.metadata.as_slice());
let registrar = decoder::get_macro_registrar_fn(library.metadata.as_slice()).map(|id| {
decoder::get_symbol(library.metadata.as_slice(), id)
});
MacroCrate {
lib: library.dylib,
let mc = MacroCrate {
lib: library.dylib.clone(),
macros: macros.move_iter().collect(),
registrar_symbol: registrar,
};
if should_link {
// register crate now to avoid double-reading metadata
register_crate(&mut self.env, &None, info.ident.as_slice(),
&info.crate_id, krate.span, library);
}
mc
}
}

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)
}
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>

View file

@ -1147,6 +1147,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);
@ -1252,13 +1258,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| {

View file

@ -1690,6 +1690,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,
@ -1759,6 +1765,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();

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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.

View file

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

View file

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

View file

@ -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)]

View file

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

View file

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