Make crate hash stable and externally computable.

This replaces the link meta attributes with a pkgid attribute and uses a hash
of this as the crate hash. This makes the crate hash computable by things
other than the Rust compiler. It also switches the hash function ot SHA1 since
that is much more likely to be available in shell, Python, etc than SipHash.

Fixes #10188, #8523.
This commit is contained in:
Jack Moffitt 2013-12-09 14:56:53 -07:00
parent 29ca4350c8
commit b349036e5f
111 changed files with 1260 additions and 603 deletions

View File

@ -9,15 +9,15 @@
// except according to those terms.
#[cfg(rustpkg)]
extern mod this(name = "rustpkg");
extern mod this = "rustpkg";
#[cfg(rustdoc)]
extern mod this(name = "rustdoc");
extern mod this = "rustdoc";
#[cfg(rustc)]
extern mod this(name = "rustc");
extern mod this = "rustc";
#[cfg(rustdoc_ng)]
extern mod this(name = "rustdoc_ng");
extern mod this = "rustdoc_ng";
fn main() { this::main() }

View File

@ -42,6 +42,7 @@ stage2_tests.sort()
c = open("tmp/run_pass_stage2.rc", "w")
i = 0
c.write("// AUTO-GENERATED FILE: DO NOT EDIT\n")
c.write("#[pkgid=\"run_pass_stage2#0.1\"];\n")
c.write("#[link(name=\"run_pass_stage2\", vers=\"0.1\")];\n")
c.write("#[feature(globs, macro_rules, struct_variant, managed_boxes)];\n")
c.write("#[allow(attribute_usage)];\n")

View File

@ -20,6 +20,8 @@ Rust extras are part of the standard Rust distribution.
*/
#[pkgid="extra#0.9-pre"];
// NOTE: remove after the next snapshot
#[link(name = "extra",
package_id = "extra",
vers = "0.9-pre",

View File

