auto merge of #15319 : alexcrichton/rust/no-crate-id, r=brson

This is an implementation of [RFC 35](https://github.com/rust-lang/rfcs/blob/master/active/0035-remove-crate-id.md).

The summary for this PR is the same as that of the RFC, with one addendum:


* Removes the `#[crate_id]` attribute and knowledge of versions from rustc.
* Added a `#[crate_name]` attribute similar to the old `#[crate_id]` attribute
* Output filenames no longer have versions or hashes
* Symbols no longer have versions (they still have hashes)
* A new flag, `--extern`, is used to override searching for external crates
* A new flag, `-C metadata=foo`, used when hashing symbols
* [added] An old flag, `--crate-name`, was re purposed to specify the crate name from the command line.

I tried to maintain backwards compatibility wherever possible (with warnings being printed). If I missed anywhere, however, please let me know!

[breaking-change]

Closes #14468
Closes #14469
Closes #14470
Closes #14471
This commit is contained in:
bors 2014-07-05 22:51:38 +00:00
commit c3ef04be55
113 changed files with 1010 additions and 718 deletions

View File

@ -16,6 +16,8 @@
CFG_RELEASE_NUM=0.11.0
CFG_RELEASE_LABEL=
CFG_FILENAME_EXTRA=4e7c5e5c
ifndef CFG_ENABLE_NIGHTLY
# This is the normal version string
CFG_RELEASE=$(CFG_RELEASE_NUM)$(CFG_RELEASE_LABEL)

View File

@ -44,6 +44,13 @@ $(foreach host,$(CFG_HOST), \
$(foreach crate,$(CRATES), \
$(eval $(call RUST_CRATE_FULLDEPS,$(stage),$(target),$(host),$(crate)))))))
# NOTE: after a stage0 snap this should be just EXTRA_FILENAME, not with a stage
# bound
EXTRA_FILENAME_0 =
EXTRA_FILENAME_1 = -C extra-filename=-$(CFG_FILENAME_EXTRA)
EXTRA_FILENAME_2 = -C extra-filename=-$(CFG_FILENAME_EXTRA)
EXTRA_FILENAME_3 = -C extra-filename=-$(CFG_FILENAME_EXTRA)
# RUST_TARGET_STAGE_N template: This defines how target artifacts are built
# for all stage/target architecture combinations. This is one giant rule which
# works as follows:
@ -85,7 +92,9 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
-L "$$(LLVM_LIBDIR_$(2))" \
-L "$$(dir $$(LLVM_STDCPP_LOCATION_$(2)))" \
$$(RUSTFLAGS_$(4)) \
--out-dir $$(@D) $$<
--out-dir $$(@D) \
$$(EXTRA_FILENAME_$(1)) \
$$<
@touch $$@
$$(call LIST_ALL_OLD_GLOB_MATCHES,\
$$(dir $$@)$$(call CFG_LIB_GLOB_$(2),$(4)))

View File

@ -60,7 +60,8 @@
//! by libc malloc/free. The `libc_heap` module is defined to be wired up to
//! the system malloc/free.
#![crate_id = "alloc#0.11.0"]
#![crate_id = "alloc#0.11.0"] // NOTE: remove after a stage0 snap
#![crate_name = "alloc"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
@ -70,6 +71,7 @@
#![no_std]
#![feature(lang_items, phase, unsafe_destructor)]
#![allow(unused_attribute)] // NOTE: remove after stage0
#[phase(plugin, link)]
extern crate core;

View File

@ -20,6 +20,7 @@
//! more complex, slower Arena which can hold objects of any type.
#![crate_id = "arena#0.11.0"]
#![crate_name = "arena"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -30,6 +31,7 @@
#![feature(unsafe_destructor)]
#![allow(missing_doc)]
#![allow(unused_attribute)] // NOTE: remove after stage0
use std::cell::{Cell, RefCell};
use std::cmp;

View File

@ -12,7 +12,8 @@
* Collection types.
*/
#![crate_id = "collections#0.11.0"]
#![crate_id = "collections#0.11.0"] // NOTE: remove after stage0
#![crate_name = "collections"]
#![experimental]
#![crate_type = "rlib"]
#![license = "MIT/ASL2"]
@ -24,6 +25,7 @@
#![feature(macro_rules, managed_boxes, default_type_params, phase, globs)]
#![feature(unsafe_destructor)]
#![no_std]
#![allow(unused_attribute)] // NOTE: remove after stage0
#[phase(plugin, link)] extern crate core;
extern crate alloc;

View File

@ -48,6 +48,7 @@
// separate crate, libcoretest, to avoid bizarre issues.
#![crate_id = "core#0.11.0"]
#![crate_name = "core"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
@ -60,6 +61,7 @@
#![feature(globs, intrinsics, lang_items, macro_rules, managed_boxes, phase)]
#![feature(simd, unsafe_destructor)]
#![deny(missing_doc)]
#![allow(unused_attribute)] // NOTE: remove after stage0
mod macros;

View File

@ -16,7 +16,8 @@
//! Additionally, it is not guaranteed that functionality such as reflection
//! will persist into the future.
#![crate_id = "debug#0.11.0"]
#![crate_id = "debug#0.11.0"] // NOTE: remove after stage0
#![crate_name = "debug"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
@ -27,6 +28,7 @@
#![experimental]
#![feature(managed_boxes, macro_rules)]
#![allow(experimental)]
#![allow(unused_attribute)] // NOTE: remove after stage0
pub mod fmt;
pub mod reflect;

View File

@ -18,7 +18,8 @@
*/
#![crate_id = "flate#0.11.0"]
#![crate_id = "flate#0.11.0"] // NOTE: remove after stage0
#![crate_name = "flate"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -27,6 +28,7 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![feature(phase)]
#![allow(unused_attribute)] // NOTE: remove after stage0
#[cfg(test)] #[phase(plugin, link)] extern crate log;

View File

@ -14,12 +14,14 @@
//! Parsing does not happen at runtime: structures of `std::fmt::rt` are
//! generated instead.
#![crate_id = "fmt_macros#0.11.0"]
#![crate_id = "fmt_macros#0.11.0"] // NOTE: remove after stage0c
#![crate_name = "fmt_macros"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![feature(macro_rules, globs)]
#![allow(unused_attribute)] // NOTE: remove after stage0
use std::char;
use std::str;

View File

@ -39,7 +39,8 @@ fn main() {
*/
#![crate_id = "fourcc#0.11.0"]
#![crate_id = "fourcc#0.11.0"] // NOTE: remove after stage0
#![crate_name = "fourcc"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -47,6 +48,7 @@ fn main() {
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(plugin_registrar, managed_boxes)]

View File

@ -76,7 +76,8 @@
//! }
//! ~~~
#![crate_id = "getopts#0.11.0"]
#![crate_id = "getopts#0.11.0"] // NOTE: remove after stage0
#![crate_name = "getopts"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -87,6 +88,7 @@
html_playground_url = "http://play.rust-lang.org/")]
#![feature(globs, phase)]
#![deny(missing_doc)]
#![allow(unused_attribute)] // NOTE: remove after stage0
#[cfg(test)] extern crate debug;
#[cfg(test)] #[phase(plugin, link)] extern crate log;

View File

@ -23,7 +23,8 @@
* `glob`/`fnmatch` functions.
*/
#![crate_id = "glob#0.11.0"]
#![crate_id = "glob#0.11.0"] // NOTE: remove after stage0
#![crate_name = "glob"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -32,6 +33,7 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![allow(unused_attribute)] // NOTE: remove after stage0
use std::cell::Cell;
use std::{cmp, os, path};

View File

@ -266,7 +266,8 @@ pub fn main() {
*/
#![crate_id = "graphviz#0.11.0"]
#![crate_id = "graphviz#0.11.0"] // NOTE: remove after stage0
#![crate_name = "graphviz"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -274,8 +275,7 @@ pub fn main() {
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![experimental]
#![allow(unused_attribute)] // NOTE: remove after stage0
use std::io;
use std::str;

View File

@ -197,7 +197,8 @@
//! pool.shutdown();
//! ```
#![crate_id = "green#0.11.0"]
#![crate_id = "green#0.11.0"] // NOTE: remove after stage0
#![crate_name = "green"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
@ -208,10 +209,9 @@
html_playground_url = "http://play.rust-lang.org/")]
// NB this does *not* include globs, please keep it that way.
#![feature(macro_rules, phase)]
#![allow(visible_private_types)]
#![allow(deprecated)]
#![feature(default_type_params)]
#![feature(macro_rules, phase, default_type_params)]
#![allow(visible_private_types, deprecated)]
#![allow(unused_attribute)] // NOTE: remove after stage0
#[cfg(test)] #[phase(plugin, link)] extern crate log;
#[cfg(test)] extern crate rustuv;

View File

@ -36,7 +36,8 @@ fn main() {
*/
#![crate_id = "hexfloat#0.11.0"]
#![crate_id = "hexfloat#0.11.0"] // NOTE: remove after stage0
#![crate_name = "hexfloat"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -45,6 +46,7 @@ fn main() {
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![feature(plugin_registrar, managed_boxes)]
#![allow(unused_attribute)] // NOTE: remove after stage0
extern crate syntax;
extern crate rustc;

View File

@ -9,7 +9,8 @@
// except according to those terms.
#![feature(globs)]
#![crate_id = "libc#0.11.0"]
#![crate_id = "libc#0.11.0"] // NOTE: remove after a stage0 snap
#![crate_name = "libc"]
#![experimental]
#![no_std] // we don't need std, and we can't have std, since it doesn't exist
// yet. std depends on us.
@ -18,6 +19,7 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![allow(unused_attribute)] // NOTE: remove after stage0
/*!
* Bindings for the C standard library and other platform libraries

View File

@ -105,7 +105,8 @@ fn main() {
*/
#![crate_id = "log#0.11.0"]
#![crate_id = "log#0.11.0"] // NOTE: Remove after stage0
#![crate_name = "log"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
@ -114,7 +115,7 @@ fn main() {
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(macro_rules)]
#![deny(missing_doc)]

View File

@ -46,7 +46,8 @@
//! }
//! ```
#![crate_id = "native#0.11.0"]
#![crate_id = "native#0.11.0"] // NOTE: remove after stage0
#![crate_name = "native"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
@ -57,6 +58,7 @@
#![deny(unused_result, unused_must_use)]
#![allow(non_camel_case_types, deprecated)]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(default_type_params, lang_items)]
// NB this crate explicitly does *not* allow glob imports, please seriously

View File

@ -44,7 +44,8 @@
#![feature(macro_rules)]
#![crate_id = "num#0.11.0"]
#![crate_id = "num#0.11.0"] // NOTE: remove after stage0
#![crate_name = "num"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -53,7 +54,7 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![allow(deprecated)] // from_str_radix
extern crate rand;

View File

@ -16,7 +16,8 @@
//! is not recommended to use this library directly, but rather the official
//! interface through `std::rand`.
#![crate_id = "rand#0.11.0"]
#![crate_id = "rand#0.11.0"] // NOTE: remove after a stage0 snap
#![crate_name = "rand"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk.png",
@ -25,6 +26,7 @@
html_playground_url = "http://play.rust-lang.org/")]
#![feature(macro_rules, phase, globs)]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![no_std]
#![experimental]

View File

@ -353,7 +353,8 @@
//! characters in the search text and `m` is the number of instructions in a
//! compiled expression.
#![crate_id = "regex#0.11.0"]
#![crate_id = "regex#0.11.0"] // NOTE: remove after stage0
#![crate_name = "regex"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
#![experimental]
@ -364,6 +365,7 @@
html_playground_url = "http://play.rust-lang.org/")]
#![feature(macro_rules, phase)]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![deny(missing_doc)]
#[cfg(test)]

View File

@ -11,13 +11,15 @@
//! This crate provides the `regex!` macro. Its use is documented in the
//! `regex` crate.
#![crate_id = "regex_macros#0.11.0"]
#![crate_id = "regex_macros#0.11.0"] // NOTE: remove after stage0
#![crate_name = "regex_macros"]
#![crate_type = "dylib"]
#![experimental]
#![license = "MIT/ASL2"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(plugin_registrar, managed_boxes, quote)]

View File

@ -20,13 +20,15 @@
//! necessary. It is an error to include this library when also linking with
//! the system libc library.
#![crate_id = "rlibc#0.11.0"]
#![crate_id = "rlibc#0.11.0"] // NOTE: remove after stage0
#![crate_name = "rlibc"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![feature(intrinsics)]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![no_std]
#![experimental]

View File

