diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs index ccd6c66603f..6647a21e26a 100644 --- a/src/librustc/back/link.rs +++ b/src/librustc/back/link.rs @@ -447,7 +447,7 @@ unsafe fn populate_llvm_passes(fpm: lib::llvm::PassManagerRef, */ pub fn build_link_meta(sess: Session, - c: &ast::Crate, + attrs: &[ast::Attribute], output: &Path, symbol_hasher: &mut Sha256) -> LinkMeta { @@ -458,7 +458,7 @@ fn crate_hash(symbol_hasher: &mut Sha256, pkgid: &PkgId) -> @str { truncated_hash_result(symbol_hasher).to_managed() } - let pkgid = match attr::find_pkgid(c.attrs) { + let pkgid = match attr::find_pkgid(attrs) { None => { let stem = session::expect( sess, diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index f02a497ee46..bcaaa9224d9 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -165,7 +165,7 @@ pub fn phase_2_configure_and_expand(sess: Session, let time_passes = sess.time_passes(); *sess.building_library = session::building_library(sess.opts, &crate); - *sess.outputs = session::collect_outputs(sess.opts, &crate); + *sess.outputs = session::collect_outputs(sess.opts, crate.attrs); time(time_passes, "gated feature checking", (), |_| front::feature_gate::check_crate(sess, &crate)); @@ -446,42 +446,6 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input, let (outputs, trans) = { let expanded_crate = { let crate = phase_1_parse_input(sess, cfg.clone(), input); - let (crate_id, 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 { - let t_outputs = build_output_filenames(input, outdir, output, crate.attrs, sess); - if crate_id || crate_name { - let pkgid = match attr::find_pkgid(crate.attrs) { - Some(pkgid) => pkgid, - None => fail!("No crate_id and --crate-id or --crate-name requested") - }; - if crate_id { - println(pkgid.to_str()); - } - if crate_name { - println(pkgid.name); - } - } - - if crate_file_name { - let lm = link::build_link_meta(sess, &crate, &t_outputs.obj_filename, - &mut ::util::sha2::Sha256::new()); - // if the vector is empty we default to OutputExecutable. - let style = sess.opts.outputs.get_opt(0).unwrap_or(&OutputExecutable); - let fname = link::filename_for_input(&sess, *style, &lm, - &t_outputs.out_filename); - println!("{}", fname.display()); - - // we already maybe printed the first one, so skip it - for style in sess.opts.outputs.iter().skip(1) { - let fname = link::filename_for_input(&sess, *style, &lm, - &t_outputs.out_filename); - println!("{}", fname.display()); - } - } - - return; - } if stop_after_phase_1(sess) { return; } phase_2_configure_and_expand(sess, cfg, crate) }; diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs index 58f09a52f23..ba9ffe81a99 100644 --- a/src/librustc/driver/session.rs +++ b/src/librustc/driver/session.rs @@ -421,14 +421,15 @@ pub fn building_library(options: &options, crate: &ast::Crate) -> bool { } } -pub fn collect_outputs(options: &options, crate: &ast::Crate) -> ~[OutputStyle] { +pub fn collect_outputs(options: &options, + attrs: &[ast::Attribute]) -> ~[OutputStyle] { // If we're generating a test executable, then ignore all other output // styles at all other locations if options.test { return ~[OutputExecutable]; } let mut base = options.outputs.clone(); - let mut iter = crate.attrs.iter().filter_map(|a| { + let mut iter = attrs.iter().filter_map(|a| { if "crate_type" == a.name() { match a.value_str() { Some(n) if "rlib" == n => Some(OutputRlib), diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs index f0bff76685f..49288e35f44 100644 --- a/src/librustc/lib.rs +++ b/src/librustc/lib.rs @@ -21,14 +21,12 @@ extern mod extra; extern mod syntax; -use driver::driver::{host_triple, optgroups, early_error}; -use driver::driver::{str_input, file_input, build_session_options}; -use driver::driver::{build_session, build_configuration, parse_pretty}; -use driver::driver::{PpMode, pretty_print_input, list_metadata}; -use driver::driver::{compile_input}; +use back::link; use driver::session; use middle::lint; +use d = driver::driver; + use std::cast; use std::comm; use std::io; @@ -41,9 +39,12 @@ use std::vec; use extra::getopts::groups; use extra::getopts; +use syntax::ast; +use syntax::attr; use syntax::codemap; use syntax::diagnostic::Emitter; use syntax::diagnostic; +use syntax::parse; pub mod middle { pub mod trans; @@ -137,7 +138,7 @@ pub fn version(argv0: &str) { None => "unknown version" }; println!("{} {}", argv0, vers); - println!("host: {}", host_triple()); + println!("host: {}", d::host_triple()); } pub fn usage(argv0: &str) { @@ -146,7 +147,7 @@ pub fn usage(argv0: &str) { Additional help: -W help Print 'lint' options and default settings -Z help Print internal options for debugging rustc\n", - groups::usage(message, optgroups())); + groups::usage(message, d::optgroups())); } pub fn describe_warnings() { @@ -206,10 +207,10 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) { if args.is_empty() { usage(binary); return; } let matches = - &match getopts::groups::getopts(args, optgroups()) { + &match getopts::groups::getopts(args, d::optgroups()) { Ok(m) => m, Err(f) => { - early_error(demitter, f.to_err_msg()); + d::early_error(demitter, f.to_err_msg()); } }; @@ -246,48 +247,97 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) { return; } let input = match matches.free.len() { - 0u => early_error(demitter, "no input filename given"), + 0u => d::early_error(demitter, "no input filename given"), 1u => { let ifile = matches.free[0].as_slice(); if "-" == ifile { let src = str::from_utf8_owned(io::stdin().read_to_end()); - str_input(src.to_managed()) + d::str_input(src.to_managed()) } else { - file_input(Path::new(ifile)) + d::file_input(Path::new(ifile)) } } - _ => early_error(demitter, "multiple input filenames provided") + _ => d::early_error(demitter, "multiple input filenames provided") }; - let sopts = build_session_options(binary, matches, demitter); - let sess = build_session(sopts, demitter); + let sopts = d::build_session_options(binary, matches, demitter); + let sess = d::build_session(sopts, demitter); let odir = matches.opt_str("out-dir").map(|o| Path::new(o)); let ofile = matches.opt_str("o").map(|o| Path::new(o)); - let cfg = build_configuration(sess); + let cfg = d::build_configuration(sess); let pretty = matches.opt_default("pretty", "normal").map(|a| { - parse_pretty(sess, a) + d::parse_pretty(sess, a) }); match pretty { - Some::(ppm) => { - pretty_print_input(sess, cfg, &input, ppm); + Some::(ppm) => { + d::pretty_print_input(sess, cfg, &input, ppm); return; } - None:: => {/* continue */ } + None:: => {/* continue */ } } let ls = matches.opt_present("ls"); if ls { match input { - file_input(ref ifile) => { - list_metadata(sess, &(*ifile), @mut io::stdout() as @mut io::Writer); + d::file_input(ref ifile) => { + d::list_metadata(sess, &(*ifile), + @mut io::stdout() as @mut io::Writer); } - str_input(_) => { - early_error(demitter, "can not list metadata for stdin"); + d::str_input(_) => { + d::early_error(demitter, "can not list metadata for stdin"); } } return; } + let (crate_id, crate_name, crate_file_name) = sopts.print_metas; + // these nasty nested conditions are to avoid doing extra work + if crate_id || crate_name || crate_file_name { + let attrs = parse_crate_attrs(sess, &input); + let t_outputs = d::build_output_filenames(&input, &odir, &ofile, + attrs, sess); + if crate_id || crate_name { + let pkgid = match attr::find_pkgid(attrs) { + Some(pkgid) => pkgid, + None => { + sess.fatal("No crate_id and --crate-id or \ + --crate-name requested") + } + }; + if crate_id { + println(pkgid.to_str()); + } + if crate_name { + println(pkgid.name); + } + } - compile_input(sess, cfg, &input, &odir, &ofile); + if crate_file_name { + let lm = link::build_link_meta(sess, attrs, &t_outputs.obj_filename, + &mut ::util::sha2::Sha256::new()); + let outputs = session::collect_outputs(sopts, attrs); + for &style in outputs.iter() { + let fname = link::filename_for_input(&sess, style, &lm, + &t_outputs.out_filename); + println!("{}", fname.filename_display()); + } + } + + return; + } + + d::compile_input(sess, cfg, &input, &odir, &ofile); +} + +fn parse_crate_attrs(sess: session::Session, + input: &d::input) -> ~[ast::Attribute] { + match *input { + d::file_input(ref ifile) => { + parse::parse_crate_attrs_from_file(ifile, ~[], sess.parse_sess) + } + d::str_input(src) => { + parse::parse_crate_attrs_from_source_str( + d::anon_src(), src, ~[], sess.parse_sess) + } + } } #[deriving(Eq)] diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 7ab3b4fd69e..7dbe760e027 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -3096,7 +3096,7 @@ pub fn trans_crate(sess: session::Session, } let mut symbol_hasher = Sha256::new(); - let link_meta = link::build_link_meta(sess, &crate, output, + let link_meta = link::build_link_meta(sess, crate.attrs, output, &mut symbol_hasher); // Append ".rc" to crate name as LLVM module identifier. diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 612151f83e4..73240a9effd 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -79,6 +79,16 @@ pub fn parse_crate_from_file( // why is there no p.abort_if_errors here? } +pub fn parse_crate_attrs_from_file( + input: &Path, + cfg: ast::CrateConfig, + sess: @mut ParseSess +) -> ~[ast::Attribute] { + let parser = new_parser_from_file(sess, cfg, input); + let (inner, _) = parser.parse_inner_attrs_and_next(); + return inner; +} + pub fn parse_crate_from_source_str( name: @str, source: @str, @@ -92,6 +102,20 @@ pub fn parse_crate_from_source_str( maybe_aborted(p.parse_crate_mod(),p) } +pub fn parse_crate_attrs_from_source_str( + name: @str, + source: @str, + cfg: ast::CrateConfig, + sess: @mut ParseSess +) -> ~[ast::Attribute] { + let p = new_parser_from_source_str(sess, + /*bad*/ cfg.clone(), + name, + source); + let (inner, _) = maybe_aborted(p.parse_inner_attrs_and_next(),p); + return inner; +} + pub fn parse_expr_from_source_str( name: @str, source: @str, diff --git a/src/test/run-make/crate-data-smoke/Makefile b/src/test/run-make/crate-data-smoke/Makefile new file mode 100644 index 00000000000..35ae4accb27 --- /dev/null +++ b/src/test/run-make/crate-data-smoke/Makefile @@ -0,0 +1,10 @@ +-include ../tools.mk + +all: + [ `$(RUSTC) --crate-id crate.rs` = "foo#0.9" ] + [ `$(RUSTC) --crate-name crate.rs` = "foo" ] + [ `$(RUSTC) --crate-file-name crate.rs` = "foo" ] + [ `$(RUSTC) --crate-file-name --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 diff --git a/src/test/run-make/crate-data-smoke/crate.rs b/src/test/run-make/crate-data-smoke/crate.rs new file mode 100644 index 00000000000..840f346a601 --- /dev/null +++ b/src/test/run-make/crate-data-smoke/crate.rs @@ -0,0 +1,7 @@ +#[crate_id = "foo#0.9"]; + +// 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 +// sure that if we have an error like a missing module that we can still query +// about the crate id. +mod error; diff --git a/src/test/run-make/crate-data-smoke/lib.rs b/src/test/run-make/crate-data-smoke/lib.rs new file mode 100644 index 00000000000..11c5682389e --- /dev/null +++ b/src/test/run-make/crate-data-smoke/lib.rs @@ -0,0 +1,2 @@ +#[crate_id = "mylib"]; +#[crate_type = "lib"]; diff --git a/src/test/run-make/crate-data-smoke/rlib.rs b/src/test/run-make/crate-data-smoke/rlib.rs new file mode 100644 index 00000000000..26a1de1806a --- /dev/null +++ b/src/test/run-make/crate-data-smoke/rlib.rs @@ -0,0 +1,2 @@ +#[crate_id = "mylib"]; +#[crate_type = "rlib"];