pub crate_hash: Svh,
}
-// Where a crate came from on the local filesystem. One of these two options
+// Where a crate came from on the local filesystem. One of these three options
// must be non-None.
#[derive(PartialEq, Clone, Debug)]
pub struct CrateSource {
pub dylib: Option<(PathBuf, PathKind)>,
pub rlib: Option<(PathBuf, PathKind)>,
+ pub rmeta: Option<(PathBuf, PathKind)>,
}
-#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)]
-pub enum DepKind {
- /// A dependency that is only used for its macros.
- MacrosOnly,
- /// A dependency that is always injected into the dependency list and so
- /// doesn't need to be linked to an rlib, e.g. the injected allocator.
- Implicit,
- /// A dependency that is required by an rlib version of this crate.
- /// Ordinary `extern crate`s result in `Explicit` dependencies.
- Explicit,
+#[derive(PartialEq, Clone, Debug)]
+pub enum LibSource {
+ Some(PathBuf),
+ MetadataOnly,
+ None,
+}
+
+impl LibSource {
+ pub fn is_some(&self) -> bool {
+ if let LibSource::Some(_) = *self {
+ true
+ } else {
+ false
+ }
+ }
+
+ pub fn option(&self) -> Option<PathBuf> {
+ match *self {
+ LibSource::Some(ref p) => Some(p.clone()),
+ LibSource::MetadataOnly | LibSource::None => None,
+ }
+ }
}
#[derive(Copy, Debug, PartialEq, Clone, RustcEncodable, RustcDecodable)]
// utility functions
fn metadata_filename(&self) -> &str;
fn metadata_section_name(&self, target: &Target) -> &str;
- fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option<PathBuf>)>;
+ fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>;
fn used_crate_source(&self, cnum: CrateNum) -> CrateSource;
fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum>;
fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
// utility functions
fn metadata_filename(&self) -> &str { bug!("metadata_filename") }
fn metadata_section_name(&self, target: &Target) -> &str { bug!("metadata_section_name") }
- fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option<PathBuf>)>
+ fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
{ vec![] }
fn used_crate_source(&self, cnum: CrateNum) -> CrateSource { bug!("used_crate_source") }
fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> { None }
if src.dylib.is_none() &&
!formats.contains_key(&cnum) &&
sess.cstore.dep_kind(cnum) == DepKind::Explicit {
- assert!(src.rlib.is_some());
+ assert!(src.rlib.is_some() || src.rmeta.is_some());
info!("adding staticlib: {}", sess.cstore.crate_name(cnum));
add_library(sess, cnum, RequireStatic, &mut formats);
ret[cnum.as_usize() - 1] = Linkage::Static;
"serialize work products",
move || rustc_incremental::save_work_products(sess));
- println!("finish phase 5: {}", sess.err_count());
if sess.err_count() > 0 {
Err(sess.err_count())
} else {
pub struct Library {
pub dylib: Option<(PathBuf, PathKind)>,
pub rlib: Option<(PathBuf, PathKind)>,
+ pub rmeta: Option<(PathBuf, PathKind)>,
pub metadata: MetadataBlob,
}
info!(" cnum: {}", data.cnum);
info!(" hash: {}", data.hash());
info!(" reqd: {:?}", data.dep_kind.get());
- let CrateSource { dylib, rlib } = data.source.clone();
+ let CrateSource { dylib, rlib, rmeta } = data.source.clone();
dylib.map(|dl| info!(" dylib: {}", dl.0.display()));
rlib.map(|rl| info!(" rlib: {}", rl.0.display()));
+ rmeta.map(|rl| info!(" rmeta: {}", rl.0.display()));
+ });
})
}
ident: ident.to_string(),
dylib: lib.dylib.clone().map(|p| p.0),
rlib: lib.rlib.clone().map(|p| p.0),
+ rmeta: lib.rmeta.clone().map(|p| p.0),
})
} else {
None
// Maintain a reference to the top most crate.
let root = if root.is_some() { root } else { &crate_paths };
- let Library { dylib, rlib, metadata } = lib;
+ let Library { dylib, rlib, rmeta, metadata } = lib;
let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);
source: cstore::CrateSource {
dylib: dylib,
rlib: rlib,
+ rmeta: rmeta,
},
});
use std::cell::{RefCell, Cell};
use std::rc::Rc;
-use std::path::PathBuf;
use flate::Bytes;
use syntax::{ast, attr};
use syntax::ext::base::SyntaxExtension;
pub use rustc::middle::cstore::{NativeLibrary, LinkagePreference};
pub use rustc::middle::cstore::{NativeStatic, NativeFramework, NativeUnknown};
-pub use rustc::middle::cstore::{CrateSource, LinkMeta};
+pub use rustc::middle::cstore::{CrateSource, LinkMeta, LibSource};
// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
// positions.
pub fn do_get_used_crates(&self,
prefer: LinkagePreference)
- -> Vec<(CrateNum, Option<PathBuf>)> {
+ -> Vec<(CrateNum, LibSource)> {
let mut ordering = Vec::new();
for (&num, _) in self.metas.borrow().iter() {
self.push_dependencies_in_postorder(&mut ordering, num);
LinkagePreference::RequireDynamic => data.source.dylib.clone().map(|p| p.0),
LinkagePreference::RequireStatic => data.source.rlib.clone().map(|p| p.0),
};
+ let path = match path {
+ Some(p) => LibSource::Some(p),
+ None => {
+ if data.rmeta.is_some() {
+ LibSource::MetadataOnly
+ } else {
+ LibSource::None
+ }
+ }
+ };
Some((cnum, path))
})
.collect::<Vec<_>>();
use locator;
use schema;
-use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, DepKind, ExternCrate};
+use rustc::middle::cstore::{InlinedItem, CrateStore, CrateSource, LibSource, DepKind, ExternCrate};
use rustc::middle::cstore::{NativeLibrary, LinkMeta, LinkagePreference, LoadedMacro};
use rustc::hir::def::{self, Def};
use rustc::middle::lang_items;
use rustc::util::nodemap::{NodeSet, DefIdMap};
use rustc_back::PanicStrategy;
-use std::path::PathBuf;
use syntax::ast;
use syntax::attr;
use syntax::parse::{token, new_parser_from_source_str};
locator::meta_section_name(target)
}
- fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, Option<PathBuf>)>
+ fn used_crates(&self, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)>
{
self.do_get_used_crates(prefer)
}
//! is a platform-defined dynamic library. Each library has a metadata somewhere
//! inside of it.
//!
+//! A third kind of dependency is an rmeta file. These are rlibs, which contain
+//! metadata, but no code. To a first approximation, these are treated in the
+//! same way as rlibs. Where there is both an rlib and an rmeta file, the rlib
+//! gets priority (even if the rmeta file is newer). An rmeta file is only
+//! useful for checking a downstream crate, attempting to link one will cause an
+//! error.
+//!
//! When translating a crate name to a crate on the filesystem, we all of a
//! sudden need to take into account both rlibs and dylibs! Linkage later on may
//! use either one of these files, as each has their pros/cons. The job of crate
pub ident: String,
pub dylib: Option<PathBuf>,
pub rlib: Option<PathBuf>,
+ pub rmeta: Option<PathBuf>,
}
pub const METADATA_FILENAME: &'static str = "rust.metadata.bin";
#[derive(Copy, Clone, PartialEq)]
enum CrateFlavor {
Rlib,
+ Rmeta,
Dylib,
}
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(match *self {
CrateFlavor::Rlib => "rlib",
+ CrateFlavor::Rmeta => "rmeta",
CrateFlavor::Dylib => "dylib",
})
}
impl CratePaths {
fn paths(&self) -> Vec<PathBuf> {
- match (&self.dylib, &self.rlib) {
- (&None, &None) => vec![],
- (&Some(ref p), &None) |
- (&None, &Some(ref p)) => vec![p.clone()],
- (&Some(ref p1), &Some(ref p2)) => vec![p1.clone(), p2.clone()],
- }
+ self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).cloned().collect()
}
}
None => return FileDoesntMatch,
Some(file) => file,
};
- let (hash, rlib) = if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rlib") {
- (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], true)
+ let (hash, found_kind) = if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rlib") {
+ (&file[(rlib_prefix.len())..(file.len() - ".rlib".len())], CrateFlavor::Rlib)
+ } else if file.starts_with(&rlib_prefix[..]) && file.ends_with(".rmeta") {
+ (&file[(rlib_prefix.len())..(file.len() - ".rmeta".len())], CrateFlavor::Rmeta)
} else if file.starts_with(&dylib_prefix) &&
file.ends_with(&dypair.1) {
- (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], false)
+ (&file[(dylib_prefix.len())..(file.len() - dypair.1.len())], CrateFlavor::Dylib)
} else {
if file.starts_with(&staticlib_prefix[..]) && file.ends_with(&staticpair.1) {
staticlibs.push(CrateMismatch {
let hash_str = hash.to_string();
let slot = candidates.entry(hash_str)
- .or_insert_with(|| (FxHashMap(), FxHashMap()));
- let (ref mut rlibs, ref mut dylibs) = *slot;
+ .or_insert_with(|| (FxHashMap(), FxHashMap(), FxHashMap()));
+ let (ref mut rlibs, ref mut rmetas, ref mut dylibs) = *slot;
fs::canonicalize(path)
.map(|p| {
- if rlib {
- rlibs.insert(p, kind);
- } else {
- dylibs.insert(p, kind);
+ match found_kind {
+ CrateFlavor::Rlib => { rlibs.insert(p, kind); }
+ CrateFlavor::Rmeta => { rmetas.insert(p, kind); }
+ CrateFlavor::Dylib => { dylibs.insert(p, kind); }
}
FileMatches
})
// libraries corresponds to the crate id and hash criteria that this
// search is being performed for.
let mut libraries = FxHashMap();
- for (_hash, (rlibs, dylibs)) in candidates {
+ for (_hash, (rlibs, rmetas, dylibs)) in candidates {
let mut slot = None;
let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot);
+ let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot);
let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot);
if let Some((h, m)) = slot {
libraries.insert(h,
Library {
dylib: dylib,
rlib: rlib,
+ rmeta: rmeta,
metadata: m,
});
}
let sess = self.sess;
let dylibname = self.dylibname();
let mut rlibs = FxHashMap();
+ let mut rmetas = FxHashMap();
let mut dylibs = FxHashMap();
{
let locs = locs.map(|l| PathBuf::from(l)).filter(|loc| {
for loc in locs {
if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
rlibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
+ } else if loc.file_name().unwrap().to_str().unwrap().ends_with(".rmeta") {
+ rmetas.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
} else {
dylibs.insert(fs::canonicalize(&loc).unwrap(), PathKind::ExternFlag);
}
// Extract the rlib/dylib pair.
let mut slot = None;
let rlib = self.extract_one(rlibs, CrateFlavor::Rlib, &mut slot);
+ let rmeta = self.extract_one(rmetas, CrateFlavor::Rmeta, &mut slot);
let dylib = self.extract_one(dylibs, CrateFlavor::Dylib, &mut slot);
- if rlib.is_none() && dylib.is_none() {
+ if rlib.is_none() && rmeta.is_none() && dylib.is_none() {
return None;
}
match slot {
Some(Library {
dylib: dylib,
rlib: rlib,
+ rmeta: rmeta,
metadata: metadata,
})
}
if !filename.exists() {
return Err(format!("no such file: '{}'", filename.display()));
}
- if flavor == CrateFlavor::Rlib {
+ if flavor == CrateFlavor::Rlib || flavor == CrateFlavor::Rmeta {
// Use ArchiveRO for speed here, it's backed by LLVM and uses mmap
// internally to read the file. We also avoid even using a memcpy by
// just keeping the archive along while the metadata is in use.
let filename = path.file_name().unwrap().to_str().unwrap();
let flavor = if filename.ends_with(".rlib") {
CrateFlavor::Rlib
+ } else if filename.ends_with(".rmeta") {
+ CrateFlavor::Rmeta
} else {
CrateFlavor::Dylib
};
use session::filesearch;
use session::search_paths::PathKind;
use session::Session;
-use middle::cstore::{self, LinkMeta, NativeLibrary};
+use middle::cstore::{self, LinkMeta, NativeLibrary, LibSource};
use middle::cstore::{LinkagePreference, NativeLibraryKind};
use middle::dependency_format::Linkage;
use CrateTranslation;
}
"rust_out".to_string()
-
}
pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap,
.or_else(|| fmts.get(&config::CrateTypeCdylib))
.or_else(|| fmts.get(&config::CrateTypeProcMacro));
let fmts = fmts.unwrap_or_else(|| {
- bug!("could not find formats for rlibs")
+ bug!("could not find formats for rlibs");
});
for (cnum, path) in crates {
match fmts[cnum.as_usize() - 1] {
}
let name = sess.cstore.crate_name(cnum).clone();
let path = match path {
- Some(p) => p,
- None => {
+ LibSource::Some(p) => p,
+ LibSource::MetadataOnly => {
+ sess.fatal(&format!("could not find rlib for: `{}`, found rmeta (metadata) file", name));
+ }
+ LibSource::None => {
sess.fatal(&format!("could not find rlib for: `{}`", name));
}
};
outputs: &OutputFilenames,
crate_name: &str) -> PathBuf {
let objects = object_filenames(trans, outputs);
- println!("objects: {:?}", objects);
let default_filename = filename_for_input(sess, crate_type, crate_name,
outputs);
let out_filename = outputs.outputs.get(&OutputType::Exe)
use std::fs;
use rustc::hir::def_id::CrateNum;
+use rustc::middle::cstore::LibSource;
pub struct RPathConfig<'a> {
- pub used_crates: Vec<(CrateNum, Option<PathBuf>)>,
+ pub used_crates: Vec<(CrateNum, LibSource)>,
pub out_filename: PathBuf,
pub is_like_osx: bool,
pub has_rpath: bool,
debug!("preparing the RPATH!");
let libs = config.used_crates.clone();
- let libs = libs.into_iter().filter_map(|(_, l)| l).collect::<Vec<_>>();
+ let libs = libs.into_iter().filter_map(|(_, l)| l.option()).collect::<Vec<_>>();
let rpaths = get_rpaths(config, &libs[..]);
flags.extend_from_slice(&rpaths_to_flags(&rpaths[..]));
use rustc::dep_graph::{DepNode, WorkProduct};
use rustc::hir::map as hir_map;
use rustc::util::common::time;
-use session::config::{self, NoDebugInfo, OutputType};
+use session::config::{self, NoDebugInfo};
use rustc_incremental::IncrementalHashesMap;
use session::Session;
use abi::{self, Abi, FnType};