@ -11,7 +11,7 @@
use back::archive::{Archive, METADATA_FILENAME};
use back::rpath;
use back::svh::Svh;
use driver::driver::{CrateTranslation, OutputFilenames};
use driver::driver::{CrateTranslation, OutputFilenames, Input, FileInput};
use driver::config::NoDebugInfo;
use driver::session::Session;
use driver::config;
@ -19,7 +19,7 @@
use lib::llvm::ModuleRef;
use lib;
use metadata::common::LinkMeta;
use metadata::{encoder, cstore, filesearch, csearch, loader};
use metadata::{encoder, cstore, filesearch, csearch, loader, creader};
use middle::trans::context::CrateContext;
use middle::trans::common::gensym_name;
use middle::ty;
@ -40,9 +40,8 @@
use syntax::ast;
use syntax::ast_map::{PathElem, PathElems, PathName};
use syntax::ast_map;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::crateid::CrateId;
use syntax::codemap::Span;
use syntax::parse::token;
#[deriving(Clone, PartialEq, PartialOrd, Ord, Eq)]
@ -546,32 +545,69 @@ unsafe fn populate_llvm_passes(fpm: lib::llvm::PassManagerRef,
* system linkers understand.
*/
// FIXME (#9639): This needs to handle non-utf8 `out_filestem` values
pub fn find_crate_id(attrs: &[ast::Attribute], out_filestem: &str) -> CrateId {
match attr::find_crateid(attrs) {
None => from_str(out_filestem).unwrap_or_else(|| {
let mut s = out_filestem.chars().filter(|c| c.is_XID_continue());
from_str(s.collect::<String>().as_slice())
.or(from_str("rust-out")).unwrap()
}),
Some(s) => s,
pub fn find_crate_name(sess: Option<&Session>,
attrs: &[ast::Attribute],
input: &Input) -> String {
use syntax::crateid::CrateId;
let validate = |s: String, span: Option<Span>| {
creader::validate_crate_name(sess, s.as_slice(), span);
s
};
match sess {
Some(sess) => {
match sess.opts.crate_name {
Some(ref s) => return validate(s.clone(), None),
None => {}
}
}
None => {}
}
let crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
.and_then(|at| at.value_str().map(|s| (at, s)));
match crate_name {
Some((attr, s)) => return validate(s.get().to_string(), Some(attr.span)),
None => {}
}
let crate_id = attrs.iter().find(|at| at.check_name("crate_id"))
.and_then(|at| at.value_str().map(|s| (at, s)))
.and_then(|(at, s)| {
from_str::<CrateId>(s.get()).map(|id| (at, id))
});
match crate_id {
Some((attr, id)) => {
match sess {
Some(sess) => {
sess.span_warn(attr.span, "the #[crate_id] attribute is \
deprecated for the \
#[crate_name] attribute");
}
None => {}
}
return validate(id.name, Some(attr.span))
}
None => {}
}
match *input {
FileInput(ref path) => {
match path.filestem_str() {
Some(s) => return validate(s.to_string(), None),
None => {}
}
}
_ => {}
}
"rust-out".to_string()
}
pub fn crate_id_hash(crate_id: &CrateId) -> String {
// This calculates CMH as defined above. Note that we don't use the path of
// the crate id in the hash because lookups are only done by (name/vers),
// not by path.
let mut s = Sha256::new();
s.input_str(crate_id.short_name_with_version().as_slice());
truncated_hash_result(&mut s).as_slice().slice_to(8).to_string()
}
// FIXME (#9639): This needs to handle non-utf8 `out_filestem` values
pub fn build_link_meta(krate: &ast::Crate, out_filestem: &str) -> LinkMeta {
pub fn build_link_meta(sess: &Session, krate: &ast::Crate,
name: String) -> LinkMeta {
let r = LinkMeta {
crateid: find_crate_id(krate.attrs.as_slice(), out_filestem),
crate_hash: Svh::calculate(krate),
crate_name: name,
crate_hash: Svh::calculate(sess, krate),
};
info!("{}", r);
return r;
@ -594,9 +630,12 @@ fn symbol_hash(tcx: &ty::ctxt,
// to be independent of one another in the crate.
symbol_hasher.reset();
symbol_hasher.input_str(link_meta.crateid.name.as_slice());
symbol_hasher.input_str(link_meta.crate_name.as_slice());
symbol_hasher.input_str("-");
symbol_hasher.input_str(link_meta.crate_hash.as_str());
for meta in tcx.sess.crate_metadata.borrow().iter() {
symbol_hasher.input_str(meta.as_slice());
}
symbol_hasher.input_str("-");
symbol_hasher.input_str(encoder::encoded_ty(tcx, t).as_slice());
// Prefix with 'h' so that it never blends into adjacent digits
@ -666,8 +705,7 @@ pub fn sanitize(s: &str) -> String {
}
pub fn mangle<PI: Iterator<PathElem>>(mut path: PI,
hash: Option<&str>,
vers: Option<&str>) -> String {
hash: Option<&str>) -> String {
// Follow C++ namespace-mangling style, see
// http://en.wikipedia.org/wiki/Name_mangling for more info.
//
@ -698,25 +736,13 @@ fn push(n: &mut String, s: &str) {
Some(s) => push(&mut n, s),
None => {}
}
match vers {
Some(s) => push(&mut n, s),
None => {}
}
n.push_char('E'); // End name-sequence.
n
}
pub fn exported_name(path: PathElems, hash: &str, vers: &str) -> String {
// The version will get mangled to have a leading '_', but it makes more
// sense to lead with a 'v' b/c this is a version...
let vers = if vers.len() > 0 && !char::is_XID_start(vers.char_at(0)) {
format!("v{}", vers)
} else {
vers.to_string()
};
mangle(path, Some(hash), Some(vers.as_slice()))
pub fn exported_name(path: PathElems, hash: &str) -> String {
mangle(path, Some(hash))
}
pub fn mangle_exported_name(ccx: &CrateContext, path: PathElems,
@ -741,9 +767,7 @@ pub fn mangle_exported_name(ccx: &CrateContext, path: PathElems,
hash.push_char(EXTRA_CHARS.as_bytes()[extra2] as char);
hash.push_char(EXTRA_CHARS.as_bytes()[extra3] as char);
exported_name(path,
hash.as_slice(),
ccx.link_meta.crateid.version_or_default())
exported_name(path, hash.as_slice())
}
pub fn mangle_internal_name_by_type_and_seq(ccx: &CrateContext,
@ -753,15 +777,11 @@ pub fn mangle_internal_name_by_type_and_seq(ccx: &CrateContext,
let path = [PathName(token::intern(s.as_slice())),
gensym_name(name)];
let hash = get_symbol_hash(ccx, t);
mangle(ast_map::Values(path.iter()), Some(hash.as_slice()), None)
mangle(ast_map::Values(path.iter()), Some(hash.as_slice()))
}
pub fn mangle_internal_name_by_path_and_seq(path: PathElems, flav: &str) -> String {
mangle(path.chain(Some(gensym_name(flav)).move_iter()), None, None)
}
pub fn output_lib_filename(id: &CrateId) -> String {
format!("{}-{}-{}", id.name, crate_id_hash(id), id.version_or_default())
mangle(path.chain(Some(gensym_name(flav)).move_iter()), None)
}
pub fn get_cc_prog(sess: &Session) -> String {
@ -803,14 +823,15 @@ fn remove(sess: &Session, path: &Path) {
pub fn link_binary(sess: &Session,
trans: &CrateTranslation,
outputs: &OutputFilenames,
id: &CrateId) -> Vec<Path> {
crate_name: &str) -> Vec<Path> {
let mut out_filenames = Vec::new();
for &crate_type in sess.crate_types.borrow().iter() {
if invalid_output_for_target(sess, crate_type) {
sess.bug(format!("invalid output type `{}` for target os `{}`",
crate_type, sess.targ_cfg.os).as_slice());
}
let out_file = link_binary_output(sess, trans, crate_type, outputs, id);
let out_file = link_binary_output(sess, trans, crate_type, outputs,
crate_name);
out_filenames.push(out_file);
}
@ -859,9 +880,11 @@ fn is_writeable(p: &Path) -> bool {
}
}
pub fn filename_for_input(sess: &Session, crate_type: config::CrateType,
id: &CrateId, out_filename: &Path) -> Path {
let libname = output_lib_filename(id);
pub fn filename_for_input(sess: &Session,
crate_type: config::CrateType,
name: &str,
out_filename: &Path) -> Path {
let libname = format!("{}{}", name, sess.opts.cg.extra_filename);
match crate_type {
config::CrateTypeRlib => {
out_filename.with_filename(format!("lib{}.rlib", libname))
@ -891,13 +914,13 @@ fn link_binary_output(sess: &Session,
trans: &CrateTranslation,
crate_type: config::CrateType,
outputs: &OutputFilenames,
id: &CrateId) -> Path {
crate_name: &str) -> Path {
let obj_filename = outputs.temp_path(OutputTypeObject);
let out_filename = match outputs.single_output_file {
Some(ref file) => file.clone(),
None => {
let out_filename = outputs.path(OutputTypeExe);
filename_for_input(sess, crate_type, id, &out_filename)
filename_for_input(sess, crate_type, crate_name, &out_filename)
}
};

View File

@ -53,6 +53,8 @@
use syntax::ast;
use syntax::visit;
use driver::session::Session;
#[deriving(Clone, PartialEq)]
pub struct Svh {
hash: String,
@ -68,7 +70,7 @@ pub fn as_str<'a>(&'a self) -> &'a str {
self.hash.as_slice()
}
pub fn calculate(krate: &ast::Crate) -> Svh {
pub fn calculate(sess: &Session, krate: &ast::Crate) -> Svh {
// FIXME (#14132): This is better than it used to be, but it still not
// ideal. We now attempt to hash only the relevant portions of the
// Crate AST as well as the top-level crate attributes. (However,
@ -80,6 +82,10 @@ pub fn calculate(krate: &ast::Crate) -> Svh {
// avoid collisions.
let mut state = SipState::new();
for data in sess.opts.cg.metadata.iter() {
data.hash(&mut state);
}
{
let mut visit = svh_visitor::make(&mut state);
visit::walk_crate(&mut visit, krate, ());

View File

@ -11,7 +11,7 @@
//! Contains infrastructure for configuring the compiler, including parsing
//! command line options.
use driver::early_error;
use driver::{early_error, early_warn};
use driver::driver;
use driver::session::Session;
@ -30,7 +30,7 @@
use syntax::parse;
use syntax::parse::token::InternedString;
use std::collections::HashSet;
use std::collections::{HashSet, HashMap};
use getopts::{optopt, optmulti, optflag, optflagopt};
use getopts;
use lib::llvm::llvm;
@ -91,10 +91,12 @@ pub struct Options {
pub debugging_opts: u64,
/// Whether to write dependency files. It's (enabled, optional filename).
pub write_dependency_info: (bool, Option<Path>),
/// Crate id-related things to maybe print. It's (crate_id, crate_name, crate_file_name).
pub print_metas: (bool, bool, bool),
/// Crate id-related things to maybe print. It's (crate_name, crate_file_name).
pub print_metas: (bool, bool),
pub cg: CodegenOptions,
pub color: ColorConfig,
pub externs: HashMap<String, Vec<String>>,
pub crate_name: Option<String>,
}
/// Some reasonable defaults
@ -117,9 +119,11 @@ pub fn basic_options() -> Options {
no_analysis: false,
debugging_opts: 0,
write_dependency_info: (false, None),
print_metas: (false, false, false),
print_metas: (false, false),
cg: basic_codegen_options(),
color: Auto,
externs: HashMap::new(),
crate_name: None,
}
}
@ -318,6 +322,10 @@ fn parse_list(slot: &mut Vec<String>, v: Option<&str>)
"use an external assembler rather than LLVM's integrated one"),
relocation_model: String = ("pic".to_string(), parse_string,
"choose the relocation model to use (llc -relocation-model for details)"),
metadata: Vec<String> = (Vec::new(), parse_list,
"metadata to mangle symbol names with"),
extra_filename: String = ("".to_string(), parse_string,
"extra data to put in each output filename"),
)
pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
@ -505,10 +513,12 @@ pub fn optgroups() -> Vec<getopts::OptGroup> {
"[bin|lib|rlib|dylib|staticlib]"),
optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
"[asm|bc|ir|obj|link]"),
optflag("", "crate-id", "Output the crate id and exit"),
optflag("", "crate-name", "Output the crate name and exit"),
optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
optopt("", "crate-name", "Specify the name of the crate being built",
"NAME"),
optflag("", "print-crate-name", "Output the crate name and exit"),
optflag("", "print-file-name", "Output the file(s) that would be written if compilation \
continued and exit"),
optflag("", "crate-file-name", "deprecated in favor of --print-file-name"),
optflag("g", "", "Equivalent to --debuginfo=2"),
optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
0 = no debug info,
@ -548,7 +558,9 @@ pub fn optgroups() -> Vec<getopts::OptGroup> {
optopt("", "color", "Configure coloring of output:
auto = colorize, if output goes to a tty (default);
always = always colorize output;
never = never colorize output", "auto|always|never")
never = never colorize output", "auto|always|never"),
optmulti("", "extern", "Specify where an external rust library is located",
"PATH"),
)
}
@ -709,9 +721,13 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
matches.opt_str("dep-info")
.map(|p| Path::new(p)));
let print_metas = (matches.opt_present("crate-id"),
matches.opt_present("crate-name"),
let print_metas = (matches.opt_present("print-crate-name"),
matches.opt_present("print-file-name") ||
matches.opt_present("crate-file-name"));
if matches.opt_present("crate-file-name") {
early_warn("the --crate-file-name argument has been renamed to \
--print-file-name");
}
let cg = build_codegen_options(matches);
let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
@ -728,6 +744,23 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
}
};
let mut externs = HashMap::new();
for arg in matches.opt_strs("extern").iter() {
let mut parts = arg.as_slice().splitn('=', 1);
let name = match parts.next() {
Some(s) => s,
None => early_error("--extern value must not be empty"),
};
let location = match parts.next() {
Some(s) => s,
None => early_error("--extern value must be of the format `foo=bar`"),
};
let locs = externs.find_or_insert(name.to_string(), Vec::new());
locs.push(location.to_string());
}
let crate_name = matches.opt_str("crate-name");
Options {
crate_types: crate_types,
gc: gc,
@ -748,7 +781,9 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
write_dependency_info: write_dependency_info,
print_metas: print_metas,
cg: cg,
color: color
color: color,
externs: externs,
crate_name: crate_name,
}
}

View File

@ -41,7 +41,6 @@
use syntax::ast;
use syntax::attr;
use syntax::attr::{AttrMetaMethods};
use syntax::crateid::CrateId;
use syntax::parse;
use syntax::parse::token;
use syntax::print::{pp, pprust};
@ -69,7 +68,7 @@ pub fn compile_input(sess: Session,
// large chunks of memory alive and we want to free them as soon as
// possible to keep the peak memory usage low
let (outputs, trans, sess) = {
let (outputs, expanded_crate, ast_map) = {
let (outputs, expanded_crate, ast_map, id) = {
let krate = phase_1_parse_input(&sess, cfg, input);
if stop_after_phase_1(&sess) { return; }
let outputs = build_output_filenames(input,
@ -77,25 +76,25 @@ pub fn compile_input(sess: Session,
output,
krate.attrs.as_slice(),
&sess);
let id = link::find_crate_id(krate.attrs.as_slice(),
outputs.out_filestem.as_slice());
let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(),
input);
let (expanded_crate, ast_map)
= match phase_2_configure_and_expand(&sess, krate, &id) {
= match phase_2_configure_and_expand(&sess, krate, id.as_slice()) {
None => return,
Some(p) => p,
};
(outputs, expanded_crate, ast_map)
(outputs, expanded_crate, ast_map, id)
};
write_out_deps(&sess, input, &outputs, &expanded_crate);
write_out_deps(&sess, input, &outputs, id.as_slice());
if stop_after_phase_2(&sess) { return; }
let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
let analysis = phase_3_run_analysis_passes(sess, &expanded_crate,
ast_map, id);
phase_save_analysis(&analysis.ty_cx.sess, &expanded_crate, &analysis, outdir);
if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
analysis, &outputs);
let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate, analysis);
// Discard interned strings as they are no longer required.
token::get_ident_interner().clear();
@ -181,11 +180,14 @@ pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
/// Returns `None` if we're aborting after handling -W help.
pub fn phase_2_configure_and_expand(sess: &Session,
mut krate: ast::Crate,
crate_id: &CrateId)
crate_name: &str)
-> Option<(ast::Crate, syntax::ast_map::Map)> {
let time_passes = sess.time_passes();
*sess.crate_types.borrow_mut() = collect_crate_types(sess, krate.attrs.as_slice());
*sess.crate_types.borrow_mut() =
collect_crate_types(sess, krate.attrs.as_slice());
*sess.crate_metadata.borrow_mut() =
collect_crate_metadata(sess, krate.attrs.as_slice());
time(time_passes, "gated feature checking", (), |_|
front::feature_gate::check_crate(sess, &krate));
@ -247,7 +249,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
}
let cfg = syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: sess.features.default_type_params.get(),
crate_id: crate_id.clone(),
crate_name: crate_name.to_string(),
};
syntax::ext::expand::expand_crate(&sess.parse_sess,
cfg,
@ -286,6 +288,7 @@ pub struct CrateAnalysis {
pub public_items: middle::privacy::PublicItems,
pub ty_cx: ty::ctxt,
pub reachable: NodeSet,
pub name: String,
}
/// Run the resolution, typechecking, region checking and other
@ -293,7 +296,8 @@ pub struct CrateAnalysis {
/// structures carrying the results of the analysis.
pub fn phase_3_run_analysis_passes(sess: Session,
krate: &ast::Crate,
ast_map: syntax::ast_map::Map) -> CrateAnalysis {
ast_map: syntax::ast_map::Map,
name: String) -> CrateAnalysis {
let time_passes = sess.time_passes();
@ -398,6 +402,7 @@ pub fn phase_3_run_analysis_passes(sess: Session,
exported_items: exported_items,
public_items: public_items,
reachable: reachable_map,
name: name,
}
}
@ -426,8 +431,7 @@ pub struct CrateTranslation {
/// Run the translation phase to LLVM, after which the AST and analysis can
/// be discarded.
pub fn phase_4_translate_to_llvm(krate: ast::Crate,
analysis: CrateAnalysis,
outputs: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
analysis: CrateAnalysis) -> (ty::ctxt, CrateTranslation) {
let time_passes = analysis.ty_cx.sess.time_passes();
time(time_passes, "resolving dependency formats", (), |_|
@ -435,7 +439,7 @@ pub fn phase_4_translate_to_llvm(krate: ast::Crate,
// Option dance to work around the lack of stack once closures.
time(time_passes, "translation", (krate, analysis), |(krate, analysis)|
trans::base::trans_crate(krate, analysis, outputs))
trans::base::trans_crate(krate, analysis))
}
/// Run LLVM itself, producing a bitcode file, assembly file or object file
@ -473,7 +477,7 @@ pub fn phase_6_link_output(sess: &Session,
link::link_binary(sess,
trans,
outputs,
&trans.link.crateid));
trans.link.crate_name.as_slice()));
}
pub fn stop_after_phase_3(sess: &Session) -> bool {
@ -514,9 +518,7 @@ pub fn stop_after_phase_5(sess: &Session) -> bool {
fn write_out_deps(sess: &Session,
input: &Input,
outputs: &OutputFilenames,
krate: &ast::Crate) {
let id = link::find_crate_id(krate.attrs.as_slice(),
outputs.out_filestem.as_slice());
id: &str) {
let mut out_filenames = Vec::new();
for output_type in sess.opts.output_types.iter() {
@ -524,7 +526,8 @@ fn write_out_deps(sess: &Session,
match *output_type {
link::OutputTypeExe => {
for output in sess.crate_types.borrow().iter() {
let p = link::filename_for_input(sess, *output, &id, &file);
let p = link::filename_for_input(sess, *output,
id, &file);
out_filenames.push(p);
}
}
@ -649,13 +652,13 @@ pub fn pretty_print_input(sess: Session,
ppm: PpMode,
ofile: Option<Path>) {
let krate = phase_1_parse_input(&sess, cfg, input);
let id = link::find_crate_id(krate.attrs.as_slice(),
input.filestem().as_slice());
let id = link::find_crate_name(Some(&sess), krate.attrs.as_slice(), input);
let (krate, ast_map, is_expanded) = match ppm {
PpmExpanded | PpmExpandedIdentified | PpmTyped | PpmFlowGraph(_) => {
let (krate, ast_map)
= match phase_2_configure_and_expand(&sess, krate, &id) {
= match phase_2_configure_and_expand(&sess, krate,
id.as_slice()) {
None => return,
Some(p) => p,
};
@ -695,7 +698,7 @@ pub fn pretty_print_input(sess: Session,
}
PpmTyped => {
let ast_map = ast_map.expect("--pretty=typed missing ast_map");
let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map, id);
let annotation = TypedAnnotation {
analysis: analysis
};
@ -728,7 +731,8 @@ pub fn pretty_print_input(sess: Session,
}
}
};
let analysis = phase_3_run_analysis_passes(sess, &krate, ast_map);
let analysis = phase_3_run_analysis_passes(sess, &krate,
ast_map, id);
print_flowgraph(analysis, block, out)
}
_ => {
@ -845,6 +849,11 @@ pub fn collect_crate_types(session: &Session,
}).collect()
}
pub fn collect_crate_metadata(session: &Session,
_attrs: &[ast::Attribute]) -> Vec<String> {
session.opts.cg.metadata.clone()
}
pub struct OutputFilenames {
pub out_directory: Path,
pub out_filestem: String,
@ -893,14 +902,11 @@ pub fn build_output_filenames(input: &Input,
None => Path::new(".")
};
let mut stem = input.filestem();
// If a crateid is present, we use it as the link name
let crateid = attr::find_crateid(attrs);
match crateid {
None => {}
Some(crateid) => stem = crateid.name.to_string(),
}
// If a crate name is present, we use it as the link name
let stem = match attr::find_crate_name(attrs) {
None => input.filestem(),
Some(name) => name.get().to_string(),
};
OutputFilenames {
out_directory: dirpath,
out_filestem: stem,

View File

@ -294,28 +294,26 @@ fn print_crate_info(sess: &Session,
odir: &Option<Path>,
ofile: &Option<Path>)
-> bool {
let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
let (crate_name, crate_file_name) = sess.opts.print_metas;
// these nasty nested conditions are to avoid doing extra work
if crate_id || crate_name || crate_file_name {
if crate_name || crate_file_name {
let attrs = parse_crate_attrs(sess, input);
let t_outputs = driver::build_output_filenames(input,
odir,
ofile,
attrs.as_slice(),
sess);
let id = link::find_crate_id(attrs.as_slice(),
t_outputs.out_filestem.as_slice());
let id = link::find_crate_name(Some(sess), attrs.as_slice(), input);
if crate_id {
println!("{}", id.to_str());
}
if crate_name {
println!("{}", id.name);
println!("{}", id);
}
if crate_file_name {
let crate_types = driver::collect_crate_types(sess, attrs.as_slice());
let metadata = driver::collect_crate_metadata(sess, attrs.as_slice());
*sess.crate_metadata.borrow_mut() = metadata;
for &style in crate_types.iter() {
let fname = link::filename_for_input(sess, style, &id,
let fname = link::filename_for_input(sess, style, id.as_slice(),
&t_outputs.with_extension(""));
println!("{}", fname.filename_display());
}
@ -390,6 +388,11 @@ pub fn early_error(msg: &str) -> ! {
fail!(diagnostic::FatalError);
}
pub fn early_warn(msg: &str) {
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto);
emitter.emit(None, msg, diagnostic::Warning);
}
pub fn list_metadata(sess: &Session, path: &Path,
out: &mut io::Writer) -> io::IoResult<()> {
metadata::loader::list_file_metadata(sess.targ_cfg.os, path, out)

View File

@ -47,6 +47,7 @@ pub struct Session {
pub lints: RefCell<NodeMap<Vec<(lint::LintId, codemap::Span, String)>>>,
pub node_id: Cell<ast::NodeId>,
pub crate_types: RefCell<Vec<config::CrateType>>,
pub crate_metadata: RefCell<Vec<String>>,
pub features: front::feature_gate::Features,
/// The maximum recursion limit for potentially infinitely recursive
@ -243,6 +244,7 @@ pub fn build_session_(sopts: config::Options,
lints: RefCell::new(NodeMap::new()),
node_id: Cell::new(1),
crate_types: RefCell::new(Vec::new()),
crate_metadata: RefCell::new(Vec::new()),
features: front::feature_gate::Features::new(),
recursion_limit: Cell::new(64),
};

View File

@ -25,8 +25,6 @@
use std::mem;
use std::gc::{Gc, GC};
pub static VERSION: &'static str = "0.11.0";
pub fn maybe_inject_crates_ref(sess: &Session, krate: ast::Crate)
-> ast::Crate {
if use_std(&krate) {
@ -60,24 +58,12 @@ struct StandardLibraryInjector<'a> {
sess: &'a Session,
}
pub fn with_version(krate: &str) -> Option<(InternedString, ast::StrStyle)> {
match option_env!("CFG_DISABLE_INJECT_STD_VERSION") {
Some("1") => None,
_ => {
Some((token::intern_and_get_ident(format!("{}#{}",
krate,
VERSION).as_slice()),
ast::CookedStr))
}
}
}
impl<'a> fold::Folder for StandardLibraryInjector<'a> {
fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
let mut vis = vec!(ast::ViewItem {
node: ast::ViewItemExternCrate(token::str_to_ident("std"),
with_version("std"),
ast::DUMMY_NODE_ID),
None,
ast::DUMMY_NODE_ID),
attrs: vec!(
attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_list_item(
InternedString::new("phase"),
@ -95,8 +81,8 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
if use_start(&krate) && any_exe {
vis.push(ast::ViewItem {
node: ast::ViewItemExternCrate(token::str_to_ident("native"),
with_version("native"),
ast::DUMMY_NODE_ID),
None,
ast::DUMMY_NODE_ID),
attrs: Vec::new(),
vis: ast::Inherited,
span: DUMMY_SP

View File

@ -15,7 +15,6 @@
use driver::session::Session;
use front::config;
use front::std_inject::with_version;
use std::cell::RefCell;
use std::gc::{Gc, GC};
@ -154,7 +153,7 @@ fn generate_test_harness(sess: &Session, krate: ast::Crate)
ext_cx: ExtCtxt::new(&sess.parse_sess, sess.opts.cfg.clone(),
ExpansionConfig {
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
crate_name: "test".to_string(),
}),
path: RefCell::new(Vec::new()),
testfns: RefCell::new(Vec::new()),
@ -298,9 +297,7 @@ fn mk_std(cx: &TestCtxt) -> ast::ViewItem {
ast::DUMMY_NODE_ID))),
ast::Public)
} else {
(ast::ViewItemExternCrate(id_test,
with_version("test"),
ast::DUMMY_NODE_ID),
(ast::ViewItemExternCrate(id_test, None, ast::DUMMY_NODE_ID),
ast::Inherited)
};
ast::ViewItem {
@ -395,8 +392,8 @@ fn mk_tests(cx: &TestCtxt) -> Gc<ast::Item> {
}
fn is_test_crate(krate: &ast::Crate) -> bool {
match attr::find_crateid(krate.attrs.as_slice()) {
Some(ref s) if "test" == s.name.as_slice() => true,
match attr::find_crate_name(krate.attrs.as_slice()) {
Some(ref s) if "test" == s.get().as_slice() => true,
_ => false
}
}

View File

@ -18,7 +18,8 @@
*/
#![crate_id = "rustc#0.11.0"]
#![crate_id = "rustc#0.11.0"] // NOTE: remove after stage0
#![crate_name = "rustc"]
#![experimental]
#![comment = "The Rust compiler"]
#![license = "MIT/ASL2"]
@ -31,6 +32,7 @@
#![allow(deprecated)]
#![feature(macro_rules, globs, struct_variant, managed_boxes, quote)]
#![feature(default_type_params, phase, unsafe_destructor)]
#![allow(unused_attribute)] // NOTE: remove after stage0
extern crate arena;
extern crate debug;

View File

@ -11,7 +11,6 @@
#![allow(non_camel_case_types)]
use std::mem;
use syntax::crateid::CrateId;
use back::svh::Svh;
// EBML enum definitions and utils shared by the encoder and decoder
@ -71,9 +70,9 @@
pub static tag_crate_dep: uint = 0x19;
pub static tag_crate_hash: uint = 0x1a;
pub static tag_crate_crateid: uint = 0x1b;
pub static tag_crate_crate_name: uint = 0x1b;
pub static tag_crate_dep_crateid: uint = 0x1d;
pub static tag_crate_dep_crate_name: uint = 0x1d;
pub static tag_crate_dep_hash: uint = 0x1e;
pub static tag_mod_impl: uint = 0x1f;
@ -215,7 +214,7 @@ pub fn from_uint(value : uint) -> Option<astencode_tag> {
#[deriving(Clone, Show)]
pub struct LinkMeta {
pub crateid: CrateId,
pub crate_name: String,
pub crate_hash: Svh,
}

View File

@ -12,7 +12,6 @@
//! Validates all used crates and extern libraries and loads their metadata
use back::link;
use back::svh::Svh;
use driver::session::Session;
use driver::{driver, config};
@ -33,7 +32,6 @@
use syntax::diagnostic::SpanHandler;
use syntax::parse::token::InternedString;
use syntax::parse::token;
use syntax::crateid::CrateId;
use syntax::visit;
struct Env<'a> {
@ -69,7 +67,7 @@ fn visit_item(&mut self, a: &ast::Item, _: ()) {
fn dump_crates(cstore: &CStore) {
debug!("resolved crates:");
cstore.iter_crate_data_origins(|_, data, opt_source| {
debug!("crate_id: {}", data.crate_id());
debug!(" name: {}", data.name());
debug!(" cnum: {}", data.cnum);
debug!(" hash: {}", data.hash());
opt_source.map(|cs| {
@ -83,20 +81,17 @@ fn dump_crates(cstore: &CStore) {
fn warn_if_multiple_versions(diag: &SpanHandler, cstore: &CStore) {
let mut map = HashMap::new();
cstore.iter_crate_data(|cnum, data| {
let crateid = data.crate_id();
let key = (crateid.name.clone(), crateid.path.clone());
map.find_or_insert_with(key, |_| Vec::new()).push(cnum);
map.find_or_insert_with(data.name(), |_| Vec::new()).push(cnum);
});
for ((name, _), dupes) in map.move_iter() {
for (name, dupes) in map.move_iter() {
if dupes.len() == 1 { continue }
diag.handler().warn(
format!("using multiple versions of crate `{}`",
name).as_slice());
format!("using multiple versions of crate `{}`", name).as_slice());
for dupe in dupes.move_iter() {
let data = cstore.get_crate_data(dupe);
diag.span_note(data.span, "used here");
loader::note_crateid_attr(diag, &data.crate_id());
loader::note_crate_name(diag, data.name().as_slice());
}
}
}
@ -129,7 +124,7 @@ fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
let (cnum, _, _) = resolve_crate(e,
&None,
info.ident.as_slice(),
&info.crate_id,
info.name.as_slice(),
None,
i.span);
e.sess.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
@ -140,7 +135,7 @@ fn visit_view_item(e: &mut Env, i: &ast::ViewItem) {
struct CrateInfo {
ident: String,
crate_id: CrateId,
name: String,
id: ast::NodeId,
should_link: bool,
}
@ -151,22 +146,18 @@ fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option<CrateInfo> {
let ident = token::get_ident(ident);
debug!("resolving extern crate stmt. ident: {:?} path_opt: {:?}",
ident, path_opt);
let crate_id = match *path_opt {
let name = match *path_opt {
Some((ref path_str, _)) => {
let crateid: Option<CrateId> = from_str(path_str.get());
match crateid {
None => {
e.sess.span_err(i.span, "malformed crate id");
return None
}
Some(id) => id
}
let name = path_str.get().to_str();
validate_crate_name(Some(e.sess), name.as_slice(),
Some(i.span));
name
}
None => from_str(ident.get().to_str().as_slice()).unwrap()
None => ident.get().to_str(),
};
Some(CrateInfo {
ident: ident.get().to_string(),
crate_id: crate_id,
name: name,
id: id,
should_link: should_link(i),
})
@ -175,6 +166,28 @@ fn extract_crate_info(e: &Env, i: &ast::ViewItem) -> Option<CrateInfo> {
}
}
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
let err = |s: &str| {
match (sp, sess) {
(_, None) => fail!("{}", s),
(Some(sp), Some(sess)) => sess.span_err(sp, s),
(None, Some(sess)) => sess.err(s),
}
};
if s.len() == 0 {
err("crate name must not be empty");
}
for c in s.chars() {
if c.is_alphanumeric() { continue }
if c == '_' || c == '-' { continue }
err(format!("invalid character `{}` in crate name: `{}`", c, s).as_slice());
}
match sess {
Some(sess) => sess.abort_if_errors(),
None => {}
}
}
fn visit_item(e: &Env, i: &ast::Item) {
match i.node {
ast::ItemForeignMod(ref fm) => {
@ -263,17 +276,36 @@ fn visit_item(e: &Env, i: &ast::Item) {
}
}
fn existing_match(e: &Env, crate_id: &CrateId,
fn existing_match(e: &Env, name: &str,
hash: Option<&Svh>) -> Option<ast::CrateNum> {
let mut ret = None;
e.sess.cstore.iter_crate_data(|cnum, data| {
let other_id = data.crate_id();
if crate_id.matches(&other_id) {
let other_hash = data.hash();
match hash {
Some(hash) if *hash != other_hash => {}
Some(..) | None => { ret = Some(cnum); }
if data.name().as_slice() != name { return }
match hash {
Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
Some(..) => return,
None => {}
}
// When the hash is None we're dealing with a top-level dependency in
// which case we may have a specification on the command line for this
// library. Even though an upstream library may have loaded something of
// the same name, we have to make sure it was loaded from the exact same
// location as well.
let source = e.sess.cstore.get_used_crate_source(cnum).unwrap();
let dylib = source.dylib.as_ref().map(|p| p.as_vec());
let rlib = source.rlib.as_ref().map(|p| p.as_vec());
match e.sess.opts.externs.find_equiv(&name) {
Some(locs) => {
let found = locs.iter().any(|l| {
Some(l.as_bytes()) == dylib || Some(l.as_bytes()) == rlib
});
if found {
ret = Some(cnum);
}
}
None => ret = Some(cnum),
}
});
return ret;
@ -282,7 +314,7 @@ fn existing_match(e: &Env, crate_id: &CrateId,
fn register_crate<'a>(e: &mut Env,
root: &Option<CratePaths>,
ident: &str,
crate_id: &CrateId,
name: &str,
span: Span,
lib: loader::Library)
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
@ -309,7 +341,7 @@ fn register_crate<'a>(e: &mut Env,
let loader::Library{ dylib, rlib, metadata } = lib;
let cmeta = Rc::new( cstore::crate_metadata {
name: crate_id.name.to_string(),
name: name.to_string(),
data: metadata,
cnum_map: cnum_map,
cnum: cnum,
@ -330,20 +362,18 @@ fn register_crate<'a>(e: &mut Env,
fn resolve_crate<'a>(e: &mut Env,
root: &Option<CratePaths>,
ident: &str,
crate_id: &CrateId,
name: &str,
hash: Option<&Svh>,
span: Span)
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
cstore::CrateSource) {
match existing_match(e, crate_id, hash) {
match existing_match(e, name, hash) {
None => {
let id_hash = link::crate_id_hash(crate_id);
let mut load_ctxt = loader::Context {
sess: e.sess,
span: span,
ident: ident,
crate_id: crate_id,
id_hash: id_hash.as_slice(),
crate_name: name,
hash: hash.map(|a| &*a),
filesearch: e.sess.target_filesearch(),
os: e.sess.targ_cfg.os,
@ -351,9 +381,10 @@ fn resolve_crate<'a>(e: &mut Env,
root: root,
rejected_via_hash: vec!(),
rejected_via_triple: vec!(),
should_match_name: true,
};
let library = load_ctxt.load_library_crate();
register_crate(e, root, ident, crate_id, span, library)
register_crate(e, root, ident, name, span, library)
}
Some(cnum) => (cnum,
e.sess.cstore.get_crate_data(cnum),
@ -370,10 +401,10 @@ fn resolve_crate_deps(e: &mut Env,
// The map from crate numbers in the crate we're resolving to local crate
// numbers
decoder::get_crate_deps(cdata).iter().map(|dep| {
debug!("resolving dep crate {} hash: `{}`", dep.crate_id, dep.hash);
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
let (local_cnum, _, _) = resolve_crate(e, root,
dep.crate_id.name.as_slice(),
&dep.crate_id,
dep.name.as_slice(),
dep.name.as_slice(),
Some(&dep.hash),
span);
(dep.cnum, local_cnum)
@ -399,14 +430,12 @@ pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata
let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice();
let is_cross = target_triple != driver::host_triple();
let mut should_link = info.should_link && !is_cross;
let id_hash = link::crate_id_hash(&info.crate_id);
let os = config::get_os(driver::host_triple()).unwrap();
let mut load_ctxt = loader::Context {
sess: self.env.sess,
span: krate.span,
ident: info.ident.as_slice(),
crate_id: &info.crate_id,
id_hash: id_hash.as_slice(),
crate_name: info.name.as_slice(),
hash: None,
filesearch: self.env.sess.host_filesearch(),
triple: driver::host_triple(),
@ -414,6 +443,7 @@ pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata
root: &None,
rejected_via_hash: vec!(),
rejected_via_triple: vec!(),
should_match_name: true,
};
let library = match load_ctxt.maybe_load_library_crate() {
Some (l) => l,
@ -448,10 +478,11 @@ pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata
macros: macros,
registrar_symbol: registrar,
};
if should_link && existing_match(&self.env, &info.crate_id, None).is_none() {
if should_link && existing_match(&self.env, info.name.as_slice(),
None).is_none() {
// register crate now to avoid double-reading metadata
register_crate(&mut self.env, &None, info.ident.as_slice(),
&info.crate_id, krate.span, library);
info.name.as_slice(), krate.span, library);
}
pc
}

View File

@ -22,7 +22,6 @@
use std::rc::Rc;
use std::collections::HashMap;
use syntax::ast;
use syntax::crateid::CrateId;
use syntax::codemap::Span;
use syntax::parse::token::IdentInterner;
@ -220,7 +219,7 @@ pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
impl crate_metadata {
pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
pub fn crate_id(&self) -> CrateId { decoder::get_crate_id(self.data()) }
pub fn name(&self) -> String { decoder::get_crate_name(self.data()) }
pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
}

View File

@ -46,7 +46,6 @@
use syntax::print::pprust;
use syntax::ast;
use syntax::codemap;
use syntax::crateid::CrateId;
pub type Cmd<'a> = &'a crate_metadata;
@ -1101,7 +1100,7 @@ pub fn get_crate_attributes(data: &[u8]) -> Vec<ast::Attribute> {
#[deriving(Clone)]
pub struct CrateDep {
pub cnum: ast::CrateNum,
pub crate_id: CrateId,
pub name: String,
pub hash: Svh,
}
@ -1115,13 +1114,11 @@ fn docstr(doc: ebml::Doc, tag_: uint) -> String {
d.as_str_slice().to_string()
}
reader::tagged_docs(depsdoc, tag_crate_dep, |depdoc| {
let crate_id =
from_str(docstr(depdoc,
tag_crate_dep_crateid).as_slice()).unwrap();
let name = docstr(depdoc, tag_crate_dep_crate_name);
let hash = Svh::new(docstr(depdoc, tag_crate_dep_hash).as_slice());
deps.push(CrateDep {
cnum: crate_num,
crate_id: crate_id,
name: name,
hash: hash,
});
crate_num += 1;
@ -1133,7 +1130,7 @@ fn docstr(doc: ebml::Doc, tag_: uint) -> String {
fn list_crate_deps(data: &[u8], out: &mut io::Writer) -> io::IoResult<()> {
try!(write!(out, "=External Dependencies=\n"));
for dep in get_crate_deps(data).iter() {
try!(write!(out, "{} {}-{}\n", dep.cnum, dep.crate_id, dep.hash));
try!(write!(out, "{} {}-{}\n", dep.cnum, dep.name, dep.hash));
}
try!(write!(out, "\n"));
Ok(())
@ -1152,23 +1149,21 @@ pub fn get_crate_hash(data: &[u8]) -> Svh {
Svh::new(hashdoc.as_str_slice())
}
pub fn maybe_get_crate_id(data: &[u8]) -> Option<CrateId> {
pub fn maybe_get_crate_name(data: &[u8]) -> Option<String> {
let cratedoc = ebml::Doc::new(data);
reader::maybe_get_doc(cratedoc, tag_crate_crateid).map(|doc| {
from_str(doc.as_str_slice()).unwrap()
reader::maybe_get_doc(cratedoc, tag_crate_crate_name).map(|doc| {
doc.as_str_slice().to_string()
})
}
pub fn get_crate_triple(data: &[u8]) -> String {
pub fn get_crate_triple(data: &[u8]) -> Option<String> {
let cratedoc = ebml::Doc::new(data);
let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple);
triple_doc.expect("No triple in crate").as_str().to_string()
triple_doc.map(|s| s.as_str().to_string())
}
pub fn get_crate_id(data: &[u8]) -> CrateId {
let cratedoc = ebml::Doc::new(data);
let hashdoc = reader::get_doc(cratedoc, tag_crate_crateid);
from_str(hashdoc.as_str_slice()).unwrap()
pub fn get_crate_name(data: &[u8]) -> String {
maybe_get_crate_name(data).expect("no crate name in crate")
}
pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Writer) -> io::IoResult<()> {

View File

@ -44,11 +44,9 @@
use syntax::ast_map;
use syntax::ast_util::*;
use syntax::ast_util;
use syntax::attr::AttrMetaMethods;
use syntax::attr;
use syntax::crateid::CrateId;
use syntax::attr::AttrMetaMethods;
use syntax::diagnostic::SpanHandler;
use syntax::parse::token::InternedString;
use syntax::parse::token::special_idents;
use syntax::parse::token;
use syntax::visit::Visitor;
@ -1494,35 +1492,6 @@ fn encode_attributes(ebml_w: &mut Encoder, attrs: &[Attribute]) {
ebml_w.end_tag();
}
// So there's a special crate attribute called 'crate_id' 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,
krate: &Crate) -> Vec<Attribute> {
fn synthesize_crateid_attr(ecx: &EncodeContext) -> Attribute {
assert!(!ecx.link_meta.crateid.name.is_empty());
attr::mk_attr_inner(attr::mk_attr_id(),
attr::mk_name_value_item_str(
InternedString::new("crate_id"),
token::intern_and_get_ident(ecx.link_meta
.crateid
.to_str()
.as_slice())))
}
let mut attrs = Vec::new();
for attr in krate.attrs.iter() {
if !attr.check_name("crate_id") {
attrs.push(*attr);
}
}
attrs.push(synthesize_crateid_attr(ecx));
attrs
}
fn encode_crate_deps(ebml_w: &mut Encoder, cstore: &cstore::CStore) {
fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
// Pull the cnums and name,vers,hash out of cstore
@ -1530,8 +1499,8 @@ fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
cstore.iter_crate_data(|key, val| {
let dep = decoder::CrateDep {
cnum: key,
crate_id: decoder::get_crate_id(val.data()),
hash: decoder::get_crate_hash(val.data())
name: decoder::get_crate_name(val.data()),
hash: decoder::get_crate_hash(val.data()),
};
deps.push(dep);
});
@ -1766,8 +1735,8 @@ fn encode_reachable_extern_fns(ecx: &EncodeContext, ebml_w: &mut Encoder) {
fn encode_crate_dep(ebml_w: &mut Encoder,
dep: decoder::CrateDep) {
ebml_w.start_tag(tag_crate_dep);
ebml_w.start_tag(tag_crate_dep_crateid);
ebml_w.writer.write(dep.crate_id.to_str().as_bytes());
ebml_w.start_tag(tag_crate_dep_crate_name);
ebml_w.writer.write(dep.name.as_bytes());
ebml_w.end_tag();
ebml_w.start_tag(tag_crate_dep_hash);
ebml_w.writer.write(dep.hash.as_str().as_bytes());
@ -1781,9 +1750,9 @@ fn encode_hash(ebml_w: &mut Encoder, hash: &Svh) {
ebml_w.end_tag();
}
fn encode_crate_id(ebml_w: &mut Encoder, crate_id: &CrateId) {
ebml_w.start_tag(tag_crate_crateid);
ebml_w.writer.write(crate_id.to_str().as_bytes());
fn encode_crate_name(ebml_w: &mut Encoder, crate_name: &str) {
ebml_w.start_tag(tag_crate_crate_name);
ebml_w.writer.write(crate_name.as_bytes());
ebml_w.end_tag();
}
@ -1880,7 +1849,7 @@ struct Stats {
let mut ebml_w = writer::Encoder::new(wr);
encode_crate_id(&mut ebml_w, &ecx.link_meta.crateid);
encode_crate_name(&mut ebml_w, ecx.link_meta.crate_name.as_slice());
encode_crate_triple(&mut ebml_w,
tcx.sess
.targ_cfg
@ -1891,8 +1860,7 @@ struct Stats {
encode_dylib_dependency_formats(&mut ebml_w, &ecx);
let mut i = ebml_w.writer.tell().unwrap();
let crate_attrs = synthesize_crate_attrs(&ecx, krate);
encode_attributes(&mut ebml_w, crate_attrs.as_slice());
encode_attributes(&mut ebml_w, krate.attrs.as_slice());
stats.attr_bytes = ebml_w.writer.tell().unwrap() - i;
i = ebml_w.writer.tell().unwrap();

View File

@ -9,6 +9,208 @@
// except according to those terms.
//! Finds crate binaries and loads their metadata
//!
//! Might I be the first to welcome you to a world of platform differences,
//! version requirements, dependency graphs, conficting desires, and fun! This
//! is the major guts (along with metadata::creader) of the compiler for loading
//! crates and resolving dependencies. Let's take a tour!
//!
//! # The problem
//!
//! Each invocation of the compiler is immediately concerned with one primary
//! problem, to connect a set of crates to resolved crates on the filesystem.
//! Concretely speaking, the compiler follows roughly these steps to get here:
//!
//! 1. Discover a set of `extern crate` statements.
//! 2. Transform these directives into crate names. If the directive does not
//! have an explicit name, then the identifier is the name.
//! 3. For each of these crate names, find a corresponding crate on the
//! filesystem.
//!
//! Sounds easy, right? Let's walk into some of the nuances.
//!
//! ## Transitive Dependencies
//!
//! Let's say we've got three crates: A, B, and C. A depends on B, and B depends
//! on C. When we're compiling A, we primarily need to find and locate B, but we
//! also end up needing to find and locate C as well.
//!
//! The reason for this is that any of B's types could be composed of C's types,
//! any function in B could return a type from C, etc. To be able to guarantee
//! that we can always typecheck/translate any function, we have to have
//! complete knowledge of the whole ecosystem, not just our immediate
//! dependencies.
//!
//! So now as part of the "find a corresponding crate on the filesystem" step
//! above, this involves also finding all crates for *all upstream
//! dependencies*. This includes all dependencies transitively.
//!
//! ## Rlibs and Dylibs
//!
//! The compiler has two forms of intermediate dependencies. These are dubbed
//! rlibs and dylibs for the static and dynamic variants, respectively. An rlib
//! is a rustc-defined file format (currently just an ar archive) while a dylib
//! is a platform-defined dynamic library. Each library has a metadata somewhere
//! inside of it.
//!
//! When translating a crate name to a crate on the filesystem, we all of a
//! sudden need to take into account both rlibs and dylibs! Linkage later on may
//! use either one of these files, as each has their pros/cons. The job of crate
//! loading is to discover what's possible by finding all candidates.
//!
//! Most parts of this loading systems keep the dylib/rlib as just separate
//! variables.
//!
//! ## Where to look?
//!
//! We can't exactly scan your whole hard drive when looking for dependencies,
//! so we need to places to look. Currently the compiler will implicitly add the
//! target lib search path ($prefix/lib/rustlib/$target/lib) to any compilation,
//! and otherwise all -L flags are added to the search paths.
//!
//! ## What criterion to select on?
//!
//! This a pretty tricky area of loading crates. Given a file, how do we know
//! whether it's the right crate? Currently, the rules look along these lines:
//!
//! 1. Does the filename match an rlib/dylib pattern? That is to say, does the
//! filename have the right prefix/suffix?
//! 2. Does the filename have the right prefix for the crate name being queried?
//! This is filtering for files like `libfoo*.rlib` and such.
//! 3. Is the file an actual rust library? This is done by loading the metadata
//! from the library and making sure it's actually there.
//! 4. Does the name in the metadata agree with the name of the library?
//! 5. Does the target in the metadata agree with the current target?
//! 6. Does the SVH match? (more on this later)
//!
//! If the file answeres `yes` to all these questions, then the file is
//! considered as being *candidate* for being accepted. It is illegal to have
//! more than two candidates as the compiler has no method by which to resolve
//! this conflict. Additionally, rlib/dylib candidates are considered
//! separately.
//!
//! After all this has happened, we have 1 or two files as candidates. These
//! represent the rlib/dylib file found for a library, and they're returned as
//! being found.
//!
//! ### What about versions?
//!
//! A lot of effort has been put forth to remove versioning from the compiler.
//! There have been forays in the past to have versioning baked in, but it was
//! largely always deemed insufficient to the point that it was recognized that
//! it's probably something the compiler shouldn't do anyway due to its
//! complicated nature and the state of the half-baked solutions.
//!
//! With a departure from versioning, the primary criterion for loading crates
//! is just the name of a crate. If we stopped here, it would imply that you
//! could never link two crates of the same name from different sources
//! together, which is clearly a bad state to be in.
//!
//! To resolve this problem, we come to the next section!
//!
//! # Expert Mode
//!
//! A number of flags have been added to the compiler to solve the "version
//! problem" in the previous section, as well as generally enabling more
//! powerful usage of the crate loading system of the compiler. The goal of
//! these flags and options are to enable third-party tools to drive the
//! compiler with prior knowledge about how the world should look.
//!
//! ## The `--extern` flag
//!
//! The compiler accepts a flag of this form a number of times:
//!
//! ```notrust
//! --extern crate-name=path/to/the/crate.rlib
//! ```
//!
//! This flag is basically the following letter to the compiler:
//!
//! > Dear rustc,
//! >
//! > When you are attempting to load the immediate dependency `crate-name`, I
//! > would like you too assume that the library is located at
//! > `path/to/the/crate.rlib`, and look nowhere else. Also, please do not
//! > assume that the path I specified has the name `crate-name`.
//!
//! This flag basically overrides most matching logic except for validating that
//! the file is indeed a rust library. The same `crate-name` can be specified
//! twice to specify the rlib/dylib pair.
//!
//! ## Enabling "multiple versions"
//!
//! This basically boils down to the ability to specify arbitrary packages to
//! the compiler. For example, if crate A wanted to use Bv1 and Bv2, then it
//! would look something like:
//!
//! ```ignore
//! extern crate b1;
//! extern crate b2;
//!
//! fn main() {}
//! ```
//!
//! and the compiler would be invoked as:
//!
//! ```notrust
//! rustc a.rs --extern b1=path/to/libb1.rlib --extern b2=path/to/libb2.rlib
//! ```
//!
//! In this scenario there are two crates named `b` and the compiler must be
//! manually driven to be informed where each crate is.
//!
//! ## Frobbing symbols
//!
//! One of the immediate problems with linking the same library together twice
//! in the same problem is dealing with duplicate symbols. The primary way to
//! deal with this in rustc is to add hashes to the end of each symbol.
//!
//! In order to force hashes to change between versions of a library, if
//! desired, the compiler exposes an option `-C metadata=foo`, which is used to
//! initially seed each symbol hash. The string `foo` is prepended to each
//! string-to-hash to ensure that symbols change over time.
//!
//! ## Loading transitive dependencies
//!
//! Dealing with same-named-but-distinct crates is not just a local problem, but
//! one that also needs to be dealt with for transitive dependences. Note that
//! in the letter above `--extern` flags only apply to the *local* set of
//! dependencies, not the upstream transitive dependencies. Consider this
//! dependency graph:
//!
//! ```notrust
//! A.1 A.2
//! | |
//! | |
//! B C
//! \ /
//! \ /
//! D
//! ```
//!
//! In this scenario, when we compile `D`, we need to be able to distinctly
//! resolve `A.1` and `A.2`, but an `--extern` flag cannot apply to these
//! transitive dependencies.
//!
//! Note that the key idea here is that `B` and `C` are both *already compiled*.
//! That is, they have already resolved their dependencies. Due to unrelated
//! technical reasons, when a library is compiled, it is only compatible with
//! the *exact same* version of the upstream libraries it was compiled against.
//! We use the "Strict Version Hash" to identify the exact copy of an upstream
//! library.
//!
//! With this knowledge, we know that `B` and `C` will depend on `A` with
//! different SVH values, so we crawl the normal `-L` paths looking for
//! `liba*.rlib` and filter based on the contained SVH.
//!
//! In the end, this ends up not needing `--extern` to specify upstream
//! transitive dependencies.
//!
//! # Wrapping up
//!
//! That's the general overview of loading crates in the compiler, but it's by
//! no means all of the necessary details. Take a look at the rest of
//! metadata::loader or metadata::creader for all the juicy details!
use back::archive::{ArchiveRO, METADATA_FILENAME};
use back::svh::Svh;
@ -21,8 +223,6 @@
use syntax::abi;
use syntax::codemap::Span;
use syntax::diagnostic::SpanHandler;
use syntax::crateid::CrateId;
use syntax::attr::AttrMetaMethods;
use util::fs;
use std::c_str::ToCStr;
@ -61,8 +261,7 @@ pub struct Context<'a> {
pub sess: &'a Session,
pub span: Span,
pub ident: &'a str,
pub crate_id: &'a CrateId,
pub id_hash: &'a str,
pub crate_name: &'a str,
pub hash: Option<&'a Svh>,
pub triple: &'a str,
pub os: abi::Os,
@ -70,6 +269,7 @@ pub struct Context<'a> {
pub root: &'a Option<CratePaths>,
pub rejected_via_hash: Vec<CrateMismatch>,
pub rejected_via_triple: Vec<CrateMismatch>,
pub should_match_name: bool,
}
pub struct Library {
@ -167,19 +367,30 @@ pub fn report_load_errs(&mut self) {
}
fn find_library_crate(&mut self) -> Option<Library> {
// If an SVH is specified, then this is a transitive dependency that
// must be loaded via -L plus some filtering.
if self.hash.is_none() {
self.should_match_name = false;
match self.find_commandline_library() {
Some(l) => return Some(l),
None => {}
}
self.should_match_name = true;
}
let dypair = self.dylibname();
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
let dylib_prefix = dypair.map(|(prefix, _)| {
format!("{}{}-", prefix, self.crate_id.name)
format!("{}{}", prefix, self.crate_name)
});
let rlib_prefix = format!("lib{}-", self.crate_id.name);
let rlib_prefix = format!("lib{}", self.crate_name);
let mut candidates = HashMap::new();
// First, find all possible candidate rlibs and dylibs purely based on
// the name of the files themselves. We're trying to match against an
// exact crate_id and a possibly an exact hash.
// exact crate name and a possibly an exact hash.
//
// During this step, we can filter all found libraries based on the
// name and id found in the crate id (we ignore the path portion for
@ -195,49 +406,32 @@ fn find_library_crate(&mut self) -> Option<Library> {
None => return FileDoesntMatch,
Some(file) => file,
};
if file.starts_with(rlib_prefix.as_slice()) &&
let (hash, rlib) = if file.starts_with(rlib_prefix.as_slice()) &&
file.ends_with(".rlib") {
info!("rlib candidate: {}", path.display());
match self.try_match(file, rlib_prefix.as_slice(), ".rlib") {
Some(hash) => {
info!("rlib accepted, hash: {}", hash);
let slot = candidates.find_or_insert_with(hash, |_| {
(HashSet::new(), HashSet::new())
});
let (ref mut rlibs, _) = *slot;
rlibs.insert(fs::realpath(path).unwrap());
FileMatches
}
None => {
info!("rlib rejected");
FileDoesntMatch
}
}
(file.slice(rlib_prefix.len(), file.len() - ".rlib".len()),
true)
} else if dypair.map_or(false, |(_, suffix)| {
file.starts_with(dylib_prefix.get_ref().as_slice()) &&
file.ends_with(suffix)
}) {
let (_, suffix) = dypair.unwrap();
let dylib_prefix = dylib_prefix.get_ref().as_slice();
info!("dylib candidate: {}", path.display());
match self.try_match(file, dylib_prefix, suffix) {
Some(hash) => {
info!("dylib accepted, hash: {}", hash);
let slot = candidates.find_or_insert_with(hash, |_| {
(HashSet::new(), HashSet::new())
});
let (_, ref mut dylibs) = *slot;
dylibs.insert(fs::realpath(path).unwrap());
FileMatches
}
None => {
info!("dylib rejected");
FileDoesntMatch
}
}
(file.slice(dylib_prefix.len(), file.len() - suffix.len()),
false)
} else {
FileDoesntMatch
return FileDoesntMatch
};
info!("lib candidate: {}", path.display());
let slot = candidates.find_or_insert_with(hash.to_string(), |_| {
(HashSet::new(), HashSet::new())
});
let (ref mut rlibs, ref mut dylibs) = *slot;
if rlib {
rlibs.insert(fs::realpath(path).unwrap());
} else {
dylibs.insert(fs::realpath(path).unwrap());
}
FileMatches
});
// We have now collected all known libraries into a set of candidates
@ -274,7 +468,7 @@ fn find_library_crate(&mut self) -> Option<Library> {
_ => {
self.sess.span_err(self.span,
format!("multiple matching crates for `{}`",
self.crate_id.name).as_slice());
self.crate_name).as_slice());
self.sess.note("candidates:");
for lib in libraries.iter() {
match lib.dylib {
@ -292,50 +486,14 @@ fn find_library_crate(&mut self) -> Option<Library> {
None => {}
}
let data = lib.metadata.as_slice();
let crate_id = decoder::get_crate_id(data);
note_crateid_attr(self.sess.diagnostic(), &crate_id);
let name = decoder::get_crate_name(data);
note_crate_name(self.sess.diagnostic(), name.as_slice());
}
None
}
}
}
// Attempts to match the requested version of a library against the file
// specified. The prefix/suffix are specified (disambiguates between
// rlib/dylib).
//
// The return value is `None` if `file` doesn't look like a rust-generated
// library, or if a specific version was requested and it doesn't match the
// apparent file's version.
//
// If everything checks out, then `Some(hash)` is returned where `hash` is
// the listed hash in the filename itself.
fn try_match(&self, file: &str, prefix: &str, suffix: &str) -> Option<String>{
let middle = file.slice(prefix.len(), file.len() - suffix.len());
debug!("matching -- {}, middle: {}", file, middle);
let mut parts = middle.splitn('-', 1);
let hash = match parts.next() { Some(h) => h, None => return None };
debug!("matching -- {}, hash: {} (want {})", file, hash, self.id_hash);
let vers = match parts.next() { Some(v) => v, None => return None };
debug!("matching -- {}, vers: {} (want {})", file, vers,
self.crate_id.version);
match self.crate_id.version {
Some(ref version) if version.as_slice() != vers => return None,
Some(..) => {} // check the hash
// hash is irrelevant, no version specified
None => return Some(hash.to_string())
}
debug!("matching -- {}, vers ok", file);
// hashes in filenames are prefixes of the "true hash"
if self.id_hash == hash.as_slice() {
debug!("matching -- {}, hash ok", file);
Some(hash.to_string())
} else {
None
}
}
// Attempts to extract *one* library from the set `m`. If the set has no
// elements, `None` is returned. If the set has more than one element, then
// the errors and notes are emitted about the set of libraries.
@ -382,7 +540,7 @@ fn extract_one(&mut self, m: HashSet<Path>, flavor: &str,
format!("multiple {} candidates for `{}` \
found",
flavor,
self.crate_id.name).as_slice());
self.crate_name).as_slice());
self.sess.span_note(self.span,
format!(r"candidate #1: {}",
ret.get_ref()
@ -404,9 +562,11 @@ fn extract_one(&mut self, m: HashSet<Path>, flavor: &str,
}
fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
match decoder::maybe_get_crate_id(crate_data) {
Some(ref id) if self.crate_id.matches(id) => {}
_ => { info!("Rejecting via crate_id"); return false }
if self.should_match_name {
match decoder::maybe_get_crate_name(crate_data) {
Some(ref name) if self.crate_name == name.as_slice() => {}
_ => { info!("Rejecting via crate name"); return false }
}
}
let hash = match decoder::maybe_get_crate_hash(crate_data) {
Some(hash) => hash, None => {
@ -415,7 +575,10 @@ fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> bool {
}
};
let triple = decoder::get_crate_triple(crate_data);
let triple = match decoder::get_crate_triple(crate_data) {
None => { debug!("triple not present"); return false }
Some(t) => t,
};
if triple.as_slice() != self.triple {
info!("Rejecting via crate triple: expected {} got {}", self.triple, triple);
self.rejected_via_triple.push(CrateMismatch {
@ -456,10 +619,72 @@ fn dylibname(&self) -> Option<(&'static str, &'static str)> {
}
}
fn find_commandline_library(&mut self) -> Option<Library> {
let locs = match self.sess.opts.externs.find_equiv(&self.crate_name) {
Some(s) => s,
None => return None,
};
// First, filter out all libraries that look suspicious. We only accept
// files which actually exist that have the correct naming scheme for
// rlibs/dylibs.
let sess = self.sess;
let dylibname = self.dylibname();
let mut locs = locs.iter().map(|l| Path::new(l.as_slice())).filter(|loc| {
if !loc.exists() {
sess.err(format!("extern location does not exist: {}",
loc.display()).as_slice());
return false;
}
let file = loc.filename_str().unwrap();
if file.starts_with("lib") && file.ends_with(".rlib") {
return true
} else {
match dylibname {
Some((prefix, suffix)) => {
if file.starts_with(prefix) && file.ends_with(suffix) {
return true
}
}
None => {}
}
}
sess.err(format!("extern location is of an unknown type: {}",
loc.display()).as_slice());
false
});
// Now that we have an itertor of good candidates, make sure there's at
// most one rlib and at most one dylib.
let mut rlibs = HashSet::new();
let mut dylibs = HashSet::new();
for loc in locs {
if loc.filename_str().unwrap().ends_with(".rlib") {
rlibs.insert(loc.clone());
} else {
dylibs.insert(loc.clone());
}
}
// Extract the rlib/dylib pair.
let mut metadata = None;
let rlib = self.extract_one(rlibs, "rlib", &mut metadata);
let dylib = self.extract_one(dylibs, "dylib", &mut metadata);
if rlib.is_none() && dylib.is_none() { return None }
match metadata {
Some(metadata) => Some(Library {
dylib: dylib,
rlib: rlib,
metadata: metadata,
}),
None => None,
}
}
}
pub fn note_crateid_attr(diag: &SpanHandler, crateid: &CrateId) {
diag.handler().note(format!("crate_id: {}", crateid.to_str()).as_slice());
pub fn note_crate_name(diag: &SpanHandler, name: &str) {
diag.handler().note(format!("crate name: {}", name).as_slice());
}
impl ArchiveMetadata {

View File

@ -1373,15 +1373,15 @@ pub fn process_crate(sess: &Session,
return;
}
let (cratename, crateid) = match attr::find_crateid(krate.attrs.as_slice()) {
Some(crateid) => (crateid.name.clone(), crateid.to_str()),
let cratename = match attr::find_crate_name(krate.attrs.as_slice()) {
Some(name) => name.get().to_string(),
None => {
info!("Could not find crate name, using 'unknown_crate'");
(String::from_str("unknown_crate"),"unknown_crate".to_owned())
String::from_str("unknown_crate")
},
};
info!("Dumping crate {} ({})", cratename, crateid);
info!("Dumping crate {}", cratename);
// find a path to dump our data to
let mut root_path = match os::getenv("DXR_RUST_TEMP_FOLDER") {

View File

@ -30,7 +30,6 @@
use driver::config;
use driver::config::{NoDebugInfo, FullDebugInfo};
use driver::session::Session;
use driver::driver::OutputFilenames;
use driver::driver::{CrateAnalysis, CrateTranslation};
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
use lib::llvm::{llvm, Vector};
@ -2270,8 +2269,9 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
}.as_slice());
let llmeta = C_bytes(cx, compressed.as_slice());
let llconst = C_struct(cx, [llmeta], false);
let name = format!("rust_metadata_{}_{}_{}", cx.link_meta.crateid.name,
cx.link_meta.crateid.version_or_default(), cx.link_meta.crate_hash);
let name = format!("rust_metadata_{}_{}",
cx.link_meta.crate_name,
cx.link_meta.crate_hash);
let llglobal = name.with_c_str(|buf| {
unsafe {
llvm::LLVMAddGlobal(cx.metadata_llmod, val_ty(llconst).to_ref(), buf)
@ -2288,9 +2288,8 @@ pub fn write_metadata(cx: &CrateContext, krate: &ast::Crate) -> Vec<u8> {
}
pub fn trans_crate(krate: ast::Crate,
analysis: CrateAnalysis,
output: &OutputFilenames) -> (ty::ctxt, CrateTranslation) {
let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, .. } = analysis;
analysis: CrateAnalysis) -> (ty::ctxt, CrateTranslation) {
let CrateAnalysis { ty_cx: tcx, exp_map2, reachable, name, .. } = analysis;
// Before we touch LLVM, make sure that multithreading is enabled.
unsafe {
@ -2310,8 +2309,7 @@ pub fn trans_crate(krate: ast::Crate,
}
}
let link_meta = link::build_link_meta(&krate,
output.out_filestem.as_slice());
let link_meta = link::build_link_meta(&tcx.sess, &krate, name);
// Append ".rs" to crate name as LLVM module identifier.
//
@ -2321,7 +2319,7 @@ pub fn trans_crate(krate: ast::Crate,
// crashes if the module identifier is same as other symbols
// such as a function name in the module.
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
let mut llmod_id = link_meta.crateid.name.clone();
let mut llmod_id = link_meta.crate_name.clone();
llmod_id.push_str(".rs");
let ccx = CrateContext::new(llmod_id.as_slice(), tcx, exp_map2,

View File

@ -1496,7 +1496,7 @@ fn compile_unit_metadata(cx: &CrateContext) {
});
fn fallback_path(cx: &CrateContext) -> CString {
cx.link_meta.crateid.name.as_slice().to_c_str()
cx.link_meta.crate_name.as_slice().to_c_str()
}
}
@ -3972,7 +3972,7 @@ fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
}
fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
cx.link_meta.crateid.name.as_slice()
cx.link_meta.crate_name.as_slice()
}
fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {

View File

@ -566,7 +566,7 @@ fn build_rust_fn(ccx: &CrateContext,
let ps = ccx.tcx.map.with_path(id, |path| {
let abi = Some(ast_map::PathName(special_idents::clownshoe_abi.name));
link::mangle(path.chain(abi.move_iter()), None, None)
link::mangle(path.chain(abi.move_iter()), None)
});
// Compute the type that the function would have if it were just a

View File

@ -129,9 +129,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
hash_id.hash(&mut state);
mono_ty.hash(&mut state);
exported_name(path,
format!("h{}", state.result()).as_slice(),
ccx.link_meta.crateid.version_or_default())
exported_name(path, format!("h{}", state.result()).as_slice())
});
debug!("monomorphize_fn mangled to {}", s);

View File

@ -37,7 +37,6 @@
use syntax::codemap::{Span, CodeMap, DUMMY_SP};
use syntax::diagnostic::{Level, RenderSpan, Bug, Fatal, Error, Warning, Note};
use syntax::ast;
use syntax::crateid::CrateId;
use util::ppaux::{ty_to_str, UserString};
struct Env<'a> {
@ -116,11 +115,8 @@ fn test_env(_test_name: &str,
let krate_config = Vec::new();
let input = driver::StrInput(source_string.to_owned());
let krate = driver::phase_1_parse_input(&sess, krate_config, &input);
let krate_id = CrateId { path: "test".to_owned(),
name: "test".to_owned(),
version: None };
let (krate, ast_map) =
driver::phase_2_configure_and_expand(&sess, krate, &krate_id)
driver::phase_2_configure_and_expand(&sess, krate, "test")
.expect("phase 2 aborted");
// run just enough stuff to build a tcx:

View File

@ -119,13 +119,7 @@ fn clean(&self) -> Crate {
// Figure out the name of this crate
let input = driver::FileInput(cx.src.clone());
let t_outputs = driver::build_output_filenames(&input,
&None,
&None,
self.attrs.as_slice(),
cx.sess());
let id = link::find_crate_id(self.attrs.as_slice(),
t_outputs.out_filestem.as_slice());
let name = link::find_crate_name(None, self.attrs.as_slice(), &input);
// Clean the crate, translating the entire libsyntax AST to one that is
// understood by rustdoc.
@ -188,7 +182,7 @@ fn clean(&self) -> Crate {
}
Crate {
name: id.name.to_string(),
name: name.to_string(),
module: Some(module),
externs: externs,
primitives: primitives,

View File

@ -12,6 +12,7 @@
use rustc::{driver, middle};
use rustc::middle::{privacy, ty};
use rustc::lint;
use rustc::back::link;
use syntax::ast;
use syntax::parse::token;
@ -115,13 +116,17 @@ fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<String>)
}
let krate = phase_1_parse_input(&sess, cfg, &input);
let name = link::find_crate_name(Some(&sess), krate.attrs.as_slice(),
&input);
let (krate, ast_map)
= phase_2_configure_and_expand(&sess, krate, &from_str("rustdoc").unwrap())
= phase_2_configure_and_expand(&sess, krate, name.as_slice())
.expect("phase_2_configure_and_expand aborted in rustdoc!");
let driver::driver::CrateAnalysis {
exported_items, public_items, ty_cx, ..
} = phase_3_run_analysis_passes(sess, &krate, ast_map);
} = phase_3_run_analysis_passes(sess, &krate, ast_map, name);
debug!("crate: {:?}", krate);
(DocContext {

View File

@ -8,12 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id = "rustdoc#0.11.0"]
#![crate_id = "rustdoc#0.11.0"] // NOTE: remove after stage0
#![crate_name = "rustdoc"]
#![experimental]
#![desc = "rustdoc, the Rust documentation extractor"]
#![license = "MIT/ASL2"]
#![crate_type = "dylib"]
#![crate_type = "rlib"]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(globs, struct_variant, managed_boxes, macro_rules, phase)]

View File

@ -69,7 +69,7 @@ pub fn run(input: &str,
}));
let krate = driver::phase_1_parse_input(&sess, cfg, &input);
let (krate, _) = driver::phase_2_configure_and_expand(&sess, krate,
&from_str("rustdoc-test").unwrap())
"rustdoc-test")
.expect("phase_2_configure_and_expand aborted in rustdoc!");
let ctx = box(GC) core::DocContext {

View File

@ -8,7 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id = "rustrt#0.11.0"]
#![crate_id = "rustrt#0.11.0"] // NOTE: remove after stage0
#![crate_name = "rustrt"]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -20,6 +21,7 @@
#![feature(linkage, lang_items, unsafe_destructor)]
#![no_std]
#![experimental]
#![allow(unused_attribute)] // NOTE: remove after stage0
#[phase(plugin, link)] extern crate core;
extern crate alloc;

View File

@ -34,7 +34,8 @@
*/
#![crate_id = "rustuv#0.11.0"]
#![crate_id = "rustuv#0.11.0"] // NOTE: remove after stage0
#![crate_name = "rustuv"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "rlib"]
@ -47,6 +48,7 @@
#![feature(macro_rules, unsafe_destructor)]
#![deny(unused_result, unused_must_use)]
#![allow(visible_private_types)]
#![allow(unused_attribute)] // NOTE: remove after stage0
#[cfg(test)] extern crate green;
#[cfg(test)] extern crate debug;

View File

@ -28,7 +28,8 @@
//! An example version number with all five components is
//! `0.8.1-rc.3.0+20130922.linux`.
#![crate_id = "semver#0.11.0"]
#![crate_id = "semver#0.11.0"] // NOTE: remove after stage0
#![crate_name = "semver"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -36,6 +37,7 @@
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![allow(unused_attribute)] // NOTE: remove after stage0
use std::char;
use std::cmp;

View File

@ -14,7 +14,8 @@
Core encoding and decoding interfaces.
*/
#![crate_id = "serialize#0.11.0"]
#![crate_id = "serialize#0.11.0"] // NOTE: remove after stage0
#![crate_name = "serialize"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -24,6 +25,7 @@
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(macro_rules, managed_boxes, default_type_params, phase)]
#![allow(unused_attribute)] // NOTE: remove after stage0
// test harness access
#[cfg(test)]

View File

@ -94,7 +94,8 @@
//! all the standard macros, such as `assert!`, `fail!`, `println!`,
//! and `format!`, also available to all Rust code.
#![crate_id = "std#0.11.0"]
#![crate_id = "std#0.11.0"] // NOTE: remove after stage0 snap
#![crate_name = "std"]
#![unstable]
#![comment = "The Rust standard library"]
#![license = "MIT/ASL2"]
@ -107,6 +108,7 @@
#![feature(macro_rules, globs, managed_boxes, linkage)]
#![feature(default_type_params, phase, lang_items, unsafe_destructor)]
#![allow(unused_attribute)] // NOTE: remove after stage0
// Don't link to std. We are std.
#![no_std]

View File

@ -17,7 +17,8 @@
//! use this crate specifically. Instead, its functionality is reexported
//! through `std::sync`.
#![crate_id = "sync#0.11.0"]
#![crate_id = "sync#0.11.0"] // NOTE: remove after stage0 snap
#![crate_name = "sync"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -30,6 +31,7 @@
#![feature(phase, globs, macro_rules, unsafe_destructor)]
#![deny(missing_doc)]
#![no_std]
#![allow(unused_attribute)] // NOTE: remove after stage0
#[phase(plugin, link)] extern crate core;
extern crate alloc;

View File

@ -18,7 +18,6 @@
use parse::lexer::comments::{doc_comment_style, strip_doc_comment_decoration};
use parse::token::InternedString;
use parse::token;
use crateid::CrateId;
use std::collections::HashSet;
use std::collections::BitvSet;
@ -271,11 +270,8 @@ pub fn sort_meta_items(items: &[Gc<MetaItem>]) -> Vec<Gc<MetaItem>> {
}).collect()
}
pub fn find_crateid(attrs: &[Attribute]) -> Option<CrateId> {
match first_attr_value_str_by_name(attrs, "crate_id") {
None => None,
Some(id) => from_str::<CrateId>(id.get()),
}
pub fn find_crate_name(attrs: &[Attribute]) -> Option<InternedString> {
first_attr_value_str_by_name(attrs, "crate_name")
}
#[deriving(PartialEq)]

View File

@ -452,7 +452,7 @@ pub fn backtrace(&self) -> Option<Gc<ExpnInfo>> { self.backtrace }
pub fn mod_pop(&mut self) { self.mod_path.pop().unwrap(); }
pub fn mod_path(&self) -> Vec<ast::Ident> {
let mut v = Vec::new();
v.push(token::str_to_ident(self.ecfg.crate_id.name.as_slice()));
v.push(token::str_to_ident(self.ecfg.crate_name.as_slice()));
v.extend(self.mod_path.iter().map(|a| *a));
return v;
}

View File

@ -19,7 +19,6 @@
use attr::AttrMetaMethods;
use codemap;
use codemap::{Span, Spanned, ExpnInfo, NameAndSpan, MacroBang, MacroAttribute};
use crateid::CrateId;
use ext::base::*;
use fold;
use fold::*;
@ -985,7 +984,7 @@ fn new_span(cx: &ExtCtxt, sp: Span) -> Span {
pub struct ExpansionConfig {
pub deriving_hash_type_parameter: bool,
pub crate_id: CrateId,
pub crate_name: String,
}
pub struct ExportedMacros {
@ -1184,7 +1183,7 @@ fn crate_idents(the_crate: &ast::Crate) -> Vec<ast::Ident> {
// should fail:
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
crate_name: "test".to_str(),
};
expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
}
@ -1201,7 +1200,7 @@ fn crate_idents(the_crate: &ast::Crate) -> Vec<ast::Ident> {
Vec::new(), &sess);
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
crate_name: "test".to_str(),
};
expand_crate(&sess,cfg,vec!(),vec!(),crate_ast);
}
@ -1217,7 +1216,7 @@ fn crate_idents(the_crate: &ast::Crate) -> Vec<ast::Ident> {
Vec::new(), &sess);
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
crate_name: "test".to_str(),
};
expand_crate(&sess, cfg, vec!(), vec!(), crate_ast);
}
@ -1254,7 +1253,7 @@ fn expand_crate_str(crate_str: String) -> ast::Crate {
// the cfg argument actually does matter, here...
let cfg = ::syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: false,
crate_id: from_str("test").unwrap(),
crate_name: "test".to_str(),
};
expand_crate(&ps,cfg,vec!(),vec!(),crate_ast)
}

View File

@ -18,7 +18,8 @@
*/
#![crate_id = "syntax#0.11.0"]
#![crate_id = "syntax#0.11.0"] // NOTE: remove after stage0
#![crate_name = "syntax"]
#![experimental]
#![license = "MIT/ASL2"]
#![crate_type = "dylib"]
@ -30,6 +31,7 @@
#![feature(macro_rules, globs, managed_boxes, default_type_params, phase)]
#![feature(quote, unsafe_destructor)]
#![allow(deprecated)]
#![allow(unused_attribute)] // NOTE: remove after stage0
extern crate serialize;
extern crate term;

View File

@ -38,7 +38,8 @@
//! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx
//! [ti]: https://en.wikipedia.org/wiki/Terminfo
#![crate_id = "term#0.11.0"]
#![crate_id = "term#0.11.0"] // NOTE: remove after stage0
#![crate_name = "term"]
#![experimental]
#![comment = "Simple ANSI color library"]
#![license = "MIT/ASL2"]
@ -48,6 +49,7 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(macro_rules, phase)]

View File

@ -23,7 +23,8 @@
// running tests while providing a base that other test frameworks may
// build off of.
#![crate_id = "test#0.11.0"]
#![crate_id = "test#0.11.0"] // NOTE: remove after stage0
#![crate_name = "test"] // NOTE: remove after stage0
#![experimental]
#![comment = "Rust internal test library only used by rustc"]
#![license = "MIT/ASL2"]
@ -32,6 +33,7 @@
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/")]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(asm, macro_rules, phase)]

View File

@ -10,7 +10,8 @@
//! Simple time handling.
#![crate_id = "time#0.11.0"]
#![crate_id = "time#0.11.0"] // NOTE: remove after stage0
#![crate_name = "time"]
#![experimental]
#![crate_type = "rlib"]
@ -21,6 +22,7 @@
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(phase)]
#![allow(unused_attribute)] // NOTE: remove after stage0
#[cfg(test)] extern crate debug;
#[cfg(test)] #[phase(plugin, link)] extern crate log;

View File

@ -10,7 +10,8 @@
//! Types/fns concerning URLs (see RFC 3986)
#![crate_id = "url#0.11.0"]
#![crate_id = "url#0.11.0"] // NOTE: remove after stage0
#![crate_name = "url"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -20,6 +21,7 @@
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(default_type_params)]
#![allow(unused_attribute)] // NOTE: remove after stage0
use std::collections::HashMap;
use std::fmt;

View File

@ -54,7 +54,8 @@ fn main() {
*/
#![crate_id = "uuid#0.11.0"]
#![crate_id = "uuid#0.11.0"] // NOTE: remove after stage0
#![crate_name = "uuid"]
#![experimental]
#![crate_type = "rlib"]
#![crate_type = "dylib"]
@ -63,6 +64,7 @@ fn main() {
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/0.11.0/",
html_playground_url = "http://play.rust-lang.org/")]
#![allow(unused_attribute)] // NOTE: remove after stage0
#![feature(default_type_params)]

View File

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="crateresolve1#0.1"]
// compile-flags:-C extra-filename=-1
#![crate_name = "crateresolve1"]
#![crate_type = "lib"]
pub fn f() -> int { 10 }

View File

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="crateresolve1#0.2"]
// compile-flags:-C extra-filename=-2
#![crate_name = "crateresolve1"]
#![crate_type = "lib"]
pub fn f() -> int { 20 }

View File

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="crateresolve1#0.3"]
// compile-flags:-C extra-filename=-3
#![crate_name = "crateresolve1"]
#![crate_type = "lib"]
pub fn f() -> int { 30 }

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.
#![crate_id="crateresolve2#0.1"]
#![crate_type = "lib"]
pub fn f() -> int { 10 }

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="externcallback#0.1"]
#![crate_name="externcallback"]
#![crate_type = "lib"]
extern crate libc;

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
extern crate foo = ""; //~ ERROR: malformed crate id
extern crate bar = "#a"; //~ ERROR: malformed crate id
extern crate foo = ""; //~ ERROR: crate name must not be empty
fn main() {}

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,8 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="crateresolve2#0.2"]
extern crate bar = "#a"; //~ ERROR: invalid character `#` in crate name: `#a`
#![crate_type = "lib"]
fn main() {}
pub fn f() -> int { 20 }

View File

@ -1,24 +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.
// aux-build:crateresolve2-1.rs
// aux-build:crateresolve2-2.rs
// aux-build:crateresolve2-3.rs
// error-pattern:using multiple versions of crate `crateresolve2`
extern crate crateresolve2 = "crateresolve2#0.1";
mod m {
pub extern crate crateresolve2 = "crateresolve2#0.2";
}
fn main() {
let x: int = false;
}

View File

@ -1,21 +0,0 @@
// Copyright 2012-2014 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.
// aux-build:crateresolve5-1.rs
// aux-build:crateresolve5-2.rs
extern crate cr5_1 = "crateresolve5#0.1";
extern crate cr5_2 = "crateresolve5#0.2";
fn main() {
// Nominal types from two multiple versions of a crate are different types
assert!(cr5_1::nominal() == cr5_2::nominal()); //~ ERROR mismatched types: expected
}

View File

@ -1,24 +0,0 @@
// Copyright 2014 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.
// aux-build:issue-11908-1.rs
// ignore-android this test is incompatible with the android test runner
// error-pattern: multiple dylib candidates for `url` found
// This test ensures that if you have the same rlib or dylib at two locations
// in the same path that you don't hit an assertion in the compiler.
//
// Note that this relies on `liburl` to be in the path somewhere else,
// and then our aux-built libraries will collide with liburl (they have
// the same version listed)
extern crate url;
fn main() {}

View File

@ -6,7 +6,6 @@ TARGET_RPATH_DIR:=$(TARGET_RPATH_DIR):$(TMPDIR)
all:
$(RUSTC) lib.rs
ln -nsf $(call DYLIB,boot-*) $(call DYLIB,boot)
$(CC) main.c -o $(call RUN_BINFILE,main) $(call RPATH_LINK_SEARCH,$(HOST_LIB_DIR)) -lboot
$(call RUN,main)
$(call REMOVE_DYLIBS,boot)

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="boot#0.1"]
#![crate_name="boot"]
#![crate_type="dylib"]
extern crate rustuv;

View File

@ -6,7 +6,6 @@ TARGET_RPATH_DIR:=$(TARGET_RPATH_DIR):$(TMPDIR)
all:
$(RUSTC) lib.rs
ln -nsf $(call DYLIB,boot-*) $(call DYLIB,boot)
$(CC) main.c -o $(call RUN_BINFILE,main) $(call RPATH_LINK_SEARCH,$(HOST_LIB_DIR)) -lboot
$(call RUN,main)
$(call REMOVE_DYLIBS,boot)

View File

@ -4,7 +4,6 @@ HOST_LIB_DIR=$(TMPDIR)/../../../stage$(RUST_BUILD_STAGE)/lib
all:
$(RUSTC) foo.rs
ln -s $(call DYLIB,foo-*) $(call DYLIB,foo)
$(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(call RPATH_LINK_SEARCH,$(HOST_LIB_DIR)) -Wl,-rpath,$(TMPDIR)
$(call RUN,bar)
$(call REMOVE_DYLIBS,foo)

View File

@ -10,7 +10,6 @@ endif
ifneq ($(shell uname),FreeBSD)
all:
$(RUSTC) foo.rs
ln -s $(call STATICLIB,foo-*) $(call STATICLIB,foo)
$(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(EXTRAFLAGS) -lstdc++
$(call RUN,bar)
rm $(call STATICLIB,foo*)

View File

@ -1,10 +1,9 @@
-include ../tools.mk
all:
[ `$(RUSTC) --crate-id crate.rs` = "foo#0.11.0" ]
[ `$(RUSTC) --crate-name crate.rs` = "foo" ]
[ `$(RUSTC) --crate-file-name crate.rs` = "foo" ]
[ `$(RUSTC) --crate-file-name --crate-type=lib --test crate.rs` = "foo" ]
[ `$(RUSTC) --crate-file-name --test lib.rs` = "mylib" ]
$(RUSTC) --crate-file-name lib.rs
$(RUSTC) --crate-file-name rlib.rs
[ `$(RUSTC) --print-crate-name crate.rs` = "foo" ]
[ `$(RUSTC) --print-file-name crate.rs` = "foo" ]
[ `$(RUSTC) --print-file-name --crate-type=lib --test crate.rs` = "foo" ]
[ `$(RUSTC) --print-file-name --test lib.rs` = "mylib" ]
$(RUSTC) --print-file-name lib.rs
$(RUSTC) --print-file-name rlib.rs

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id = "foo#0.11.0"]
#![crate_name = "foo"]
// Querying about the crate metadata should *not* parse the entire crate, it
// only needs the crate attributes (which are guaranteed to be at the top) be

View File

@ -8,5 +8,5 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id = "mylib"]
#![crate_name = "mylib"]
#![crate_type = "lib"]

View File

@ -8,5 +8,5 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id = "mylib"]
#![crate_name = "mylib"]
#![crate_type = "rlib"]

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![crate_id="foo#0.1"]
#![crate_name = "foo"]
pub mod foo;
pub mod bar;

View File

@ -0,0 +1,24 @@
-include ../tools.mk
# Attempt to build this dependency tree:
#
# A.1 A.2
# |\ |
# | \ |
# B \ C
# \ | /
# \|/
# D
#
# Note that A.1 and A.2 are crates with the same name.
all:
$(RUSTC) -C metadata=1 -C extra-filename=-1 a.rs
$(RUSTC) -C metadata=2 -C extra-filename=-2 a.rs
$(RUSTC) b.rs --extern a=$(TMPDIR)/liba-1.rlib
$(RUSTC) c.rs --extern a=$(TMPDIR)/liba-2.rlib
$(RUSTC) --cfg before d.rs --extern a=$(TMPDIR)/liba-1.rlib
$(call RUN,d)
$(RUSTC) --cfg after d.rs --extern a=$(TMPDIR)/liba-1.rlib
$(call RUN,d)

View File

@ -0,0 +1,16 @@
// Copyright 2014 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.
#![crate_name = "a"]
#![crate_type = "rlib"]
static FOO: uint = 3;
pub fn token() -> &'static uint { &FOO }

View File

@ -8,14 +8,12 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:issue-11908-2.rs
// no-prefer-dynamic
// ignore-android this test is incompatible with the android test runner
// error-pattern: multiple rlib candidates for `url` found
#![crate_name = "b"]
#![crate_type = "rlib"]
// see comments in issue-11908-1 for what's going on here
extern crate a;
extern crate url;
fn main() {}
static FOO: uint = 3;
pub fn token() -> &'static uint { &FOO }
pub fn a_token() -> &'static uint { a::token() }

View File

@ -0,0 +1,19 @@
// Copyright 2014 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.
#![crate_name = "c"]
#![crate_type = "rlib"]
extern crate a;
static FOO: uint = 3;
pub fn token() -> &'static uint { &FOO }
pub fn a_token() -> &'static uint { a::token() }

View File

@ -1,4 +1,4 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,13 +8,14 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:crateresolve8-1.rs
#[cfg(before)] extern crate a;
extern crate b;
extern crate c;
#[cfg(after)] extern crate a;
#![crate_id="crateresolve8#0.1"]
fn t(a: &'static uint) -> uint { a as *const _ as uint }
extern crate crateresolve8 = "crateresolve8#0.1";
//extern crate crateresolve8(vers = "0.1");
pub fn main() {
assert_eq!(crateresolve8::f(), 20);
fn main() {
assert!(t(a::token()) == t(b::a_token()));
assert!(t(a::token()) != t(c::a_token()));
}

View File

@ -0,0 +1,16 @@
-include ../tools.mk
all:
$(RUSTC) bar.rs --crate-type=rlib
$(RUSTC) bar.rs --crate-type=rlib -C extra-filename=-a
$(RUSTC) foo.rs --extern hello && exit 1 || exit 0
$(RUSTC) foo.rs --extern bar=no-exist && exit 1 || exit 0
$(RUSTC) foo.rs --extern bar=foo.rs && exit 1 || exit 0
$(RUSTC) foo.rs \
--extern bar=$(TMPDIR)/libbar.rlib \
--extern bar=$(TMPDIR)/libbar-a.rlib \
&& exit 1 || exit 0
$(RUSTC) foo.rs \
--extern bar=$(TMPDIR)/libbar.rlib \
--extern bar=$(TMPDIR)/libbar.rlib
$(RUSTC) foo.rs --extern bar=$(TMPDIR)/libbar.rlib

View File

@ -0,0 +1,10 @@
// Copyright 2014 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.

View File

@ -8,7 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// no-prefer-dynamic
extern crate bar;
#![crate_id = "url#0.11.0"]
#![crate_type = "dylib"]
fn main() {}

View File

@ -0,0 +1,23 @@
# This test ensures that if you have the same rlib or dylib at two locations
# in the same path that you don't hit an assertion in the compiler.
#
# Note that this relies on `liburl` to be in the path somewhere else,
# and then our aux-built libraries will collide with liburl (they have
# the same version listed)
-include ../tools.mk
all:
mkdir $(TMPDIR)/other
$(RUSTC) foo.rs --crate-type=dylib
mv $(call DYLIB,foo) $(TMPDIR)/other
$(RUSTC) foo.rs --crate-type=dylib
$(RUSTC) bar.rs -L $(TMPDIR)/other 2>&1 | \
grep "multiple dylib candidates"
rm -rf $(TMPDIR)
mkdir -p $(TMPDIR)/other
$(RUSTC) foo.rs --crate-type=rlib
mv $(TMPDIR)/libfoo.rlib $(TMPDIR)/other
$(RUSTC) foo.rs --crate-type=rlib
$(RUSTC) bar.rs -L $(TMPDIR)/other 2>&1 | \
grep "multiple rlib candidates"

View File

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,6 +8,6 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern:can't find crate for `std`
extern crate foo;
extern crate std = "std#bogus";
fn main() {}

View File

@ -0,0 +1,11 @@
// Copyright 2014 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.
#![crate_name = "foo"]

View File

@ -5,6 +5,5 @@ CC := $(CC:-g=)
all:
$(RUSTC) foo.rs -Z lto
ln -s $(call STATICLIB,foo-*) $(call STATICLIB,foo)
$(CC) bar.c -lfoo -o $(call RUN_BINFILE,bar) $(EXTRACFLAGS) -lstdc++
$(call RUN,bar)

View File

@ -8,4 +8,4 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[crate_type = "rlib"];
#![crate_type = "rlib"]

View File

@ -0,0 +1,5 @@
-include ../tools.mk
all:
$(RUSTC) --crate-name foo bar.rs
rm $(TMPDIR)/libfoo.rlib

View File

@ -8,7 +8,4 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// no-prefer-dynamic
#![crate_id = "url#0.11.0"]
#![crate_type = "rlib"]

View File

@ -0,0 +1,10 @@
-include ../tools.mk
all:
$(RUSTC) foo.rs -C metadata=a -C extra-filename=-a
$(RUSTC) foo.rs -C metadata=b -C extra-filename=-b
$(RUSTC) bar.rs \
--extern foo1=$(TMPDIR)/libfoo-a.rlib \
--extern foo2=$(TMPDIR)/libfoo-b.rlib \
-Z print-link-args
$(call RUN,bar)

View File

@ -0,0 +1,18 @@
// Copyright 2014 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.
extern crate foo1;
extern crate foo2;
fn main() {
let a = foo1::foo();
let b = foo2::foo();
assert!(a as *const _ != b as *const _);
}

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