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:
commit
07aef98a32
@ -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)
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
@ -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)| {
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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| {
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -11,7 +11,6 @@
|
||||
// aux-build:macro_crate_test.rs
|
||||
// ignore-stage1
|
||||
// ignore-android
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
// aux-build:macro_crate_test.rs
|
||||
// ignore-stage1
|
||||
// ignore-android
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -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.
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
// aux-build:macro_crate_outlive_expansion_phase.rs
|
||||
// ignore-stage1
|
||||
// ignore-android
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,8 +10,6 @@
|
||||
|
||||
// aux-build:macro_crate_test.rs
|
||||
// ignore-stage1
|
||||
// ignore-android
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -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)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile
|
||||
|
||||
#![feature(phase)]
|
||||
|
||||
|
@ -10,7 +10,6 @@
|
||||
|
||||
// ignore-stage1
|
||||
// ignore-pretty
|
||||
// ignore-cross-compile #12102
|
||||
|
||||
#![feature(phase)]
|
||||
#[phase(syntax)]
|
||||
|
Loading…
x
Reference in New Issue
Block a user