@ -24,11 +24,10 @@ use middle::trans::common::gensym_name;
use middle::ty;
use util::common::time;
use util::ppaux;
use util::sha2::{Digest, Sha256};
use std::c_str::ToCStr;
use std::char;
use std::hash::Streaming;
use std::hash;
use std::os::consts::{macos, freebsd, linux, android, win32};
use std::ptr;
use std::run;
@ -39,8 +38,8 @@ use syntax::abi;
use syntax::ast;
use syntax::ast_map::{path, path_mod, path_name, path_pretty_name};
use syntax::attr;
use syntax::attr::{AttrMetaMethods};
use syntax::print::pprust;
use syntax::attr::AttrMetaMethods;
use syntax::pkgid::PkgId;
#[deriving(Clone, Eq)]
pub enum output_type {
@ -52,10 +51,6 @@ pub enum output_type {
output_type_exe,
}
fn write_string<W:Writer>(writer: &mut W, string: &str) {
writer.write(string.as_bytes());
}
pub fn llvm_err(sess: Session, msg: ~str) -> ! {
unsafe {
let cstr = llvm::LLVMRustGetLastError();
@ -413,7 +408,7 @@ pub mod write {
* - Symbols with the same name but different types need to get different
* linkage-names. We do this by hashing a string-encoding of the type into
* a fixed-size (currently 16-byte hex) cryptographic hash function (CHF:
* we use SHA1) to "prevent collisions". This is not airtight but 16 hex
* we use SHA256) to "prevent collisions". This is not airtight but 16 hex
* digits on uniform probability means you're going to need 2**32 same-name
* symbols in the same process before you're even hitting birthday-paradox
* collision probability.
@ -421,209 +416,82 @@ pub mod write {
* - Symbols in different crates but with same names "within" the crate need
* to get different linkage-names.
*
* - The hash shown in the filename needs to be predictable and stable for
* build tooling integration. It also needs to be using a hash function
* which is easy to use from Python, make, etc.
*
* So here is what we do:
*
* - Separate the meta tags into two sets: exported and local. Only work with
* the exported ones when considering linkage.
* - Consider the package id; every crate has one (specified with pkgid
* attribute). If a package id isn't provided explicitly, we infer a
* versionless one from the output name. The version will end up being 0.0
* in this case. CNAME and CVERS are taken from this package id. For
* example, github.com/mozilla/CNAME#CVERS.
*
* - Consider two exported tags as special (and mandatory): name and vers.
* Every crate gets them; if it doesn't name them explicitly we infer them
* as basename(crate) and "0.1", respectively. Call these CNAME, CVERS.
* - Define CMH as SHA256(pkgid).
*
* - Define CMETA as all the non-name, non-vers exported meta tags in the
* crate (in sorted order).
* - Define CMH8 as the first 8 characters of CMH.
*
* - Define CMH as hash(CMETA + hashes of dependent crates).
* - Compile our crate to lib CNAME-CMH8-CVERS.so
*
* - Compile our crate to lib CNAME-CMH-CVERS.so
*
* - Define STH(sym) as hash(CNAME, CMH, type_str(sym))
* - Define STH(sym) as SHA256(CMH, type_str(sym))
*
* - Suffix a mangled sym with ::STH@CVERS, so that it is unique in the
* name, non-name metadata, and type sense, and versioned in the way
* system linkers understand.
*
*/
pub fn build_link_meta(sess: Session,
c: &ast::Crate,
output: &Path,
symbol_hasher: &mut hash::State)
symbol_hasher: &mut Sha256)
-> LinkMeta {
struct ProvidedMetas {
name: Option<@str>,
vers: Option<@str>,
pkg_id: Option<@str>,
cmh_items: ~[@ast::MetaItem]
}
fn provided_link_metas(sess: Session, c: &ast::Crate) ->
ProvidedMetas {
let mut name = None;
let mut vers = None;
let mut pkg_id = None;
let mut cmh_items = ~[];
let linkage_metas = attr::find_linkage_metas(c.attrs);
attr::require_unique_names(sess.diagnostic(), linkage_metas);
for meta in linkage_metas.iter() {
match meta.name_str_pair() {
Some((n, value)) if "name" == n => name = Some(value),
Some((n, value)) if "vers" == n => vers = Some(value),
Some((n, value)) if "package_id" == n => pkg_id = Some(value),
_ => cmh_items.push(*meta)
}
}
ProvidedMetas {
name: name,
vers: vers,
pkg_id: pkg_id,
cmh_items: cmh_items
}
}
// This calculates CMH as defined above
fn crate_meta_extras_hash(symbol_hasher: &mut hash::State,
cmh_items: ~[@ast::MetaItem],
dep_hashes: ~[@str],
pkg_id: Option<@str>) -> @str {
fn len_and_str(s: &str) -> ~str {
format!("{}_{}", s.len(), s)
}
fn len_and_str_lit(l: ast::lit) -> ~str {
len_and_str(pprust::lit_to_str(&l))
}
let cmh_items = attr::sort_meta_items(cmh_items);
fn hash(symbol_hasher: &mut hash::State, m: &@ast::MetaItem) {
match m.node {
ast::MetaNameValue(key, value) => {
write_string(symbol_hasher, len_and_str(key));
write_string(symbol_hasher, len_and_str_lit(value));
}
ast::MetaWord(name) => {
write_string(symbol_hasher, len_and_str(name));
}
ast::MetaList(name, ref mis) => {
write_string(symbol_hasher, len_and_str(name));
for m_ in mis.iter() {
hash(symbol_hasher, m_);
}
}
}
}
fn crate_hash(symbol_hasher: &mut Sha256, pkgid: &PkgId) -> @str {
symbol_hasher.reset();
for m in cmh_items.iter() {
hash(symbol_hasher, m);
}
for dh in dep_hashes.iter() {
write_string(symbol_hasher, len_and_str(*dh));
}
for p in pkg_id.iter() {
write_string(symbol_hasher, len_and_str(*p));
}
return truncated_hash_result(symbol_hasher).to_managed();
symbol_hasher.input_str(pkgid.to_str());
truncated_hash_result(symbol_hasher).to_managed()
}
fn warn_missing(sess: Session, name: &str, default: &str) {
if !*sess.building_library { return; }
sess.warn(format!("missing crate link meta `{}`, using `{}` as default",
name, default));
}
fn crate_meta_name(sess: Session, output: &Path, opt_name: Option<@str>)
-> @str {
match opt_name {
Some(v) if !v.is_empty() => v,
_ => {
// to_managed could go away if there was a version of
// filestem that returned an @str
// FIXME (#9639): Non-utf8 filenames will give a misleading error
let name = session::expect(sess,
output.filestem_str(),
|| format!("output file name `{}` doesn't\
appear to have a stem",
output.display())).to_managed();
if name.is_empty() {
sess.fatal("missing crate link meta `name`, and the \
inferred name is blank");
}
warn_missing(sess, "name", name);
name
}
let pkgid = match attr::find_pkgid(c.attrs) {
None => {
let stem = session::expect(
sess,
output.filestem_str(),
|| format!("output file name '{}' doesn't appear to have a stem",
output.display()));
from_str(stem).unwrap()
}
}
Some(s) => s,
};
fn crate_meta_vers(sess: Session, opt_vers: Option<@str>) -> @str {
match opt_vers {
Some(v) if !v.is_empty() => v,
_ => {
let vers = @"0.0";
warn_missing(sess, "vers", vers);
vers
}
}
}
fn crate_meta_pkgid(sess: Session, name: @str, opt_pkg_id: Option<@str>)
-> @str {
match opt_pkg_id {
Some(v) if !v.is_empty() => v,
_ => {
let pkg_id = name.clone();
warn_missing(sess, "package_id", pkg_id);
pkg_id
}
}
}
let ProvidedMetas {
name: opt_name,
vers: opt_vers,
pkg_id: opt_pkg_id,
cmh_items: cmh_items
} = provided_link_metas(sess, c);
let name = crate_meta_name(sess, output, opt_name);
let vers = crate_meta_vers(sess, opt_vers);
let pkg_id = crate_meta_pkgid(sess, name, opt_pkg_id);
let dep_hashes = cstore::get_dep_hashes(sess.cstore);
let extras_hash =
crate_meta_extras_hash(symbol_hasher, cmh_items,
dep_hashes, Some(pkg_id));
let hash = crate_hash(symbol_hasher, &pkgid);
LinkMeta {
name: name,
vers: vers,
package_id: Some(pkg_id),
extras_hash: extras_hash
pkgid: pkgid,
crate_hash: hash,
}
}
pub fn truncated_hash_result(symbol_hasher: &mut hash::State) -> ~str {
pub fn truncated_hash_result(symbol_hasher: &mut Sha256) -> ~str {
symbol_hasher.result_str()
}
// This calculates STH for a symbol, as defined above
pub fn symbol_hash(tcx: ty::ctxt,
symbol_hasher: &mut hash::State,
symbol_hasher: &mut Sha256,
t: ty::t,
link_meta: LinkMeta) -> @str {
link_meta: &LinkMeta) -> @str {
// NB: do *not* use abbrevs here as we want the symbol names
// to be independent of one another in the crate.
symbol_hasher.reset();
write_string(symbol_hasher, link_meta.name);
write_string(symbol_hasher, "-");
write_string(symbol_hasher, link_meta.extras_hash);
write_string(symbol_hasher, "-");
write_string(symbol_hasher, encoder::encoded_ty(tcx, t));
symbol_hasher.input_str(link_meta.pkgid.name);
symbol_hasher.input_str("-");
symbol_hasher.input_str(link_meta.crate_hash);
symbol_hasher.input_str("-");
symbol_hasher.input_str(encoder::encoded_ty(tcx, t));
let mut hash = truncated_hash_result(symbol_hasher);
// Prefix with 'h' so that it never blends into adjacent digits
hash.unshift_char('h');
@ -635,7 +503,7 @@ pub fn get_symbol_hash(ccx: &mut CrateContext, t: ty::t) -> @str {
match ccx.type_hashcodes.find(&t) {
Some(&h) => h,
None => {
let hash = symbol_hash(ccx.tcx, &mut ccx.symbol_hasher, t, ccx.link_meta);
let hash = symbol_hash(ccx.tcx, &mut ccx.symbol_hasher, t, &ccx.link_meta);
ccx.type_hashcodes.insert(t, hash);
hash
}
@ -774,7 +642,7 @@ pub fn mangle_exported_name(ccx: &mut CrateContext,
let hash = get_symbol_hash(ccx, t);
return exported_name(ccx.sess, path,
hash,
ccx.link_meta.vers);
ccx.link_meta.pkgid.version_or_default());
}
pub fn mangle_internal_name_by_type_only(ccx: &mut CrateContext,
@ -813,8 +681,11 @@ pub fn mangle_internal_name_by_path(ccx: &mut CrateContext, path: path) -> ~str
mangle(ccx.sess, path, None, None)
}
pub fn output_lib_filename(lm: LinkMeta) -> ~str {
format!("{}-{}-{}", lm.name, lm.extras_hash, lm.vers)
pub fn output_lib_filename(lm: &LinkMeta) -> ~str {
format!("{}-{}-{}",
lm.pkgid.name,
lm.crate_hash.slice_chars(0, 8),
lm.pkgid.version_or_default())
}
pub fn get_cc_prog(sess: Session) -> ~str {
@ -848,7 +719,8 @@ pub fn get_cc_prog(sess: Session) -> ~str {
pub fn link_binary(sess: Session,
trans: &CrateTranslation,
obj_filename: &Path,
out_filename: &Path) {
out_filename: &Path,
lm: &LinkMeta) {
// If we're generating a test executable, then ignore all other output
// styles at all other locations
let outputs = if sess.opts.test {
@ -858,7 +730,7 @@ pub fn link_binary(sess: Session,
};
for output in outputs.move_iter() {
link_binary_output(sess, trans, output, obj_filename, out_filename);
link_binary_output(sess, trans, output, obj_filename, out_filename, lm);
}
// Remove the temporary object file and metadata if we aren't saving temps
@ -881,8 +753,9 @@ fn link_binary_output(sess: Session,
trans: &CrateTranslation,
output: session::OutputStyle,
obj_filename: &Path,
out_filename: &Path) {
let libname = output_lib_filename(trans.link);
out_filename: &Path,
lm: &LinkMeta) {
let libname = output_lib_filename(lm);
let out_filename = match output {
session::OutputRlib => {
out_filename.with_filename(format!("lib{}.rlib", libname))

View File

@ -389,7 +389,8 @@ pub fn phase_6_link_output(sess: Session,
link::link_binary(sess,
trans,
&outputs.obj_filename,
&outputs.out_filename));
&outputs.out_filename,
&trans.link));
}
pub fn stop_after_phase_3(sess: Session) -> bool {
@ -977,17 +978,13 @@ pub fn build_output_filenames(input: &input,
str_input(_) => @"rust_out"
};
// If a linkage name meta is present, we use it as the link name
let linkage_metas = attr::find_linkage_metas(attrs);
if !linkage_metas.is_empty() {
// But if a linkage meta is present, that overrides
let maybe_name = linkage_metas.iter().find(|m| "name" == m.name());
match maybe_name.and_then(|m| m.value_str()) {
Some(s) => stem = s,
_ => ()
// If a pkgid is present, we use it as the link name
let pkgid = attr::find_pkgid(attrs);
match pkgid {
None => {}
Some(pkgid) => {
stem = pkgid.name.to_managed()
}
// If the name is missing, we just default to the filename
// version
}
if *sess.building_library {

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="rustc#0.9-pre"];
// NOTE: remove after the next snapshot
#[link(name = "rustc",
package_id = "rustc",
vers = "0.9-pre",
@ -109,6 +111,7 @@ pub mod driver;
pub mod util {
pub mod common;
pub mod ppaux;
pub mod sha2;
}
pub mod lib {

View File

@ -7,7 +7,9 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::cast;
use syntax::pkgid::PkgId;
// EBML enum definitions and utils shared by the encoder and decoder
@ -202,10 +204,8 @@ pub static tag_native_libraries_lib: uint = 0x104;
pub static tag_native_libraries_name: uint = 0x105;
pub static tag_native_libraries_kind: uint = 0x106;
#[deriving(Clone)]
pub struct LinkMeta {
name: @str,
vers: @str,
// Optional package ID
package_id: Option<@str>, // non-None if this was a URL-like package ID
extras_hash: @str
pkgid: PkgId,
crate_hash: @str,
}

View File

@ -17,7 +17,6 @@ use metadata::loader;
use std::hashmap::HashMap;
use syntax::ast;
use std::vec;
use syntax::abi;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
@ -25,6 +24,7 @@ use syntax::codemap::{Span, dummy_sp};
use syntax::diagnostic::span_handler;
use syntax::parse::token;
use syntax::parse::token::ident_interner;
use syntax::pkgid::PkgId;
use syntax::visit;
// Traverses an AST, reading all the information about use'd crates and extern
@ -64,7 +64,7 @@ struct cache_entry {
cnum: ast::CrateNum,
span: Span,
hash: @str,
metas: @~[@ast::MetaItem]
pkgid: PkgId,
}
fn dump_crates(crate_cache: &[cache_entry]) {
@ -80,12 +80,10 @@ fn warn_if_multiple_versions(e: @mut Env,
diag: @mut span_handler,
crate_cache: &[cache_entry]) {
if crate_cache.len() != 0u {
let name = loader::crate_name_from_metas(
*crate_cache[crate_cache.len() - 1].metas
);
let name = crate_cache[crate_cache.len() - 1].pkgid.name.clone();
let (matches, non_matches) = crate_cache.partitioned(|entry|
name == loader::crate_name_from_metas(*entry.metas));
name == entry.pkgid.name);
assert!(!matches.is_empty());
@ -94,11 +92,7 @@ fn warn_if_multiple_versions(e: @mut Env,
format!("using multiple versions of crate `{}`", name));
for match_ in matches.iter() {
diag.span_note(match_.span, "used here");
let attrs = ~[
attr::mk_attr(attr::mk_list_item(@"link",
(*match_.metas).clone()))
];
loader::note_linkage_attrs(e.intr, diag, attrs);
loader::note_pkgid_attr(diag, &match_.pkgid);
}
}
@ -129,28 +123,30 @@ fn visit_crate(e: &Env, c: &ast::Crate) {
fn visit_view_item(e: @mut Env, i: &ast::view_item) {
match i.node {
ast::view_item_extern_mod(ident, path_opt, ref meta_items, id) => {
ast::view_item_extern_mod(ident, path_opt, _, id) => {
let ident = token::ident_to_str(&ident);
let meta_items = match path_opt {
None => meta_items.clone(),
Some((p, _path_str_style)) => {
let p_path = Path::new(p);
match p_path.filestem_str() {
None|Some("") =>
e.sess.span_bug(i.span, "Bad package path in `extern mod` item"),
Some(s) =>
vec::append(
~[attr::mk_name_value_item_str(@"package_id", p),
attr::mk_name_value_item_str(@"name", s.to_managed())],
*meta_items)
debug!("resolving extern mod stmt. ident: {:?} path_opt: {:?}",
ident, path_opt);
let (name, version) = match path_opt {
Some((path_str, _)) => {
let pkgid: Option<PkgId> = from_str(path_str);
match pkgid {
None => (@"", @""),
Some(pkgid) => {
let version = match pkgid.version {
None => @"",
Some(ref ver) => ver.to_managed(),
};
(pkgid.name.to_managed(), version)
}
}
}
}
None => (ident, @""),
};
debug!("resolving extern mod stmt. ident: {:?}, meta: {:?}",
ident, meta_items);
let cnum = resolve_crate(e,
ident,
meta_items,
name,
version,
@"",
i.span);
cstore::add_extern_mod_stmt_cnum(e.sess.cstore, id, cnum);
@ -233,46 +229,36 @@ fn visit_item(e: &Env, i: @ast::item) {
}
}
fn metas_with(ident: @str, key: @str, mut metas: ~[@ast::MetaItem])
-> ~[@ast::MetaItem] {
// Check if key isn't there yet.
if !attr::contains_name(metas, key) {
metas.push(attr::mk_name_value_item_str(key, ident));
}
metas
}
fn metas_with_ident(ident: @str, metas: ~[@ast::MetaItem])
-> ~[@ast::MetaItem] {
metas_with(ident, @"name", metas)
}
fn existing_match(e: &Env, metas: &[@ast::MetaItem], hash: &str)
-> Option<ast::CrateNum> {
fn existing_match(e: &Env, name: @str, version: @str, hash: &str) -> Option<ast::CrateNum> {
for c in e.crate_cache.iter() {
if loader::metadata_matches(*c.metas, metas)
&& (hash.is_empty() || c.hash.as_slice() == hash) {
let pkgid_version = match c.pkgid.version {
None => @"0.0",
Some(ref ver) => ver.to_managed(),
};
if (name.is_empty() || c.pkgid.name.to_managed() == name) &&
(version.is_empty() || pkgid_version == version) &&
(hash.is_empty() || c.hash.as_slice() == hash) {
return Some(c.cnum);
}
}
return None;
None
}
fn resolve_crate(e: @mut Env,
ident: @str,
metas: ~[@ast::MetaItem],
name: @str,
version: @str,
hash: @str,
span: Span)
-> ast::CrateNum {
let metas = metas_with_ident(ident, metas);
match existing_match(e, metas, hash) {
match existing_match(e, name, version, hash) {
None => {
let load_ctxt = loader::Context {
sess: e.sess,
span: span,
ident: ident,
metas: metas,
name: name,
version: version,
hash: hash,
os: e.os,
intr: e.intr
@ -282,7 +268,7 @@ fn resolve_crate(e: @mut Env,
} = load_ctxt.load_library_crate();
let attrs = decoder::get_crate_attributes(metadata);
let linkage_metas = attr::find_linkage_metas(attrs);
let pkgid = attr::find_pkgid(attrs).unwrap();
let hash = decoder::get_crate_hash(metadata);
// Claim this crate number and cache it
@ -291,21 +277,15 @@ fn resolve_crate(e: @mut Env,
cnum: cnum,
span: span,
hash: hash,
metas: @linkage_metas
pkgid: pkgid,
});
e.next_crate_num += 1;
// Now resolve the crates referenced by this crate
let cnum_map = resolve_crate_deps(e, metadata);
let cname =
match attr::last_meta_item_value_str_by_name(load_ctxt.metas,
"name") {
Some(v) => v,
None => ident
};
let cmeta = @cstore::crate_metadata {
name: cname,
name: name,
data: metadata,
cnum_map: cnum_map,
cnum: cnum
@ -336,12 +316,9 @@ fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map {
for dep in r.iter() {
let extrn_cnum = dep.cnum;
let cname_str = token::ident_to_str(&dep.name);
let cmetas = metas_with(dep.vers, @"vers", ~[]);
debug!("resolving dep crate {} ver: {} hash: {}",
cname_str, dep.vers, dep.hash);
match existing_match(e,
metas_with_ident(cname_str, cmetas.clone()),
dep.hash) {
match existing_match(e, cname_str, dep.vers, dep.hash) {
Some(local_cnum) => {
debug!("already have it");
// We've already seen this crate
@ -353,8 +330,8 @@ fn resolve_crate_deps(e: @mut Env, cdata: @~[u8]) -> cstore::cnum_map {
// FIXME (#2404): Need better error reporting than just a bogus
// span.
let fake_span = dummy_sp();
let local_cnum = resolve_crate(e, cname_str, cmetas, dep.hash,
fake_span);
let local_cnum = resolve_crate(e, cname_str, cname_str, dep.vers,
dep.hash, fake_span);
cnum_map.insert(extrn_cnum, local_cnum);
}
}

View File

@ -1171,11 +1171,9 @@ pub fn get_crate_hash(data: @~[u8]) -> @str {
pub fn get_crate_vers(data: @~[u8]) -> @str {
let attrs = decoder::get_crate_attributes(data);
let linkage_attrs = attr::find_linkage_metas(attrs);
match attr::last_meta_item_value_str_by_name(linkage_attrs, "vers") {
Some(ver) => ver,
None => @"0.0"
match attr::find_pkgid(attrs) {
None => @"0.0",
Some(pkgid) => pkgid.version_or_default().to_managed(),
}
}

View File

@ -1482,67 +1482,30 @@ fn encode_attributes(ebml_w: &mut writer::Encoder, attrs: &[Attribute]) {
ebml_w.end_tag();
}
// So there's a special crate attribute called 'link' which defines the
// metadata that Rust cares about for linking crates. This attribute requires
// 'name', 'vers' and 'package_id' items, so if the user didn't provide them we
// will throw them in anyway with default values.
// So there's a special crate attribute called 'pkgid' which defines the
// metadata that Rust cares about for linking crates. If the user didn't
// provide it we will throw it in anyway with a default value.
fn synthesize_crate_attrs(ecx: &EncodeContext,
crate: &Crate) -> ~[Attribute] {
fn synthesize_link_attr(ecx: &EncodeContext, items: ~[@MetaItem]) ->
Attribute {
fn synthesize_pkgid_attr(ecx: &EncodeContext) -> Attribute {
assert!(!ecx.link_meta.pkgid.name.is_empty());
assert!(!ecx.link_meta.name.is_empty());
assert!(!ecx.link_meta.vers.is_empty());
let name_item =
attr::mk_name_value_item_str(@"name",
ecx.link_meta.name);
let vers_item =
attr::mk_name_value_item_str(@"vers",
ecx.link_meta.vers);
let pkgid_item = match ecx.link_meta.package_id {
Some(pkg_id) => attr::mk_name_value_item_str(@"package_id",
pkg_id),
// uses package_id equal to name;
// this should never happen here but package_id is an Option
// FIXME (#10370): change package_id in LinkMeta to @str instead of Option<@str>
_ => attr::mk_name_value_item_str(@"package_id",
ecx.link_meta.name)
};
let mut meta_items = ~[name_item, vers_item, pkgid_item];
for &mi in items.iter().filter(|mi| "name" != mi.name() && "vers" != mi.name() &&
"package_id" != mi.name()) {
meta_items.push(mi);
}
let link_item = attr::mk_list_item(@"link", meta_items);
return attr::mk_attr(link_item);
attr::mk_attr(
attr::mk_name_value_item_str(
@"pkgid",
ecx.link_meta.pkgid.to_str().to_managed()))
}
let mut attrs = ~[];
let mut found_link_attr = false;
for attr in crate.attrs.iter() {
attrs.push(
if "link" != attr.name() {
*attr
} else {
match attr.meta_item_list() {
Some(l) => {
found_link_attr = true;;
synthesize_link_attr(ecx, l.to_owned())
}
_ => *attr
}
});
if "pkgid" != attr.name() {
attrs.push(*attr);
}
}
attrs.push(synthesize_pkgid_attr(ecx));
if !found_link_attr { attrs.push(synthesize_link_attr(ecx, ~[])); }
return attrs;
attrs
}
fn encode_crate_deps(ecx: &EncodeContext,
@ -1800,7 +1763,7 @@ pub fn encode_metadata(parms: EncodeParams, crate: &Crate) -> ~[u8] {
let mut ebml_w = writer::Encoder(wr);
encode_hash(&mut ebml_w, ecx.link_meta.extras_hash);
encode_hash(&mut ebml_w, ecx.link_meta.crate_hash);
let mut i = wr.tell();
let crate_attrs = synthesize_crate_attrs(&ecx, crate);

View File

@ -20,8 +20,8 @@ use metadata::filesearch;
use syntax::codemap::Span;
use syntax::diagnostic::span_handler;
use syntax::parse::token::ident_interner;
use syntax::print::pprust;
use syntax::{ast, attr};
use syntax::pkgid::PkgId;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use std::c_str::ToCStr;
@ -47,7 +47,8 @@ pub struct Context {
sess: Session,
span: Span,
ident: @str,
metas: ~[@ast::MetaItem],
name: @str,
version: @str,
hash: @str,
os: Os,
intr: @ident_interner
@ -72,9 +73,8 @@ impl Context {
}
fn find_library_crate(&self) -> Option<Library> {
attr::require_unique_names(self.sess.diagnostic(), self.metas);
let filesearch = self.sess.filesearch;
let crate_name = crate_name_from_metas(self.metas);
let crate_name = self.name;
let (dyprefix, dysuffix) = self.dylibname();
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
@ -103,9 +103,8 @@ impl Context {
} else if candidate {
match get_metadata_section(self.sess, self.os, path) {
Some(cvec) =>
if crate_matches(cvec, self.metas, self.hash) {
debug!("found {} with matching metadata",
path.display());
if crate_matches(cvec, self.name, self.version, self.hash) {
debug!("found {} with matching pkgid", path.display());
let (rlib, dylib) = if file.ends_with(".rlib") {
(Some(path.clone()), None)
} else {
@ -118,7 +117,7 @@ impl Context {
});
FileMatches
} else {
debug!("skipping {}, metadata doesn't match",
debug!("skipping {}, pkgid doesn't match",
path.display());
FileDoesntMatch
},
@ -156,7 +155,12 @@ impl Context {
None => {}
}
let attrs = decoder::get_crate_attributes(lib.metadata);
note_linkage_attrs(self.intr, self.sess.diagnostic(), attrs);
match attr::find_pkgid(attrs) {
None => {}
Some(pkgid) => {
note_pkgid_attr(self.sess.diagnostic(), &pkgid);
}
}
}
self.sess.abort_if_errors();
None
@ -217,56 +221,27 @@ impl Context {
}
}
pub fn crate_name_from_metas(metas: &[@ast::MetaItem]) -> @str {
for m in metas.iter() {
match m.name_str_pair() {
Some((name, s)) if "name" == name => { return s; }
_ => {}
}
}
fail!("expected to find the crate name")
}
pub fn package_id_from_metas(metas: &[@ast::MetaItem]) -> Option<@str> {
for m in metas.iter() {
match m.name_str_pair() {
Some((name, s)) if "package_id" == name => { return Some(s); }
_ => {}
}
}
None
}
pub fn note_linkage_attrs(intr: @ident_interner,
diag: @mut span_handler,
attrs: ~[ast::Attribute]) {
let r = attr::find_linkage_metas(attrs);
for mi in r.iter() {
diag.handler().note(format!("meta: {}", pprust::meta_item_to_str(*mi,intr)));
}
pub fn note_pkgid_attr(diag: @mut span_handler,
pkgid: &PkgId) {
diag.handler().note(format!("pkgid: {}", pkgid.to_str()));
}
fn crate_matches(crate_data: @~[u8],
metas: &[@ast::MetaItem],
name: @str,
version: @str,
hash: @str) -> bool {
let attrs = decoder::get_crate_attributes(crate_data);
let linkage_metas = attr::find_linkage_metas(attrs);
if !hash.is_empty() {
let chash = decoder::get_crate_hash(crate_data);
if chash != hash { return false; }
match attr::find_pkgid(attrs) {
None => false,
Some(pkgid) => {
if !hash.is_empty() {
let chash = decoder::get_crate_hash(crate_data);
if chash != hash { return false; }
}
name == pkgid.name.to_managed() &&
(version.is_empty() || version == pkgid.version_or_default().to_managed())
}
}
metadata_matches(linkage_metas, metas)
}
pub fn metadata_matches(extern_metas: &[@ast::MetaItem],
local_metas: &[@ast::MetaItem]) -> bool {
// extern_metas: metas we read from the crate
// local_metas: metas we're looking for
debug!("matching {} metadata requirements against {} items",
local_metas.len(), extern_metas.len());
local_metas.iter().all(|needed| attr::contains(extern_metas, *needed))
}
fn get_metadata_section(sess: Session, os: Os, filename: &Path) -> Option<@~[u8]> {

View File

@ -816,7 +816,7 @@ fn check_heap_item(cx: &Context, it: &ast::item) {
}
static crate_attrs: &'static [&'static str] = &[
"crate_type", "feature", "no_uv", "no_main", "no_std",
"crate_type", "feature", "no_uv", "no_main", "no_std", "pkgid",
"desc", "comment", "license", "copyright", // not used in rustc now
];

View File

@ -64,11 +64,10 @@ use middle::trans::value::Value;
use middle::ty;
use util::common::indenter;
use util::ppaux::{Repr, ty_to_str};
use util::sha2::Sha256;
use middle::trans::type_::Type;
use std::c_str::ToCStr;
use std::hash;
use std::hashmap::HashMap;
use std::libc::c_uint;
use std::vec;
@ -2939,8 +2938,8 @@ pub fn decl_crate_map(sess: session::Session, mapmeta: LinkMeta,
let sym_name = if is_top {
~"_rust_crate_map_toplevel"
} else {
symname(sess, "_rust_crate_map_" + mapmeta.name, mapmeta.extras_hash,
mapmeta.vers)
symname(sess, "_rust_crate_map_" + mapmeta.pkgid.name, mapmeta.crate_hash,
mapmeta.pkgid.version_or_default())
};
let slicetype = Type::struct_([int_type, int_type], false);
@ -3059,8 +3058,8 @@ pub fn write_metadata(cx: &CrateContext, crate: &ast::Crate) -> ~[u8] {
flate::deflate_bytes(metadata);
let llmeta = C_bytes(compressed);
let llconst = C_struct([llmeta], false);
let name = format!("rust_metadata_{}_{}_{}", cx.link_meta.name,
cx.link_meta.vers, cx.link_meta.extras_hash);
let name = format!("rust_metadata_{}_{}_{}", cx.link_meta.pkgid.name,
cx.link_meta.pkgid.version_or_default(), cx.link_meta.crate_hash);
let llglobal = name.with_c_str(|buf| {
unsafe {
llvm::LLVMAddGlobal(cx.metadata_llmod, val_ty(llconst).to_ref(), buf)
@ -3084,7 +3083,7 @@ pub fn trans_crate(sess: session::Session,
sess.bug("couldn't enable multi-threaded LLVM");
}
let mut symbol_hasher = hash::default_state();
let mut symbol_hasher = Sha256::new();
let link_meta = link::build_link_meta(sess, &crate, output,
&mut symbol_hasher);
@ -3096,7 +3095,7 @@ pub fn trans_crate(sess: session::Session,
// crashes if the module identifer is same as other symbols
// such as a function name in the module.
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
let llmod_id = link_meta.name.to_owned() + ".rc";
let llmod_id = link_meta.pkgid.name.clone() + ".rc";
let ccx = @mut CrateContext::new(sess,
llmod_id,
@ -3171,7 +3170,7 @@ pub fn trans_crate(sess: session::Session,
}
let llcx = ccx.llcx;
let link_meta = ccx.link_meta;
let link_meta = ccx.link_meta.clone();
let llmod = ccx.llmod;
let mut reachable = ccx.reachable.iter().filter_map(|id| {
ccx.item_symbols.find(id).map(|s| s.to_owned())

View File

@ -26,8 +26,9 @@ use middle::ty;
use middle::trans::type_::Type;
use util::sha2::Sha256;
use std::c_str::ToCStr;
use std::hash;
use std::hashmap::{HashMap, HashSet};
use std::local_data;
use std::vec;
@ -98,7 +99,7 @@ pub struct CrateContext {
lltypes: HashMap<ty::t, Type>,
llsizingtypes: HashMap<ty::t, Type>,
adt_reprs: HashMap<ty::t, @adt::Repr>,
symbol_hasher: hash::State,
symbol_hasher: Sha256,
type_hashcodes: HashMap<ty::t, @str>,
type_short_names: HashMap<ty::t, ~str>,
all_llvm_symbols: HashSet<@str>,
@ -126,7 +127,7 @@ impl CrateContext {
tcx: ty::ctxt,
emap2: resolve::ExportMap2,
maps: astencode::Maps,
symbol_hasher: hash::State,
symbol_hasher: Sha256,
link_meta: LinkMeta,
reachable: @mut HashSet<ast::NodeId>)
-> CrateContext {
@ -168,8 +169,7 @@ impl CrateContext {
tn.associate_type("tydesc", &tydesc_type);
tn.associate_type("str_slice", &str_slice_ty);
let (crate_map_name, crate_map) = decl_crate_map(sess, link_meta,
llmod);
let (crate_map_name, crate_map) = decl_crate_map(sess, link_meta.clone(), llmod);
let dbg_cx = if sess.opts.debuginfo {
Some(debuginfo::CrateDebugContext::new(llmod, name.to_owned()))
} else {

View File

@ -2728,7 +2728,7 @@ fn namespace_for_item(cx: &mut CrateContext,
if def_id.crate == ast::LOCAL_CRATE {
// prepend crate name if not already present
let crate_namespace_ident = token::str_to_ident(cx.link_meta.name);
let crate_namespace_ident = token::str_to_ident(cx.link_meta.pkgid.name);
item_path.insert(0, ast_map::path_mod(crate_namespace_ident));
}

View File

@ -1795,7 +1795,7 @@ pub fn trans_log_level(bcx: @mut Block) -> DatumBlock {
Some(&src) => {
cstore::get_crate_data(ccx.sess.cstore, src.crate).name
}
None => ccx.link_meta.name,
None => ccx.link_meta.pkgid.name.to_managed(),
};
let mut modpath = ~[path_mod(ccx.sess.ident_of(srccrate))];
for e in bcx.fcx.path.iter() {

View File

@ -286,7 +286,7 @@ pub fn trans_intrinsic(ccx: @mut CrateContext,
}
"type_id" => {
let hash = ty::hash_crate_independent(ccx.tcx, substs.tys[0],
ccx.link_meta.extras_hash);
ccx.link_meta.crate_hash);
// NB: This needs to be kept in lockstep with the TypeId struct in
// libstd/unstable/intrinsics.rs
let val = C_named_struct(type_of::type_of(ccx, output_type), [C_u64(hash)]);

670
src/librustc/util/sha2.rs Normal file
View File

@ -0,0 +1,670 @@
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! This module implements only the Sha256 function since that is all that is needed for internal
//! use. This implementation is not intended for external use or for any use where security is
//! important.
use std::iter::range_step;
use std::num::Zero;
use std::vec;
use std::vec::bytes::{MutableByteVector, copy_memory};
use extra::hex::ToHex;
/// Write a u32 into a vector, which must be 4 bytes long. The value is written in big-endian
/// format.
fn write_u32_be(dst: &mut[u8], input: u32) {
use std::cast::transmute;
use std::unstable::intrinsics::to_be32;
assert!(dst.len() == 4);
unsafe {
let x: *mut i32 = transmute(dst.unsafe_mut_ref(0));
*x = to_be32(input as i32);
}
}
/// Read a vector of bytes into a vector of u32s. The values are read in big-endian format.
fn read_u32v_be(dst: &mut[u32], input: &[u8]) {
use std::cast::transmute;
use std::unstable::intrinsics::to_be32;
assert!(dst.len() * 4 == input.len());
unsafe {
let mut x: *mut i32 = transmute(dst.unsafe_mut_ref(0));
let mut y: *i32 = transmute(input.unsafe_ref(0));
dst.len().times(|| {
*x = to_be32(*y);
x = x.offset(1);
y = y.offset(1);
});
}
}
trait ToBits {
/// Convert the value in bytes to the number of bits, a tuple where the 1st item is the
/// high-order value and the 2nd item is the low order value.
fn to_bits(self) -> (Self, Self);
}
impl ToBits for u64 {
fn to_bits(self) -> (u64, u64) {
return (self >> 61, self << 3);
}
}
/// Adds the specified number of bytes to the bit count. fail!() if this would cause numeric
/// overflow.
fn add_bytes_to_bits<T: Int + CheckedAdd + ToBits>(bits: T, bytes: T) -> T {
let (new_high_bits, new_low_bits) = bytes.to_bits();
if new_high_bits > Zero::zero() {
fail!("Numeric overflow occured.")
}
match bits.checked_add(&new_low_bits) {
Some(x) => return x,
None => fail!("Numeric overflow occured.")
}
}
/// A FixedBuffer, likes its name implies, is a fixed size buffer. When the buffer becomes full, it
/// must be processed. The input() method takes care of processing and then clearing the buffer
/// automatically. However, other methods do not and require the caller to process the buffer. Any
/// method that modifies the buffer directory or provides the caller with bytes that can be modified
/// results in those bytes being marked as used by the buffer.
trait FixedBuffer {
/// Input a vector of bytes. If the buffer becomes full, process it with the provided
/// function and then clear the buffer.
fn input(&mut self, input: &[u8], func: |&[u8]|);
/// Reset the buffer.
fn reset(&mut self);
/// Zero the buffer up until the specified index. The buffer position currently must not be
/// greater than that index.
fn zero_until(&mut self, idx: uint);
/// Get a slice of the buffer of the specified size. There must be at least that many bytes
/// remaining in the buffer.
fn next<'s>(&'s mut self, len: uint) -> &'s mut [u8];
/// Get the current buffer. The buffer must already be full. This clears the buffer as well.
fn full_buffer<'s>(&'s mut self) -> &'s [u8];
/// Get the current position of the buffer.
fn position(&self) -> uint;
/// Get the number of bytes remaining in the buffer until it is full.
fn remaining(&self) -> uint;
/// Get the size of the buffer
fn size(&self) -> uint;
}
/// A FixedBuffer of 64 bytes useful for implementing Sha256 which has a 64 byte blocksize.
struct FixedBuffer64 {
priv buffer: [u8, ..64],
priv buffer_idx: uint,
}
impl FixedBuffer64 {
/// Create a new FixedBuffer64
fn new() -> FixedBuffer64 {
return FixedBuffer64 {
buffer: [0u8, ..64],
buffer_idx: 0
};
}
}
impl FixedBuffer for FixedBuffer64 {
fn input(&mut self, input: &[u8], func: |&[u8]|) {
let mut i = 0;
let size = self.size();
// If there is already data in the buffer, copy as much as we can into it and process
// the data if the buffer becomes full.
if self.buffer_idx != 0 {
let buffer_remaining = size - self.buffer_idx;
if input.len() >= buffer_remaining {
copy_memory(
self.buffer.mut_slice(self.buffer_idx, size),
input.slice_to(buffer_remaining),
buffer_remaining);
self.buffer_idx = 0;
func(self.buffer);
i += buffer_remaining;
} else {
copy_memory(
self.buffer.mut_slice(self.buffer_idx, self.buffer_idx + input.len()),
input,
input.len());
self.buffer_idx += input.len();
return;
}
}
// While we have at least a full buffer size chunks's worth of data, process that data
// without copying it into the buffer
while input.len() - i >= size {
func(input.slice(i, i + size));
i += size;
}
// Copy any input data into the buffer. At this point in the method, the ammount of
// data left in the input vector will be less than the buffer size and the buffer will
// be empty.
let input_remaining = input.len() - i;
copy_memory(
self.buffer.mut_slice(0, input_remaining),
input.slice_from(i),
input.len() - i);
self.buffer_idx += input_remaining;
}
fn reset(&mut self) {
self.buffer_idx = 0;
}
fn zero_until(&mut self, idx: uint) {
assert!(idx >= self.buffer_idx);
self.buffer.mut_slice(self.buffer_idx, idx).set_memory(0);
self.buffer_idx = idx;
}
fn next<'s>(&'s mut self, len: uint) -> &'s mut [u8] {
self.buffer_idx += len;
return self.buffer.mut_slice(self.buffer_idx - len, self.buffer_idx);
}
fn full_buffer<'s>(&'s mut self) -> &'s [u8] {
assert!(self.buffer_idx == 64);
self.buffer_idx = 0;
return self.buffer.slice_to(64);
}
fn position(&self) -> uint { self.buffer_idx }
fn remaining(&self) -> uint { 64 - self.buffer_idx }
fn size(&self) -> uint { 64 }
}
/// The StandardPadding trait adds a method useful for Sha256 to a FixedBuffer struct.
trait StandardPadding {
/// Add padding to the buffer. The buffer must not be full when this method is called and is
/// guaranteed to have exactly rem remaining bytes when it returns. If there are not at least
/// rem bytes available, the buffer will be zero padded, processed, cleared, and then filled
/// with zeros again until only rem bytes are remaining.
fn standard_padding(&mut self, rem: uint, func: |&[u8]|);
}
impl <T: FixedBuffer> StandardPadding for T {
fn standard_padding(&mut self, rem: uint, func: |&[u8]|) {
let size = self.size();
self.next(1)[0] = 128;
if self.remaining() < rem {
self.zero_until(size);
func(self.full_buffer());
}
self.zero_until(size - rem);
}
}
/// The Digest trait specifies an interface common to digest functions, such as SHA-1 and the SHA-2
/// family of digest functions.
pub trait Digest {
/// Provide message data.
///
/// # Arguments
///
/// * input - A vector of message data
fn input(&mut self, input: &[u8]);
/// Retrieve the digest result. This method may be called multiple times.
///
/// # Arguments
///
/// * out - the vector to hold the result. Must be large enough to contain output_bits().
fn result(&mut self, out: &mut [u8]);
/// Reset the digest. This method must be called after result() and before supplying more
/// data.
fn reset(&mut self);
/// Get the output size in bits.
fn output_bits(&self) -> uint;
/// Convenience function that feeds a string into a digest.
///
/// # Arguments
///
/// * `input` The string to feed into the digest
fn input_str(&mut self, input: &str) {
self.input(input.as_bytes());
}
/// Convenience function that retrieves the result of a digest as a
/// newly allocated vec of bytes.
fn result_bytes(&mut self) -> ~[u8] {
let mut buf = vec::from_elem((self.output_bits()+7)/8, 0u8);
self.result(buf);
buf
}
/// Convenience function that retrieves the result of a digest as a
/// ~str in hexadecimal format.
fn result_str(&mut self) -> ~str {
self.result_bytes().to_hex()
}
}
// A structure that represents that state of a digest computation for the SHA-2 512 family of digest
// functions
struct Engine256State {
H0: u32,
H1: u32,
H2: u32,
H3: u32,
H4: u32,
H5: u32,
H6: u32,
H7: u32,
}
impl Engine256State {
fn new(h: &[u32, ..8]) -> Engine256State {
return Engine256State {
H0: h[0],
H1: h[1],
H2: h[2],
H3: h[3],
H4: h[4],
H5: h[5],
H6: h[6],
H7: h[7]
};
}
fn reset(&mut self, h: &[u32, ..8]) {
self.H0 = h[0];
self.H1 = h[1];
self.H2 = h[2];
self.H3 = h[3];
self.H4 = h[4];
self.H5 = h[5];
self.H6 = h[6];
self.H7 = h[7];
}
fn process_block(&mut self, data: &[u8]) {
fn ch(x: u32, y: u32, z: u32) -> u32 {
((x & y) ^ ((!x) & z))
}
fn maj(x: u32, y: u32, z: u32) -> u32 {
((x & y) ^ (x & z) ^ (y & z))
}
fn sum0(x: u32) -> u32 {
((x >> 2) | (x << 30)) ^ ((x >> 13) | (x << 19)) ^ ((x >> 22) | (x << 10))
}
fn sum1(x: u32) -> u32 {
((x >> 6) | (x << 26)) ^ ((x >> 11) | (x << 21)) ^ ((x >> 25) | (x << 7))
}
fn sigma0(x: u32) -> u32 {
((x >> 7) | (x << 25)) ^ ((x >> 18) | (x << 14)) ^ (x >> 3)
}
fn sigma1(x: u32) -> u32 {
((x >> 17) | (x << 15)) ^ ((x >> 19) | (x << 13)) ^ (x >> 10)
}
let mut a = self.H0;
let mut b = self.H1;
let mut c = self.H2;
let mut d = self.H3;
let mut e = self.H4;
let mut f = self.H5;
let mut g = self.H6;
let mut h = self.H7;
let mut W = [0u32, ..64];
// Sha-512 and Sha-256 use basically the same calculations which are implemented
// by these macros. Inlining the calculations seems to result in better generated code.
macro_rules! schedule_round( ($t:expr) => (
W[$t] = sigma1(W[$t - 2]) + W[$t - 7] + sigma0(W[$t - 15]) + W[$t - 16];
)
)
macro_rules! sha2_round(
($A:ident, $B:ident, $C:ident, $D:ident,
$E:ident, $F:ident, $G:ident, $H:ident, $K:ident, $t:expr) => (
{
$H += sum1($E) + ch($E, $F, $G) + $K[$t] + W[$t];
$D += $H;
$H += sum0($A) + maj($A, $B, $C);
}
)
)
read_u32v_be(W.mut_slice(0, 16), data);
// Putting the message schedule inside the same loop as the round calculations allows for
// the compiler to generate better code.
for t in range_step(0u, 48, 8) {
schedule_round!(t + 16);
schedule_round!(t + 17);
schedule_round!(t + 18);
schedule_round!(t + 19);
schedule_round!(t + 20);
schedule_round!(t + 21);
schedule_round!(t + 22);
schedule_round!(t + 23);
sha2_round!(a, b, c, d, e, f, g, h, K32, t);
sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
sha2_round!(f, g, h, a, b, c, d, e, K32, t + 3);
sha2_round!(e, f, g, h, a, b, c, d, K32, t + 4);
sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5);
sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6);
sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
}
for t in range_step(48u, 64, 8) {
sha2_round!(a, b, c, d, e, f, g, h, K32, t);
sha2_round!(h, a, b, c, d, e, f, g, K32, t + 1);
sha2_round!(g, h, a, b, c, d, e, f, K32, t + 2);
sha2_round!(f, g, h, a, b, c, d, e, K32, t + 3);
sha2_round!(e, f, g, h, a, b, c, d, K32, t + 4);
sha2_round!(d, e, f, g, h, a, b, c, K32, t + 5);
sha2_round!(c, d, e, f, g, h, a, b, K32, t + 6);
sha2_round!(b, c, d, e, f, g, h, a, K32, t + 7);
}
self.H0 += a;
self.H1 += b;
self.H2 += c;
self.H3 += d;
self.H4 += e;
self.H5 += f;
self.H6 += g;
self.H7 += h;
}
}
static K32: [u32, ..64] = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];
// A structure that keeps track of the state of the Sha-256 operation and contains the logic
// necessary to perform the final calculations.
struct Engine256 {
length_bits: u64,
buffer: FixedBuffer64,
state: Engine256State,
finished: bool,
}
impl Engine256 {
fn new(h: &[u32, ..8]) -> Engine256 {
return Engine256 {
length_bits: 0,
buffer: FixedBuffer64::new(),
state: Engine256State::new(h),
finished: false
}
}
fn reset(&mut self, h: &[u32, ..8]) {
self.length_bits = 0;
self.buffer.reset();
self.state.reset(h);
self.finished = false;
}
fn input(&mut self, input: &[u8]) {
assert!(!self.finished)
// Assumes that input.len() can be converted to u64 without overflow
self.length_bits = add_bytes_to_bits(self.length_bits, input.len() as u64);
self.buffer.input(input, |input: &[u8]| { self.state.process_block(input) });
}
fn finish(&mut self) {
if self.finished {
return;
}
self.buffer.standard_padding(8, |input: &[u8]| { self.state.process_block(input) });
write_u32_be(self.buffer.next(4), (self.length_bits >> 32) as u32 );
write_u32_be(self.buffer.next(4), self.length_bits as u32);
self.state.process_block(self.buffer.full_buffer());
self.finished = true;
}
}
/// The SHA-256 hash algorithm
pub struct Sha256 {
priv engine: Engine256
}
impl Sha256 {
/// Construct an new instance of a SHA-256 digest.
pub fn new() -> Sha256 {
Sha256 {
engine: Engine256::new(&H256)
}
}
}
impl Digest for Sha256 {
fn input(&mut self, d: &[u8]) {
self.engine.input(d);
}
fn result(&mut self, out: &mut [u8]) {
self.engine.finish();
write_u32_be(out.mut_slice(0, 4), self.engine.state.H0);
write_u32_be(out.mut_slice(4, 8), self.engine.state.H1);
write_u32_be(out.mut_slice(8, 12), self.engine.state.H2);
write_u32_be(out.mut_slice(12, 16), self.engine.state.H3);
write_u32_be(out.mut_slice(16, 20), self.engine.state.H4);
write_u32_be(out.mut_slice(20, 24), self.engine.state.H5);
write_u32_be(out.mut_slice(24, 28), self.engine.state.H6);
write_u32_be(out.mut_slice(28, 32), self.engine.state.H7);
}
fn reset(&mut self) {
self.engine.reset(&H256);
}
fn output_bits(&self) -> uint { 256 }
}
static H256: [u32, ..8] = [
0x6a09e667,
0xbb67ae85,
0x3c6ef372,
0xa54ff53a,
0x510e527f,
0x9b05688c,
0x1f83d9ab,
0x5be0cd19
];
#[cfg(test)]
mod tests {
use super::{Digest, Sha256};
use std::vec;
use std::rand::isaac::IsaacRng;
use std::rand::Rng;
use extra::hex::FromHex;
// A normal addition - no overflow occurs
#[test]
fn test_add_bytes_to_bits_ok() {
assert!(super::add_bytes_to_bits::<u64>(100, 10) == 180);
}
// A simple failure case - adding 1 to the max value
#[test]
#[should_fail]
fn test_add_bytes_to_bits_overflow() {
super::add_bytes_to_bits::<u64>(Bounded::max_value(), 1);
}
struct Test {
input: ~str,
output_str: ~str,
}
fn test_hash<D: Digest>(sh: &mut D, tests: &[Test]) {
// Test that it works when accepting the message all at once
for t in tests.iter() {
sh.reset();
sh.input_str(t.input);
let out_str = sh.result_str();
assert!(out_str == t.output_str);
}
// Test that it works when accepting the message in pieces
for t in tests.iter() {
sh.reset();
let len = t.input.len();
let mut left = len;
while left > 0u {
let take = (left + 1u) / 2u;
sh.input_str(t.input.slice(len - left, take + len - left));
left = left - take;
}
let out_str = sh.result_str();
assert!(out_str == t.output_str);
}
}
#[test]
fn test_sha256() {
// Examples from wikipedia
let wikipedia_tests = ~[
Test {
input: ~"",
output_str: ~"e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
},
Test {
input: ~"The quick brown fox jumps over the lazy dog",
output_str: ~"d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592"
},
Test {
input: ~"The quick brown fox jumps over the lazy dog.",
output_str: ~"ef537f25c895bfa782526529a9b63d97aa631564d5d789c2b765448c8635fb6c"
},
];
let tests = wikipedia_tests;
let mut sh = ~Sha256::new();
test_hash(sh, tests);
}
/// Feed 1,000,000 'a's into the digest with varying input sizes and check that the result is
/// correct.
fn test_digest_1million_random<D: Digest>(digest: &mut D, blocksize: uint, expected: &str) {
let total_size = 1000000;
let buffer = vec::from_elem(blocksize * 2, 'a' as u8);
let mut rng = IsaacRng::new_unseeded();
let mut count = 0;
digest.reset();
while count < total_size {
let next: uint = rng.gen_range(0, 2 * blocksize + 1);
let remaining = total_size - count;
let size = if next > remaining { remaining } else { next };
digest.input(buffer.slice_to(size));
count += size;
}
let result_str = digest.result_str();
let result_bytes = digest.result_bytes();
assert_eq!(expected, result_str.as_slice());
assert_eq!(expected.from_hex().unwrap(), result_bytes);
}
#[test]
fn test_1million_random_sha256() {
let mut sh = Sha256::new();
test_digest_1million_random(
&mut sh,
64,
"cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
}
}
#[cfg(test)]
mod bench {
use extra::test::BenchHarness;
use super::Sha256;
#[bench]
pub fn sha256_10(bh: &mut BenchHarness) {
let mut sh = Sha256::new();
let bytes = [1u8, ..10];
bh.iter(|| {
sh.input(bytes);
});
bh.bytes = bytes.len() as u64;
}
#[bench]
pub fn sha256_1k(bh: &mut BenchHarness) {
let mut sh = Sha256::new();
let bytes = [1u8, ..1024];
bh.iter(|| {
sh.input(bytes);
});
bh.bytes = bytes.len() as u64;
}
#[bench]
pub fn sha256_64k(bh: &mut BenchHarness) {
let mut sh = Sha256::new();
let bytes = [1u8, ..65536];
bh.iter(|| {
sh.input(bytes);
});
bh.bytes = bytes.len() as u64;
}
}

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="rustdoc#0.9-pre"];
// NOTE: remove after the next snapshot
#[link(name = "rustdoc",
package_id = "rustdoc",
vers = "0.9-pre",

View File

@ -10,6 +10,8 @@
// rustpkg - a package manager and build system for Rust
#[pkgid="rustpkg#0.9-pre"];
// NOTE: remove after the next snapshot
#[link(name = "rustpkg",
package_id = "rustpkg",
vers = "0.9-pre",
@ -36,6 +38,7 @@ use extra::workcache;
use rustc::driver::{driver, session};
use rustc::metadata::filesearch;
use rustc::metadata::filesearch::rust_path;
use rustc::util::sha2;
use extra::{getopts};
use syntax::{ast, diagnostic};
use messages::{error, warn, note};
@ -52,7 +55,7 @@ use context::{Context, BuildContext,
use package_id::PkgId;
use package_source::PkgSrc;
use target::{WhatToBuild, Everything, is_lib, is_main, is_test, is_bench};
use target::{Tests, MaybeCustom, Inferred, JustOne};
use target::{Main, Tests, MaybeCustom, Inferred, JustOne};
use workcache_support::digest_only_date;
use exit_codes::{COPY_FAILED_CODE, BAD_FLAG_CODE};
@ -66,7 +69,6 @@ mod messages;
pub mod package_id;
pub mod package_source;
mod path_util;
mod sha1;
mod source_control;
mod target;
#[cfg(not(windows), test)] // FIXME test failure on windows: #10471
@ -151,7 +153,8 @@ impl<'self> PkgScript<'self> {
Nothing,
&self.build_dir,
sess,
crate);
crate,
Main);
// Discover the output
// FIXME (#9639): This needs to handle non-utf8 paths
// Discover the output

View File

@ -15,8 +15,6 @@ use std::{os, run, str, task};
use std::io;
use std::io::fs;
use std::io::File;
use std::io::process;
use std::io::process::ProcessExit;
use extra::arc::Arc;
use extra::arc::RWArc;
use extra::tempfile::TempDir;
@ -739,8 +737,8 @@ fn test_package_ids_must_be_relative_path_like() {
let whatever = PkgId::new("foo");
assert_eq!(~"foo-0.1", whatever.to_str());
assert!("github.com/catamorphism/test-pkg-0.1" ==
assert_eq!(~"foo-0.0", whatever.to_str());
assert!("github.com/catamorphism/test-pkg-0.0" ==
PkgId::new("github.com/catamorphism/test-pkg").to_str());
cond.trap(|(p, e)| {
@ -749,7 +747,7 @@ fn test_package_ids_must_be_relative_path_like() {
whatever.clone()
}).inside(|| {
let x = PkgId::new("");
assert_eq!(~"foo-0.1", x.to_str());
assert_eq!(~"foo-0.0", x.to_str());
});
cond.trap(|(p, e)| {
@ -761,9 +759,8 @@ fn test_package_ids_must_be_relative_path_like() {
let zp = os::make_absolute(&Path::new("foo/bar/quux"));
// FIXME (#9639): This needs to handle non-utf8 paths
let z = PkgId::new(zp.as_str().unwrap());
assert_eq!(~"foo-0.1", z.to_str());
assert_eq!(~"foo-0.0", z.to_str());
})
}
#[test]
@ -896,7 +893,7 @@ fn package_script_with_default_build() {
let source = Path::new(file!()).dir_path().join_many(
[~"testsuite", ~"pass", ~"src", ~"fancy-lib", ~"pkg.rs"]);
debug!("package_script_with_default_build: {}", source.display());
fs::copy(&source, &dir.join_many(["src", "fancy-lib-0.1", "pkg.rs"]));
fs::copy(&source, &dir.join_many(["src", "fancy-lib-0.0", "pkg.rs"]));
command_line_test([~"install", ~"fancy-lib"], dir);
assert_lib_exists(dir, &Path::new("fancy-lib"), NoVersion);
assert!(target_build_dir(dir).join_many([~"fancy-lib", ~"generated.rs"]).exists());
@ -1349,7 +1346,7 @@ fn test_import_rustpkg() {
let p_id = PkgId::new("foo");
let workspace = create_local_package(&p_id);
let workspace = workspace.path();
writeFile(&workspace.join_many(["src", "foo-0.1", "pkg.rs"]),
writeFile(&workspace.join_many(["src", "foo-0.0", "pkg.rs"]),
"extern mod rustpkg; fn main() {}");
command_line_test([~"build", ~"foo"], workspace);
debug!("workspace = {}", workspace.display());
@ -1362,7 +1359,7 @@ fn test_macro_pkg_script() {
let p_id = PkgId::new("foo");
let workspace = create_local_package(&p_id);
let workspace = workspace.path();
writeFile(&workspace.join_many(["src", "foo-0.1", "pkg.rs"]),
writeFile(&workspace.join_many(["src", "foo-0.0", "pkg.rs"]),
"extern mod rustpkg; fn main() { debug!(\"Hi\"); }");
command_line_test([~"build", ~"foo"], workspace);
debug!("workspace = {}", workspace.display());
@ -1404,7 +1401,7 @@ fn rust_path_hack_test(hack_flag: bool) {
let workspace = workspace.path();
let dest_workspace = mk_empty_workspace(&Path::new("bar"), &NoVersion, "dest_workspace");
let dest_workspace = dest_workspace.path();
let foo_path = workspace.join_many(["src", "foo-0.1"]);
let foo_path = workspace.join_many(["src", "foo-0.0"]);
let rust_path = Some(~[(~"RUST_PATH",
format!("{}:{}",
dest_workspace.as_str().unwrap(),
@ -1534,9 +1531,9 @@ fn rust_path_hack_build_with_dependency() {
let dep_workspace = dep_workspace.path();
let dest_workspace = mk_emptier_workspace("dep");
let dest_workspace = dest_workspace.path();
let source_dir = work_dir.join_many(["src", "foo-0.1"]);
let source_dir = work_dir.join_many(["src", "foo-0.0"]);
writeFile(&source_dir.join("lib.rs"), "extern mod dep; pub fn f() { }");
let dep_dir = dep_workspace.join_many(["src", "dep-0.1"]);
let dep_dir = dep_workspace.join_many(["src", "dep-0.0"]);
let rust_path = Some(~[(~"RUST_PATH",
format!("{}:{}",
dest_workspace.display(),
@ -1706,7 +1703,7 @@ fn test_cfg_build() {
let workspace = create_local_package(&p_id);
let workspace = workspace.path();
// If the cfg flag gets messed up, this won't compile
writeFile(&workspace.join_many(["src", "foo-0.1", "main.rs"]),
writeFile(&workspace.join_many(["src", "foo-0.0", "main.rs"]),
"#[cfg(quux)] fn main() {}");
let test_sys = test_sysroot();
// FIXME (#9639): This needs to handle non-utf8 paths
@ -1724,7 +1721,7 @@ fn test_cfg_fail() {
let p_id = PkgId::new("foo");
let workspace = create_local_package(&p_id);
let workspace = workspace.path();
writeFile(&workspace.join_many(["src", "foo-0.1", "main.rs"]),
writeFile(&workspace.join_many(["src", "foo-0.0", "main.rs"]),
"#[cfg(quux)] fn main() {}");
let test_sys = test_sysroot();
// FIXME (#9639): This needs to handle non-utf8 paths
@ -1892,11 +1889,13 @@ fn pkgid_pointing_to_subdir() {
"extras", "bar"]);
fs::mkdir_recursive(&foo_dir, io::UserRWX);
fs::mkdir_recursive(&bar_dir, io::UserRWX);
writeFile(&foo_dir.join("lib.rs"), "pub fn f() {}");
writeFile(&bar_dir.join("lib.rs"), "pub fn g() {}");
writeFile(&foo_dir.join("lib.rs"),
"#[pkgid=\"mockgithub.com/mozilla/some_repo/extras/foo\"]; pub fn f() {}");
writeFile(&bar_dir.join("lib.rs"),
"#[pkgid=\"mockgithub.com/mozilla/some_repo/extras/bar\"]; pub fn g() {}");
debug!("Creating a file in {}", workspace.display());
let testpkg_dir = workspace.join_many(["src", "testpkg-0.1"]);
let testpkg_dir = workspace.join_many(["src", "testpkg-0.0"]);
fs::mkdir_recursive(&testpkg_dir, io::UserRWX);
writeFile(&testpkg_dir.join("main.rs"),
@ -1916,13 +1915,13 @@ fn test_recursive_deps() {
let c_id = PkgId::new("c");
let b_workspace = create_local_package_with_dep(&b_id, &c_id);
let b_workspace = b_workspace.path();
writeFile(&b_workspace.join_many(["src", "c-0.1", "lib.rs"]),
writeFile(&b_workspace.join_many(["src", "c-0.0", "lib.rs"]),
"pub fn g() {}");
let a_workspace = create_local_package(&a_id);
let a_workspace = a_workspace.path();
writeFile(&a_workspace.join_many(["src", "a-0.1", "main.rs"]),
writeFile(&a_workspace.join_many(["src", "a-0.0", "main.rs"]),
"extern mod b; use b::f; fn main() { f(); }");
writeFile(&b_workspace.join_many(["src", "b-0.1", "lib.rs"]),
writeFile(&b_workspace.join_many(["src", "b-0.0", "lib.rs"]),
"extern mod c; use c::g; pub fn f() { g(); }");
// FIXME (#9639): This needs to handle non-utf8 paths
let environment = Some(~[(~"RUST_PATH", b_workspace.as_str().unwrap().to_owned())]);
@ -1999,7 +1998,7 @@ fn test_dependencies_terminate() {
let b_id = PkgId::new("b");
let workspace = create_local_package(&b_id);
let workspace = workspace.path();
let b_dir = workspace.join_many(["src", "b-0.1"]);
let b_dir = workspace.join_many(["src", "b-0.0"]);
let b_subdir = b_dir.join("test");
fs::mkdir_recursive(&b_subdir, io::UserRWX);
writeFile(&b_subdir.join("test.rs"),
@ -2066,10 +2065,10 @@ fn correct_package_name_with_rust_path_hack() {
let dest_workspace = mk_empty_workspace(&Path::new("bar"), &NoVersion, "dest_workspace");
let dest_workspace = dest_workspace.path();
writeFile(&dest_workspace.join_many(["src", "bar-0.1", "main.rs"]),
writeFile(&dest_workspace.join_many(["src", "bar-0.0", "main.rs"]),
"extern mod blat; fn main() { let _x = (); }");
let foo_path = foo_workspace.join_many(["src", "foo-0.1"]);
let foo_path = foo_workspace.join_many(["src", "foo-0.0"]);
// FIXME (#9639): This needs to handle non-utf8 paths
let rust_path = Some(~[(~"RUST_PATH", format!("{}:{}", dest_workspace.as_str().unwrap(),
foo_path.as_str().unwrap()))]);
@ -2092,7 +2091,7 @@ fn test_rustpkg_test_creates_exec() {
let foo_id = PkgId::new("foo");
let foo_workspace = create_local_package(&foo_id);
let foo_workspace = foo_workspace.path();
writeFile(&foo_workspace.join_many(["src", "foo-0.1", "test.rs"]),
writeFile(&foo_workspace.join_many(["src", "foo-0.0", "test.rs"]),
"#[test] fn f() { assert!('a' == 'a'); }");
command_line_test([~"test", ~"foo"], foo_workspace);
assert!(test_executable_exists(foo_workspace, "foo"));
@ -2115,7 +2114,7 @@ fn test_rustpkg_test_failure_exit_status() {
let foo_id = PkgId::new("foo");
let foo_workspace = create_local_package(&foo_id);
let foo_workspace = foo_workspace.path();
writeFile(&foo_workspace.join_many(["src", "foo-0.1", "test.rs"]),
writeFile(&foo_workspace.join_many(["src", "foo-0.0", "test.rs"]),
"#[test] fn f() { assert!('a' != 'a'); }");
let res = command_line_test_partial([~"test", ~"foo"], foo_workspace);
match res {
@ -2129,7 +2128,7 @@ fn test_rustpkg_test_cfg() {
let foo_id = PkgId::new("foo");
let foo_workspace = create_local_package(&foo_id);
let foo_workspace = foo_workspace.path();
writeFile(&foo_workspace.join_many(["src", "foo-0.1", "test.rs"]),
writeFile(&foo_workspace.join_many(["src", "foo-0.0", "test.rs"]),
"#[test] #[cfg(not(foobar))] fn f() { assert!('a' != 'a'); }");
let output = command_line_test([~"test", ~"--cfg", ~"foobar", ~"foo"],
foo_workspace);
@ -2142,7 +2141,7 @@ fn test_rebuild_when_needed() {
let foo_id = PkgId::new("foo");
let foo_workspace = create_local_package(&foo_id);
let foo_workspace = foo_workspace.path();
let test_crate = foo_workspace.join_many(["src", "foo-0.1", "test.rs"]);
let test_crate = foo_workspace.join_many(["src", "foo-0.0", "test.rs"]);
writeFile(&test_crate, "#[test] fn f() { assert!('a' == 'a'); }");
command_line_test([~"test", ~"foo"], foo_workspace);
assert!(test_executable_exists(foo_workspace, "foo"));
@ -2163,7 +2162,7 @@ fn test_no_rebuilding() {
let foo_id = PkgId::new("foo");
let foo_workspace = create_local_package(&foo_id);
let foo_workspace = foo_workspace.path();
let test_crate = foo_workspace.join_many(["src", "foo-0.1", "test.rs"]);
let test_crate = foo_workspace.join_many(["src", "foo-0.0", "test.rs"]);
writeFile(&test_crate, "#[test] fn f() { assert!('a' == 'a'); }");
command_line_test([~"test", ~"foo"], foo_workspace);
assert!(test_executable_exists(foo_workspace, "foo"));
@ -2182,7 +2181,7 @@ fn test_no_rebuilding() {
fn test_installed_read_only() {
// Install sources from a "remote" (actually a local github repo)
// Check that afterward, sources are read-only and installed under build/
let temp_pkg_id = git_repo_pkg();
let mut temp_pkg_id = git_repo_pkg();
let repo = init_git_repo(&temp_pkg_id.path);
let repo = repo.path();
debug!("repo = {}", repo.display());
@ -2194,6 +2193,8 @@ fn test_installed_read_only() {
writeFile(&repo_subdir.join("lib.rs"),
"pub fn f() { let _x = (); }");
add_git_tag(&repo_subdir, ~"0.1"); // this has the effect of committing the files
// update pkgid to what will be auto-detected
temp_pkg_id.version = ExactRevision(~"0.1");
// FIXME (#9639): This needs to handle non-utf8 paths
command_line_test([~"install", temp_pkg_id.path.as_str().unwrap().to_owned()], repo);
@ -2247,7 +2248,7 @@ fn test_installed_local_changes() {
let target_dir = hacking_workspace.join_many(["src",
"mockgithub.com",
"catamorphism",
"test-pkg-0.1"]);
"test-pkg-0.0"]);
debug!("---- git clone {} {}", repo_subdir.display(), target_dir.display());
let c_res = safe_git_clone(&repo_subdir, &NoVersion, &target_dir);
@ -2294,7 +2295,7 @@ fn test_compile_error() {
let foo_id = PkgId::new("foo");
let foo_workspace = create_local_package(&foo_id);
let foo_workspace = foo_workspace.path();
let main_crate = foo_workspace.join_many(["src", "foo-0.1", "main.rs"]);
let main_crate = foo_workspace.join_many(["src", "foo-0.0", "main.rs"]);
// Write something bogus
writeFile(&main_crate, "pub fn main() { if 42 != ~\"the answer\" { fail!(); } }");
let result = command_line_test_partial([~"build", ~"foo"], foo_workspace);
@ -2327,15 +2328,15 @@ fn test_c_dependency_ok() {
let dir = create_local_package(&PkgId::new("cdep"));
let dir = dir.path();
writeFile(&dir.join_many(["src", "cdep-0.1", "main.rs"]),
writeFile(&dir.join_many(["src", "cdep-0.0", "main.rs"]),
"#[link_args = \"-lfoo\"]\nextern { fn f(); } \
\nfn main() { unsafe { f(); } }");
writeFile(&dir.join_many(["src", "cdep-0.1", "foo.c"]), "void f() {}");
writeFile(&dir.join_many(["src", "cdep-0.0", "foo.c"]), "void f() {}");
debug!("dir = {}", dir.display());
let source = Path::new(file!()).dir_path().join_many(
[~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
fs::copy(&source, &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]));
fs::copy(&source, &dir.join_many([~"src", ~"cdep-0.0", ~"pkg.rs"]));
command_line_test([~"build", ~"cdep"], dir);
assert_executable_exists(dir, "cdep");
let out_dir = target_build_dir(dir).join("cdep");
@ -2344,20 +2345,21 @@ fn test_c_dependency_ok() {
assert!(c_library_path.exists());
}
#[ignore(reason="rustpkg is not reentrant")]
#[test]
#[ignore(reason="busted")]
fn test_c_dependency_no_rebuilding() {
let dir = create_local_package(&PkgId::new("cdep"));
let dir = dir.path();
writeFile(&dir.join_many(["src", "cdep-0.1", "main.rs"]),
writeFile(&dir.join_many(["src", "cdep-0.0", "main.rs"]),
"#[link_args = \"-lfoo\"]\nextern { fn f(); } \
\nfn main() { unsafe { f(); } }");
writeFile(&dir.join_many(["src", "cdep-0.1", "foo.c"]), "void f() {}");
writeFile(&dir.join_many(["src", "cdep-0.0", "foo.c"]), "void f() {}");
debug!("dir = {}", dir.display());
let source = Path::new(file!()).dir_path().join_many(
[~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
fs::copy(&source, &dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]));
fs::copy(&source, &dir.join_many([~"src", ~"cdep-0.0", ~"pkg.rs"]));
command_line_test([~"build", ~"cdep"], dir);
assert_executable_exists(dir, "cdep");
let out_dir = target_build_dir(dir).join("cdep");
@ -2383,15 +2385,15 @@ fn test_c_dependency_no_rebuilding() {
fn test_c_dependency_yes_rebuilding() {
let dir = create_local_package(&PkgId::new("cdep"));
let dir = dir.path();
writeFile(&dir.join_many(["src", "cdep-0.1", "main.rs"]),
writeFile(&dir.join_many(["src", "cdep-0.0", "main.rs"]),
"#[link_args = \"-lfoo\"]\nextern { fn f(); } \
\nfn main() { unsafe { f(); } }");
let c_file_name = dir.join_many(["src", "cdep-0.1", "foo.c"]);
let c_file_name = dir.join_many(["src", "cdep-0.0", "foo.c"]);
writeFile(&c_file_name, "void f() {}");
let source = Path::new(file!()).dir_path().join_many(
[~"testsuite", ~"pass", ~"src", ~"c-dependencies", ~"pkg.rs"]);
let target = dir.join_many([~"src", ~"cdep-0.1", ~"pkg.rs"]);
let target = dir.join_many([~"src", ~"cdep-0.0", ~"pkg.rs"]);
debug!("Copying {} -> {}", source.display(), target.display());
fs::copy(&source, &target);
command_line_test([~"build", ~"cdep"], dir);
@ -2420,13 +2422,13 @@ fn test_c_dependency_yes_rebuilding() {
fn correct_error_dependency() {
// Supposing a package we're trying to install via a dependency doesn't
// exist, we should throw a condition, and not ICE
let dir = create_local_package(&PkgId::new("badpkg"));
let workspace_dir = create_local_package(&PkgId::new("badpkg"));
let dir = dir.path();
writeFile(&dir.join_many(["src", "badpkg-0.1", "main.rs"]),
let dir = workspace_dir.path();
let main_rs = dir.join_many(["src", "badpkg-0.0", "main.rs"]);
writeFile(&main_rs,
"extern mod p = \"some_package_that_doesnt_exist\";
fn main() {}");
match command_line_test_partial([~"build", ~"badpkg"], dir) {
Fail(ProcessOutput{ error: error, output: output, .. }) => {
assert!(str::is_utf8(error));

View File

@ -42,7 +42,7 @@ pub fn main() {
let mut context = api::default_context(sysroot, path_for_db);
let my_workspace = api::my_workspace(&context.context, "cdep");
let foo_c_name = my_workspace.join_many(["src", "cdep-0.1", "foo.c"]);
let foo_c_name = my_workspace.join_many(["src", "cdep-0.0", "foo.c"]);
let out_lib_path = context.workcache_context.with_prep("foo.c", |prep| {
let sub_cx = context.context.clone();

View File

@ -290,23 +290,17 @@ pub fn compile_input(context: &BuildContext,
addl_lib_search_paths.insert(p);
});
// Inject the link attributes so we get the right package name and version
if attr::find_linkage_metas(crate.attrs).is_empty() {
let name_to_use = match what {
Test => format!("{}test", pkg_id.short_name).to_managed(),
Bench => format!("{}bench", pkg_id.short_name).to_managed(),
_ => pkg_id.short_name.to_managed()
};
debug!("Injecting link name: {}", name_to_use);
// Inject the pkgid attribute so we get the right package name and version
if !attr::contains_name(crate.attrs, "pkgid") {
// FIXME (#9639): This needs to handle non-utf8 paths
let link_options =
~[attr::mk_name_value_item_str(@"name", name_to_use),
attr::mk_name_value_item_str(@"vers", pkg_id.version.to_str().to_managed())] +
~[attr::mk_name_value_item_str(@"package_id",
pkg_id.path.as_str().unwrap().to_managed())];
let pkgid_attr =
attr::mk_name_value_item_str(@"pkgid",
format!("{}\\#{}",
pkg_id.path.as_str().unwrap(),
pkg_id.version.to_str()).to_managed());
debug!("link options: {:?}", link_options);
crate.attrs = ~[attr::mk_attr(attr::mk_list_item(@"link", link_options))];
debug!("pkgid attr: {:?}", pkgid_attr);
crate.attrs = ~[attr::mk_attr(pkgid_attr)];
}
debug!("calling compile_crate_from_input, workspace = {},
@ -316,7 +310,8 @@ pub fn compile_input(context: &BuildContext,
context.compile_upto(),
&out_dir,
sess,
crate);
crate,
what);
// Discover the output
let discovered_output = if what == Lib {
built_library_in_workspace(pkg_id, workspace) // Huh???
@ -351,15 +346,29 @@ pub fn compile_crate_from_input(input: &Path,
sess: session::Session,
// Returns None if one of the flags that suppresses compilation output was
// given
crate: ast::Crate) -> Option<Path> {
crate: ast::Crate,
what: OutputType) -> Option<Path> {
debug!("Calling build_output_filenames with {}, building library? {:?}",
out_dir.display(), sess.building_library);
// bad copy
debug!("out_dir = {}", out_dir.display());
let outputs = driver::build_output_filenames(&driver::file_input(input.clone()),
&Some(out_dir.clone()), &None,
crate.attrs, sess);
let mut outputs = driver::build_output_filenames(&driver::file_input(input.clone()),
&Some(out_dir.clone()), &None,
crate.attrs, sess);
match what {
Lib | Main => {}
Test => {
let mut ofile = outputs.out_filename.filename_str().unwrap().to_owned();
ofile.push_str("test");
outputs.out_filename.set_filename(ofile);
}
Bench => {
let mut ofile = outputs.out_filename.filename_str().unwrap().to_owned();
ofile.push_str("bench");
outputs.out_filename.set_filename(ofile);
}
};
debug!("Outputs are out_filename: {} and obj_filename: {} and output type = {:?}",
outputs.out_filename.display(),

View File

@ -24,7 +24,7 @@ pub enum Version {
SemanticVersion(semver::Version),
Tagged(~str), // String that can't be parsed as a version.
// Requirements get interpreted exactly
NoVersion // user didn't specify a version -- prints as 0.1
NoVersion // user didn't specify a version -- prints as 0.0
}
// Equality on versions is non-symmetric: if self is NoVersion, it's equal to
@ -81,7 +81,7 @@ impl ToStr for Version {
match *self {
ExactRevision(ref n) | Tagged(ref n) => format!("{}", n.to_str()),
SemanticVersion(ref v) => format!("{}", v.to_str()),
NoVersion => ~"0.1"
NoVersion => ~"0.0"
}
}
}

View File

@ -11,7 +11,7 @@
use std::io;
use std::io::File;
use extra::workcache;
use sha1::{Digest, Sha1};
use sha2::{Digest, Sha256};
/// Hashes the file contents along with the last-modified time
pub fn digest_file_with_date(path: &Path) -> ~str {
@ -19,7 +19,7 @@ pub fn digest_file_with_date(path: &Path) -> ~str {
match io::result(|| File::open(path).read_to_end()) {
Ok(bytes) => {
let mut sha = Sha1::new();
let mut sha = Sha256::new();
sha.input(bytes);
let st = path.stat();
sha.input_str(st.modified.to_str());
@ -34,7 +34,7 @@ pub fn digest_file_with_date(path: &Path) -> ~str {
/// Hashes only the last-modified time
pub fn digest_only_date(path: &Path) -> ~str {
let mut sha = Sha1::new();
let mut sha = Sha256::new();
let st = path.stat();
sha.input_str(st.modified.to_str());
sha.result_str()

View File

@ -34,6 +34,8 @@ via `close` and `delete` methods.
*/
#[pkgid="rustuv#0.9-pre"];
// NOTE: remove after the next snapshot
#[link(name = "rustuv",
package_id = "rustuv",
vers = "0.9-pre",

View File

@ -43,6 +43,8 @@
//!
//! use std::prelude::*;
#[pkgid="std#0.9-pre"];
// NOTE: remove after the next snapshot
#[link(name = "std",
package_id = "std",
vers = "0.9-pre",
@ -69,13 +71,13 @@
// When testing libstd, bring in libuv as the I/O backend so tests can print
// things and all of the std::io tests have an I/O interface to run on top
// of
#[cfg(test)] extern mod rustuv(vers = "0.9-pre");
#[cfg(test)] extern mod rustuv = "rustuv#0.9-pre";
// Make extra accessible for benchmarking
#[cfg(test)] extern mod extra(vers = "0.9-pre");
#[cfg(test)] extern mod extra = "extra#0.9-pre";
// Make std testable by not duplicating lang items. See #2912
#[cfg(test)] extern mod realstd(name = "std");
#[cfg(test)] extern mod realstd = "std#0.9-pre";
#[cfg(test)] pub use kinds = realstd::kinds;
#[cfg(test)] pub use ops = realstd::ops;
#[cfg(test)] pub use cmp = realstd::cmp;

View File

@ -917,8 +917,6 @@ fn new_sched_rng() -> XorShiftRng {
#[cfg(test)]
mod test {
extern mod extra;
use prelude::*;
use rt::test::*;
use unstable::run_in_bare_thread;

View File

@ -18,6 +18,7 @@ use codemap::{Span, Spanned, spanned, dummy_spanned};
use codemap::BytePos;
use diagnostic::span_handler;
use parse::comments::{doc_comment_style, strip_doc_comment_decoration};
use pkgid::PkgId;
use std::hashmap::HashSet;
@ -235,6 +236,13 @@ pub fn find_linkage_metas(attrs: &[Attribute]) -> ~[@MetaItem] {
result
}
pub fn find_pkgid(attrs: &[Attribute]) -> Option<PkgId> {
match first_attr_value_str_by_name(attrs, "pkgid") {
None => None,
Some(id) => from_str::<PkgId>(id),
}
}
#[deriving(Eq)]
pub enum InlineAttr {
InlineNone,

View File

@ -13,6 +13,8 @@
* macros.
*/
#[pkgid="syntax#0.9-pre"];
// NOTE: remove after the next snapshot
#[link(name = "syntax",
package_id = "syntax",
vers = "0.9-pre",
@ -51,6 +53,7 @@ pub mod fold;
pub mod parse;
pub mod pkgid;
pub mod print {
pub mod pp;

160
src/libsyntax/pkgid.rs Normal file
View File

@ -0,0 +1,160 @@
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[deriving(Clone, Eq)]
pub struct PkgId {
path: ~str,
name: ~str,
version: Option<~str>,
}
impl ToStr for PkgId {
fn to_str(&self) -> ~str {
let version = match self.version {
None => "0.0",
Some(ref version) => version.as_slice(),
};
if self.path.is_empty() {
format!("{}\\#{}", self.name, version)
} else {
format!("{}/{}\\#{}", self.path, self.name, version)
}
}
}
impl FromStr for PkgId {
fn from_str(s: &str) -> Option<PkgId> {
let hash_idx = match s.find('#') {
None => s.len(),
Some(idx) => idx,
};
let prefix = s.slice_to(hash_idx);
let name_idx = match prefix.rfind('/') {
None => 0,
Some(idx) => idx + 1,
};
if name_idx >= prefix.len() {
return None;
}
let name = prefix.slice_from(name_idx);
if name.len() <= 0 {
return None;
}
let path = if name_idx == 0 {
""
} else {
prefix.slice_to(name_idx - 1)
};
let check_path = Path::new(path);
if !check_path.is_relative() {
return None;
}
let version = match s.find('#') {
None => None,
Some(idx) => {
if idx >= s.len() {
None
} else {
let v = s.slice_from(idx + 1);
if v.is_empty() {
None
} else {
Some(v.to_owned())
}
}
}
};
Some(PkgId{
path: path.to_owned(),
name: name.to_owned(),
version: version,
})
}
}
impl PkgId {
pub fn version_or_default<'a>(&'a self) -> &'a str {
match self.version {
None => "0.0",
Some(ref version) => version.as_slice(),
}
}
}
#[test]
fn bare_name() {
let pkgid: PkgId = from_str("foo").expect("valid pkgid");
assert_eq!(pkgid.name, ~"foo");
assert_eq!(pkgid.version, None);
assert_eq!(pkgid.path, ~"");
}
#[test]
fn bare_name_single_char() {
let pkgid: PkgId = from_str("f").expect("valid pkgid");
assert_eq!(pkgid.name, ~"f");
assert_eq!(pkgid.version, None);
assert_eq!(pkgid.path, ~"");
}
#[test]
fn empty_pkgid() {
let pkgid: Option<PkgId> = from_str("");
assert!(pkgid.is_none());
}
#[test]
fn simple_path() {
let pkgid: PkgId = from_str("example.com/foo/bar").expect("valid pkgid");
assert_eq!(pkgid.name, ~"bar");
assert_eq!(pkgid.version, None);
assert_eq!(pkgid.path, ~"example.com/foo");
}
#[test]
fn simple_version() {
let pkgid: PkgId = from_str("foo#1.0").expect("valid pkgid");
assert_eq!(pkgid.name, ~"foo");
assert_eq!(pkgid.version, Some(~"1.0"));
assert_eq!(pkgid.path, ~"");
}
#[test]
fn absolute_path() {
let pkgid: Option<PkgId> = from_str("/foo/bar");
assert!(pkgid.is_none());
}
#[test]
fn path_and_version() {
let pkgid: PkgId = from_str("example.com/foo/bar#1.0").expect("valid pkgid");
assert_eq!(pkgid.name, ~"bar");
assert_eq!(pkgid.version, Some(~"1.0"));
assert_eq!(pkgid.path, ~"example.com/foo");
}
#[test]
fn single_chars() {
let pkgid: PkgId = from_str("a/b#1").expect("valid pkgid");
assert_eq!(pkgid.name, ~"b");
assert_eq!(pkgid.version, Some(~"1"));
assert_eq!(pkgid.path, ~"a");
}
#[test]
fn missing_version() {
let pkgid: PkgId = from_str("foo#").expect("valid pkgid");
assert_eq!(pkgid.name, ~"foo");
assert_eq!(pkgid.version, None);
assert_eq!(pkgid.path, ~"");
}

View File

@ -8,13 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[link(name = "anonexternmod", vers = "0.1")];
#[crate_type = "lib"];
#[pkgid="anonexternmod#0.1"];
use std::libc;
#[link(name = "rustrt")]
#[link(name="rustrt")]
extern {
pub fn rust_get_test_int() -> libc::intptr_t;
}

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="cci_impl_lib"];
// NOTE: remove after the next snapshot
#[link(name="cci_impl_lib", vers="0.0")];
trait uint_helpers {

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="cci_iter_lib"];
// NOTE: remove after the next snapshot
#[link(name="cci_iter_lib", vers="0.0")];
#[inline]

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="cci_no_inline_lib"];
// NOTE: remove after the next snapshot
#[link(name="cci_no_inline_lib", vers="0.0")];
// same as cci_iter_lib, more-or-less, but not marked inline

View File

@ -9,6 +9,8 @@
// except according to those terms.
#[feature(managed_boxes)];
#[pkgid="crate_method_reexport_grrrrrrr2"];
// NOTE: remove after the next snapshot
#[link(name = "crate_method_reexport_grrrrrrr2")];
pub use name_pool::add;

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve1#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve1",
vers = "0.1")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve1#0.2"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve1",
vers = "0.2")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve1#0.3"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve1",
vers = "0.3")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve2#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve2",
vers = "0.1")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve2#0.2"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve2",
vers = "0.2")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve2#0.3"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve2",
vers = "0.3")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve3#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve3",
vers = "0.1")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve3#0.2"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve3",
vers = "0.2")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve4a#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve4a", vers = "0.1")];
#[crate_type = "lib"];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve4a#0.2"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve4a", vers= "0.2")];
#[crate_type = "lib"];

View File

@ -10,9 +10,11 @@
// aux-build:crateresolve4a-1.rs
// aux-build:crateresolve4a-2.rs
#[pkgid="crateresolve4b#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve4b", vers = "0.1")];
#[crate_type = "lib"];
extern mod crateresolve4a(vers="0.2");
extern mod crateresolve4a = "crateresolve4a#0.2";
pub fn f() -> int { crateresolve4a::g() }

View File

@ -10,9 +10,11 @@
// aux-build:crateresolve4a-1.rs
// aux-build:crateresolve4a-2.rs
#[pkgid="crateresolve4b#0.2"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve4b", vers = "0.2")];
#[crate_type = "lib"];
extern mod crateresolve4a(vers="0.1");
extern mod crateresolve4a = "crateresolve4a#0.1";
pub fn g() -> int { crateresolve4a::f() }

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve5#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve5",
vers = "0.1")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve5#0.2"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve5",
vers = "0.2")];

View File

@ -9,6 +9,8 @@
// except according to those terms.
// default link meta for 'package_id' will be equal to filestem
#[pkgid="crateresolve8#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve8",
vers = "0.1")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve_calories#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve_calories",
vers = "0.1",
calories = "100")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="crateresolve_calories#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "crateresolve_calories",
vers = "0.1",
calories = "200")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="externcallback#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "externcallback",
vers = "0.1")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="foreign_lib"];
// NOTE: remove after the next snapshot
#[link(name="foreign_lib", vers="0.0")];
pub mod rustrt {

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="inline_dtor#0.1"];
// NOTE: remove after the next snapshot
#[link(name="inline_dtor", vers="0.1")];
pub struct Foo;

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="issue6919_3#0.1"];
// NOTE: remove after the next snapshot
#[link(name="iss6919_3", vers="0.1")];
// part of issue-6919.rs

View File

@ -9,6 +9,8 @@
// except according to those terms.
#[feature(managed_boxes)];
#[pkgid="a"];
// NOTE: remove after the next snapshot
#[link(name = "a", vers = "0.0")];
#[crate_type = "lib"];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="a#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "a", vers = "0.1")];
#[crate_type = "lib"];

View File

@ -10,6 +10,8 @@
// xfail-fast
#[pkgid="b#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "b", vers = "0.1")];
#[crate_type = "lib"];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="issue_2526#0.2"];
// NOTE: remove after the next snapshot
#[link(name = "issue_2526",
vers = "0.2",
uuid = "54cc1bc9-02b8-447c-a227-75ebc923bc29")];

View File

@ -9,6 +9,8 @@
// except according to those terms.
#[feature(managed_boxes)];
#[pkgid="req"];
// NOTE: remove after the next snapshot
#[link(name = "req")];
#[crate_type = "lib"];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="socketlib"];
// NOTE: remove after the next snapshot
#[link(name="socketlib", vers="0.0")];
#[crate_type = "lib"];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="numeric#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "numeric",
vers = "0.1")];
#[crate_type = "lib"];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="a#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "a", vers = "0.1")];
#[crate_type = "lib"];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="c#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "c", vers = "0.1")];
#[crate_type = "lib"];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="issue_3979_traits#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "issue_3979_traits",
vers = "0.1")];

View File

@ -7,6 +7,8 @@
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="lint_stability#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "lint_stability",
vers = "0.1")];
#[crate_type = "lib"];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="static-function-pointer-aux"];
pub fn f(x: int) -> int { -x }
pub static F: extern fn(int) -> int = f;

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="static_methods_crate#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "static_methods_crate",
vers = "0.1")];

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="struct_variant_xc_aux#0.1"];
// NOTE: remove after the next snapshot
#[link(name = "struct_variant_xc_aux",
vers = "0.1")];
#[crate_type = "lib"];

View File

@ -1,3 +1,4 @@
#[pkgid="trait_default_method_xc_aux"];
pub struct Something { x: int }

View File

@ -1,6 +1,6 @@
// aux-build:trait_default_method_xc_aux.rs
extern mod aux(name = "trait_default_method_xc_aux");
extern mod aux = "trait_default_method_xc_aux";
use aux::A;
pub struct a_struct { x: int }

View File

@ -13,10 +13,10 @@
// aux-build:crateresolve2-3.rs
// error-pattern:using multiple versions of crate `crateresolve2`
extern mod crateresolve2(vers = "0.1");
extern mod crateresolve2 = "crateresolve2#0.1";
mod m {
pub extern mod crateresolve2(vers = "0.2");
pub extern mod crateresolve2 = "crateresolve2#0.2";
}
fn main() {

View File

@ -12,8 +12,8 @@
// aux-build:crateresolve5-1.rs
// aux-build:crateresolve5-2.rs
extern mod cr5_1 (name = "crateresolve5", vers = "0.1");
extern mod cr5_2 (name = "crateresolve5", vers = "0.2");
extern mod cr5_1 = "crateresolve5#0.1";
extern mod cr5_2 = "crateresolve5#0.2";
fn main() {

View File

@ -1,15 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:duplicate meta item `name`
#[link(name = "test", name)];
fn main() { }

View File

@ -1,15 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:duplicate meta item `name`
extern mod extra(name = "extra", name = "nonstd");
fn main() { }

View File

@ -10,6 +10,6 @@
// error-pattern:can't find crate for `extra`
extern mod extra(complex(meta(item)));
extern mod extra = "fake-crate";
fn main() { }

View File

@ -10,5 +10,4 @@
// error-pattern:can't find crate for `std`
extern mod std (name = "std",
vers = "bogus");
extern mod std = "std#bogus";

View File

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[link(package_id = "boot", name = "boot", vers = "0.1")];
#[crate_type = "lib"];
#[pkgid="boot#0.1"];
#[crate_type="lib"];
extern mod rustuv; // pull in uvio

View File

@ -13,7 +13,7 @@
// aux-build:crateresolve1-2.rs
// aux-build:crateresolve1-3.rs
extern mod crateresolve1(vers = "0.2");
extern mod crateresolve1 = "crateresolve1#0.2";
pub fn main() {
assert_eq!(crateresolve1::f(), 20);

View File

@ -14,17 +14,17 @@
// aux-build:crateresolve2-3.rs
mod a {
extern mod crateresolve2(vers = "0.1");
extern mod crateresolve2 = "crateresolve2#0.1";
pub fn f() { assert!(crateresolve2::f() == 10); }
}
mod b {
extern mod crateresolve2(vers = "0.2");
extern mod crateresolve2 = "crateresolve2#0.2";
pub fn f() { assert!(crateresolve2::f() == 20); }
}
mod c {
extern mod crateresolve2(vers = "0.3");
extern mod crateresolve2 = "crateresolve2#0.3";
pub fn f() { assert!(crateresolve2::f() == 30); }
}

View File

@ -16,12 +16,12 @@
// as long as no name collision on invoked functions.
mod a {
extern mod crateresolve3(vers = "0.1");
extern mod crateresolve3 = "crateresolve3#0.1";
pub fn f() { assert!(crateresolve3::f() == 10); }
}
mod b {
extern mod crateresolve3(vers = "0.2");
extern mod crateresolve3 = "crateresolve3#0.2";
pub fn f() { assert!(crateresolve3::g() == 20); }
}

View File

@ -15,12 +15,12 @@
// aux-build:crateresolve4b-2.rs
pub mod a {
extern mod crateresolve4b(vers = "0.1");
extern mod crateresolve4b = "crateresolve4b#0.1";
pub fn f() { assert!(crateresolve4b::f() == 20); }
}
pub mod b {
extern mod crateresolve4b(vers = "0.2");
extern mod crateresolve4b = "crateresolve4b#0.2";
pub fn f() { assert!(crateresolve4b::g() == 10); }
}

View File

@ -12,8 +12,8 @@
// aux-build:crateresolve5-1.rs
// aux-build:crateresolve5-2.rs
extern mod cr5_1 (name = "crateresolve5", vers = "0.1");
extern mod cr5_2 (name = "crateresolve5", vers = "0.2");
extern mod cr5_1 = "crateresolve5#0.1";
extern mod cr5_2 = "crateresolve5#0.2";
pub fn main() {
// Structural types can be used between two versions of the same crate

View File

@ -1,23 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-fast
// aux-build:crateresolve_calories-1.rs
// aux-build:crateresolve_calories-2.rs
// error-pattern:mismatched types
// These both have the same version but differ in other metadata
extern mod cr6_1 (name = "crateresolve_calories", vers = "0.1", calories="100");
extern mod cr6_2 (name = "crateresolve_calories", vers = "0.1", calories="200");
pub fn main() {
assert_eq!(cr6_1::f(), 100);
assert_eq!(cr6_2::f(), 200);
}

View File

@ -1,21 +0,0 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// xfail-fast
// aux-build:crateresolve_calories-1.rs
// aux-build:crateresolve_calories-2.rs
// aux-build:crateresolve7x.rs
extern mod crateresolve7x;
pub fn main() {
assert_eq!(crateresolve7x::a::f(), 100);
assert_eq!(crateresolve7x::b::f(), 200);
}

View File

@ -11,7 +11,9 @@
// xfail-fast
// aux-build:crateresolve8-1.rs
extern mod crateresolve8(vers = "0.1", package_id="crateresolve8");
#[pkgid="crateresolve8#0.1"];
extern mod crateresolve8(vers = "0.1", package_id="crateresolve8#0.1");
//extern mod crateresolve8(vers = "0.1");
pub fn main() {

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[pkgid="rust_get_test_int"];
// NOTE: remove after the next snapshot
#[link(name = "rust_get_test_int")];
mod rustrt {

View File

@ -11,5 +11,5 @@
// xfail-fast check-fast doesn't like aux-build
// aux-build:issue-4545.rs
extern mod somelib(name = "issue-4545");
extern mod somelib = "issue-4545";
fn main() { somelib::mk::<int>(); }

View File

@ -11,9 +11,11 @@
// aux-build:iss.rs
// xfail-fast
extern mod iss ( name = "iss6919_3" );
#[pkgid="issue-6919"];
extern mod issue6919_3;
pub fn main() {
iss::D.k;
issue6919_3::D.k;
}

View File

@ -11,7 +11,7 @@
// xfail-fast check-fast doesn't like aux-build
// aux-build:issue-8044.rs
extern mod minimal(name= "issue-8044");
extern mod minimal = "issue-8044";
use minimal::{BTree, leaf};
fn main() {

View File

@ -11,7 +11,7 @@
// xfail-fast check-fast doesn't like extern mod
// aux-build:issue-9906.rs
extern mod testmod(name = "issue-9906");
extern mod testmod = "issue-9906";
fn main() {
testmod::foo();

View File

@ -11,7 +11,7 @@
// xfail-fast check-fast doesn't like extern mod
// aux-build:issue-9968.rs
extern mod lib(name = "issue-9968");
extern mod lib = "issue-9968";
use lib::{Trait, Struct};

View File

@ -16,6 +16,8 @@
#[attr3];
#[attr4(attr5)];
#[pkgid="extra#0.1"];
// NOTE: remove after the next snapshot
// Special linkage attributes for the crate
#[link(name = "extra",
vers = "0.1",

View File

@ -13,7 +13,7 @@
// xfail-android: FIXME(#10379)
// xfail-win32: std::unstable::dynamic_lib does not work on win32 well
extern mod foo(name = "linkage-visibility");
extern mod foo = "linkage-visibility";
fn main() {
foo::test();

View File

@ -11,7 +11,7 @@
// xfail-fast
// aux-build:priv-impl-prim-ty.rs
extern mod bar(name = "priv-impl-prim-ty");
extern mod bar = "priv-impl-prim-ty";
fn main() {
bar::frob(1i);

View File

@ -11,7 +11,7 @@
// aux-build:reexport-should-still-link.rs
// xfail-fast check-fast doesn't like extern mod
extern mod foo(name = "reexport-should-still-link");
extern mod foo = "reexport-should-still-link";
fn main() {
foo::bar();

View File

@ -11,7 +11,7 @@
// xfail-fast
// aux-build:static_fn_inline_xc_aux.rs
extern mod mycore(name ="static_fn_inline_xc_aux");
extern mod mycore = "static_fn_inline_xc_aux";
use mycore::num;

View File

@ -1,7 +1,7 @@
// aux-build:static_fn_trait_xc_aux.rs
// xfail-fast
extern mod mycore(name ="static_fn_trait_xc_aux");
extern mod mycore = "static_fn_trait_xc_aux";
use mycore::num;

Some files were not shown because too many files have changed in this diff Show More