Skip to content

Commit 9d1de0b

Browse files
committed
auto merge of #11077 : alexcrichton/rust/crate-id, r=cmr
Right now the --crate-id and related flags are all process *after* the entire crate is parsed. This is less than desirable when used with makefiles because it means that just to learn the output name of the crate you have to parse the entire crate (unnecessary). This commit changes the behavior to lift the handling of these flags much sooner in the compilation process. This allows us to not have to parse the entire crate and only have to worry about parsing the crate attributes themselves. The related methods have all been updated to take an array of attributes rather than a crate. Additionally, this ceases duplication of the "what output are we producing" logic in order to correctly handle things in the case of --test. Finally, this adds tests for all of this functionality to ensure that it does not regress.
2 parents d5d5c50 + 87add53 commit 9d1de0b

File tree

10 files changed

+127
-67
lines changed

10 files changed

+127
-67
lines changed

src/librustc/back/link.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ pub mod write {
447447
*/
448448

449449
pub fn build_link_meta(sess: Session,
450-
c: &ast::Crate,
450+
attrs: &[ast::Attribute],
451451
output: &Path,
452452
symbol_hasher: &mut Sha256)
453453
-> LinkMeta {
@@ -458,7 +458,7 @@ pub fn build_link_meta(sess: Session,
458458
truncated_hash_result(symbol_hasher).to_managed()
459459
}
460460

461-
let pkgid = match attr::find_pkgid(c.attrs) {
461+
let pkgid = match attr::find_pkgid(attrs) {
462462
None => {
463463
let stem = session::expect(
464464
sess,

src/librustc/driver/driver.rs

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub fn phase_2_configure_and_expand(sess: Session,
165165
let time_passes = sess.time_passes();
166166

167167
*sess.building_library = session::building_library(sess.opts, &crate);
168-
*sess.outputs = session::collect_outputs(sess.opts, &crate);
168+
*sess.outputs = session::collect_outputs(sess.opts, crate.attrs);
169169

170170
time(time_passes, "gated feature checking", (), |_|
171171
front::feature_gate::check_crate(sess, &crate));
@@ -446,42 +446,6 @@ pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &input,
446446
let (outputs, trans) = {
447447
let expanded_crate = {
448448
let crate = phase_1_parse_input(sess, cfg.clone(), input);
449-
let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
450-
// these nasty nested conditions are to avoid doing extra work
451-
if crate_id || crate_name || crate_file_name {
452-
let t_outputs = build_output_filenames(input, outdir, output, crate.attrs, sess);
453-
if crate_id || crate_name {
454-
let pkgid = match attr::find_pkgid(crate.attrs) {
455-
Some(pkgid) => pkgid,
456-
None => fail!("No crate_id and --crate-id or --crate-name requested")
457-
};
458-
if crate_id {
459-
println(pkgid.to_str());
460-
}
461-
if crate_name {
462-
println(pkgid.name);
463-
}
464-
}
465-
466-
if crate_file_name {
467-
let lm = link::build_link_meta(sess, &crate, &t_outputs.obj_filename,
468-
&mut ::util::sha2::Sha256::new());
469-
// if the vector is empty we default to OutputExecutable.
470-
let style = sess.opts.outputs.get_opt(0).unwrap_or(&OutputExecutable);
471-
let fname = link::filename_for_input(&sess, *style, &lm,
472-
&t_outputs.out_filename);
473-
println!("{}", fname.display());
474-
475-
// we already maybe printed the first one, so skip it
476-
for style in sess.opts.outputs.iter().skip(1) {
477-
let fname = link::filename_for_input(&sess, *style, &lm,
478-
&t_outputs.out_filename);
479-
println!("{}", fname.display());
480-
}
481-
}
482-
483-
return;
484-
}
485449
if stop_after_phase_1(sess) { return; }
486450
phase_2_configure_and_expand(sess, cfg, crate)
487451
};

src/librustc/driver/session.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -421,14 +421,15 @@ pub fn building_library(options: &options, crate: &ast::Crate) -> bool {
421421
}
422422
}
423423

424-
pub fn collect_outputs(options: &options, crate: &ast::Crate) -> ~[OutputStyle] {
424+
pub fn collect_outputs(options: &options,
425+
attrs: &[ast::Attribute]) -> ~[OutputStyle] {
425426
// If we're generating a test executable, then ignore all other output
426427
// styles at all other locations
427428
if options.test {
428429
return ~[OutputExecutable];
429430
}
430431
let mut base = options.outputs.clone();
431-
let mut iter = crate.attrs.iter().filter_map(|a| {
432+
let mut iter = attrs.iter().filter_map(|a| {
432433
if "crate_type" == a.name() {
433434
match a.value_str() {
434435
Some(n) if "rlib" == n => Some(OutputRlib),

src/librustc/lib.rs

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,12 @@
2121
extern mod extra;
2222
extern mod syntax;
2323

24-
use driver::driver::{host_triple, optgroups, early_error};
25-
use driver::driver::{str_input, file_input, build_session_options};
26-
use driver::driver::{build_session, build_configuration, parse_pretty};
27-
use driver::driver::{PpMode, pretty_print_input, list_metadata};
28-
use driver::driver::{compile_input};
24+
use back::link;
2925
use driver::session;
3026
use middle::lint;
3127

28+
use d = driver::driver;
29+
3230
use std::cast;
3331
use std::comm;
3432
use std::io;
@@ -41,9 +39,12 @@ use std::task;
4139
use std::vec;
4240
use extra::getopts::groups;
4341
use extra::getopts;
42+
use syntax::ast;
43+
use syntax::attr;
4444
use syntax::codemap;
4545
use syntax::diagnostic::Emitter;
4646
use syntax::diagnostic;
47+
use syntax::parse;
4748

4849
pub mod middle {
4950
pub mod trans;
@@ -137,7 +138,7 @@ pub fn version(argv0: &str) {
137138
None => "unknown version"
138139
};
139140
println!("{} {}", argv0, vers);
140-
println!("host: {}", host_triple());
141+
println!("host: {}", d::host_triple());
141142
}
142143

143144
pub fn usage(argv0: &str) {
@@ -146,7 +147,7 @@ pub fn usage(argv0: &str) {
146147
Additional help:
147148
-W help Print 'lint' options and default settings
148149
-Z help Print internal options for debugging rustc\n",
149-
groups::usage(message, optgroups()));
150+
groups::usage(message, d::optgroups()));
150151
}
151152

152153
pub fn describe_warnings() {
@@ -206,10 +207,10 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
206207
if args.is_empty() { usage(binary); return; }
207208

208209
let matches =
209-
&match getopts::groups::getopts(args, optgroups()) {
210+
&match getopts::groups::getopts(args, d::optgroups()) {
210211
Ok(m) => m,
211212
Err(f) => {
212-
early_error(demitter, f.to_err_msg());
213+
d::early_error(demitter, f.to_err_msg());
213214
}
214215
};
215216

@@ -246,48 +247,97 @@ pub fn run_compiler(args: &[~str], demitter: @diagnostic::Emitter) {
246247
return;
247248
}
248249
let input = match matches.free.len() {
249-
0u => early_error(demitter, "no input filename given"),
250+
0u => d::early_error(demitter, "no input filename given"),
250251
1u => {
251252
let ifile = matches.free[0].as_slice();
252253
if "-" == ifile {
253254
let src = str::from_utf8_owned(io::stdin().read_to_end());
254-
str_input(src.to_managed())
255+
d::str_input(src.to_managed())
255256
} else {
256-
file_input(Path::new(ifile))
257+
d::file_input(Path::new(ifile))
257258
}
258259
}
259-
_ => early_error(demitter, "multiple input filenames provided")
260+
_ => d::early_error(demitter, "multiple input filenames provided")
260261
};
261262

262-
let sopts = build_session_options(binary, matches, demitter);
263-
let sess = build_session(sopts, demitter);
263+
let sopts = d::build_session_options(binary, matches, demitter);
264+
let sess = d::build_session(sopts, demitter);
264265
let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
265266
let ofile = matches.opt_str("o").map(|o| Path::new(o));
266-
let cfg = build_configuration(sess);
267+
let cfg = d::build_configuration(sess);
267268
let pretty = matches.opt_default("pretty", "normal").map(|a| {
268-
parse_pretty(sess, a)
269+
d::parse_pretty(sess, a)
269270
});
270271
match pretty {
271-
Some::<PpMode>(ppm) => {
272-
pretty_print_input(sess, cfg, &input, ppm);
272+
Some::<d::PpMode>(ppm) => {
273+
d::pretty_print_input(sess, cfg, &input, ppm);
273274
return;
274275
}
275-
None::<PpMode> => {/* continue */ }
276+
None::<d::PpMode> => {/* continue */ }
276277
}
277278
let ls = matches.opt_present("ls");
278279
if ls {
279280
match input {
280-
file_input(ref ifile) => {
281-
list_metadata(sess, &(*ifile), @mut io::stdout() as @mut io::Writer);
281+
d::file_input(ref ifile) => {
282+
d::list_metadata(sess, &(*ifile),
283+
@mut io::stdout() as @mut io::Writer);
282284
}
283-
str_input(_) => {
284-
early_error(demitter, "can not list metadata for stdin");
285+
d::str_input(_) => {
286+
d::early_error(demitter, "can not list metadata for stdin");
285287
}
286288
}
287289
return;
288290
}
291+
let (crate_id, crate_name, crate_file_name) = sopts.print_metas;
292+
// these nasty nested conditions are to avoid doing extra work
293+
if crate_id || crate_name || crate_file_name {
294+
let attrs = parse_crate_attrs(sess, &input);
295+
let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
296+
attrs, sess);
297+
if crate_id || crate_name {
298+
let pkgid = match attr::find_pkgid(attrs) {
299+
Some(pkgid) => pkgid,
300+
None => {
301+
sess.fatal("No crate_id and --crate-id or \
302+
--crate-name requested")
303+
}
304+
};
305+
if crate_id {
306+
println(pkgid.to_str());
307+
}
308+
if crate_name {
309+
println(pkgid.name);
310+
}
311+
}
312+
313+
if crate_file_name {
314+
let lm = link::build_link_meta(sess, attrs, &t_outputs.obj_filename,
315+
&mut ::util::sha2::Sha256::new());
316+
let outputs = session::collect_outputs(sopts, attrs);
317+
for &style in outputs.iter() {
318+
let fname = link::filename_for_input(&sess, style, &lm,
319+
&t_outputs.out_filename);
320+
println!("{}", fname.filename_display());
321+
}
322+
}
323+
324+
return;
325+
}
326+
327+
d::compile_input(sess, cfg, &input, &odir, &ofile);
328+
}
289329

290-
compile_input(sess, cfg, &input, &odir, &ofile);
330+
fn parse_crate_attrs(sess: session::Session,
331+
input: &d::input) -> ~[ast::Attribute] {
332+
match *input {
333+
d::file_input(ref ifile) => {
334+
parse::parse_crate_attrs_from_file(ifile, ~[], sess.parse_sess)
335+
}
336+
d::str_input(src) => {
337+
parse::parse_crate_attrs_from_source_str(
338+
d::anon_src(), src, ~[], sess.parse_sess)
339+
}
340+
}
291341
}
292342

293343
#[deriving(Eq)]

src/librustc/middle/trans/base.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3096,7 +3096,7 @@ pub fn trans_crate(sess: session::Session,
30963096
}
30973097

30983098
let mut symbol_hasher = Sha256::new();
3099-
let link_meta = link::build_link_meta(sess, &crate, output,
3099+
let link_meta = link::build_link_meta(sess, crate.attrs, output,
31003100
&mut symbol_hasher);
31013101

31023102
// Append ".rc" to crate name as LLVM module identifier.

src/libsyntax/parse/mod.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,16 @@ pub fn parse_crate_from_file(
7979
// why is there no p.abort_if_errors here?
8080
}
8181

82+
pub fn parse_crate_attrs_from_file(
83+
input: &Path,
84+
cfg: ast::CrateConfig,
85+
sess: @mut ParseSess
86+
) -> ~[ast::Attribute] {
87+
let parser = new_parser_from_file(sess, cfg, input);
88+
let (inner, _) = parser.parse_inner_attrs_and_next();
89+
return inner;
90+
}
91+
8292
pub fn parse_crate_from_source_str(
8393
name: @str,
8494
source: @str,
@@ -92,6 +102,20 @@ pub fn parse_crate_from_source_str(
92102
maybe_aborted(p.parse_crate_mod(),p)
93103
}
94104

105+
pub fn parse_crate_attrs_from_source_str(
106+
name: @str,
107+
source: @str,
108+
cfg: ast::CrateConfig,
109+
sess: @mut ParseSess
110+
) -> ~[ast::Attribute] {
111+
let p = new_parser_from_source_str(sess,
112+
/*bad*/ cfg.clone(),
113+
name,
114+
source);
115+
let (inner, _) = maybe_aborted(p.parse_inner_attrs_and_next(),p);
116+
return inner;
117+
}
118+
95119
pub fn parse_expr_from_source_str(
96120
name: @str,
97121
source: @str,
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-include ../tools.mk
2+
3+
all:
4+
[ `$(RUSTC) --crate-id crate.rs` = "foo#0.9" ]
5+
[ `$(RUSTC) --crate-name crate.rs` = "foo" ]
6+
[ `$(RUSTC) --crate-file-name crate.rs` = "foo" ]
7+
[ `$(RUSTC) --crate-file-name --lib --test crate.rs` = "foo" ]
8+
[ `$(RUSTC) --crate-file-name --test lib.rs` = "mylib" ]
9+
$(RUSTC) --crate-file-name lib.rs
10+
$(RUSTC) --crate-file-name rlib.rs
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#[crate_id = "foo#0.9"];
2+
3+
// Querying about the crate metadata should *not* parse the entire crate, it
4+
// only needs the crate attributes (which are guaranteed to be at the top) be
5+
// sure that if we have an error like a missing module that we can still query
6+
// about the crate id.
7+
mod error;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#[crate_id = "mylib"];
2+
#[crate_type = "lib"];
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#[crate_id = "mylib"];
2+
#[crate_type = "rlib"];

0 commit comments

Comments
 (0)