1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
17 This API is completely unstable and subject to change.
21 #[crate_id = "rustc#0.10-pre"];
22 #[comment = "The Rust compiler"];
23 #[license = "MIT/ASL2"];
24 #[crate_type = "dylib"];
25 #[crate_type = "rlib"];
26 #[doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
27 html_favicon_url = "http://www.rust-lang.org/favicon.ico",
28 html_root_url = "http://static.rust-lang.org/doc/master")];
31 #[feature(macro_rules, globs, struct_variant, managed_boxes, quote,
32 default_type_params, phase)];
33 #[allow(deprecated_owned_vector)]; // NOTE: remove after stage0
38 extern crate serialize;
41 extern crate collections;
43 #[phase(syntax, link)]
50 use d = driver::driver;
52 use std::any::AnyRefExt;
60 use syntax::diagnostic::Emitter;
61 use syntax::diagnostic;
70 pub mod resolve_lifetime;
79 pub mod mem_categorization;
102 pub mod assign_node_ids_and_map;
103 pub mod feature_gate;
137 static BUG_REPORT_URL: &'static str =
138 "http://static.rust-lang.org/doc/master/complement-bugreport.html";
140 pub fn version(argv0: &str) {
141 let vers = match option_env!("CFG_VERSION") {
143 None => "unknown version"
145 println!("{} {}", argv0, vers);
146 println!("host: {}", d::host_triple());
149 pub fn usage(argv0: &str) {
150 let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
153 -C help Print codegen options
154 -W help Print 'lint' options and default settings
155 -Z help Print internal options for debugging rustc\n",
156 getopts::usage(message, d::optgroups().as_slice()));
159 pub fn describe_warnings() {
161 Available lint options:
162 -W <foo> Warn about <foo>
165 -F <foo> Forbid <foo> (deny, and deny all overrides)
168 let lint_dict = lint::get_lint_dict();
169 let mut lint_dict = lint_dict.move_iter()
170 .map(|(k, v)| (v, k))
171 .collect::<Vec<(lint::LintSpec, &'static str)> >();
172 lint_dict.as_mut_slice().sort();
175 for &(_, name) in lint_dict.iter() {
176 max_key = cmp::max(name.len(), max_key);
178 fn padded(max: uint, s: &str) -> ~str {
179 " ".repeat(max - s.len()) + s
181 println!("\nAvailable lint checks:\n");
182 println!(" {} {:7.7s} {}",
183 padded(max_key, "name"), "default", "meaning");
184 println!(" {} {:7.7s} {}\n",
185 padded(max_key, "----"), "-------", "-------");
186 for (spec, name) in lint_dict.move_iter() {
187 let name = name.replace("_", "-");
188 println!(" {} {:7.7s} {}",
189 padded(max_key, name),
190 lint::level_to_str(spec.default),
196 pub fn describe_debug_flags() {
197 println!("\nAvailable debug options:\n");
198 let r = session::debugging_opts_map();
199 for tuple in r.iter() {
201 (ref name, ref desc, _) => {
202 println!(" -Z {:>20s} -- {}", *name, *desc);
208 pub fn describe_codegen_flags() {
209 println!("\nAvailable codegen options:\n");
210 let mut cg = session::basic_codegen_options();
211 for &(name, parser, desc) in session::CG_OPTIONS.iter() {
212 // we invoke the parser function on `None` to see if this option needs
213 // an argument or not.
214 let (width, extra) = if parser(&mut cg, None) {
219 println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"),
220 extra, desc, width=width);
224 pub fn run_compiler(args: &[~str]) {
225 let mut args = args.to_owned();
226 let binary = args.shift().unwrap();
228 if args.is_empty() { usage(binary); return; }
231 &match getopts::getopts(args, d::optgroups().as_slice()) {
234 d::early_error(f.to_err_msg());
238 if matches.opt_present("h") || matches.opt_present("help") {
243 let lint_flags = vec::append(matches.opt_strs("W")
246 matches.opt_strs("warn"));
247 if lint_flags.iter().any(|x| x == &~"help") {
252 let r = matches.opt_strs("Z");
253 if r.iter().any(|x| x == &~"help") {
254 describe_debug_flags();
258 let cg_flags = matches.opt_strs("C");
259 if cg_flags.iter().any(|x| x == &~"help") {
260 describe_codegen_flags();
264 if cg_flags.contains(&~"passes=list") {
265 unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); }
269 if matches.opt_present("v") || matches.opt_present("version") {
273 let (input, input_file_path) = match matches.free.len() {
274 0u => d::early_error("no input filename given"),
276 let ifile = matches.free[0].as_slice();
278 let contents = io::stdin().read_to_end().unwrap();
279 let src = str::from_utf8_owned(contents).unwrap();
280 (d::StrInput(src), None)
282 (d::FileInput(Path::new(ifile)), Some(Path::new(ifile)))
285 _ => d::early_error("multiple input filenames provided")
288 let sopts = d::build_session_options(matches);
289 let sess = d::build_session(sopts, input_file_path);
290 let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
291 let ofile = matches.opt_str("o").map(|o| Path::new(o));
292 let cfg = d::build_configuration(&sess);
293 let pretty = matches.opt_default("pretty", "normal").map(|a| {
294 d::parse_pretty(&sess, a)
297 Some::<d::PpMode>(ppm) => {
298 d::pretty_print_input(sess, cfg, &input, ppm);
301 None::<d::PpMode> => {/* continue */ }
303 let ls = matches.opt_present("ls");
306 d::FileInput(ref ifile) => {
307 let mut stdout = io::stdout();
308 d::list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
311 d::early_error("can not list metadata for stdin");
316 let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
317 // these nasty nested conditions are to avoid doing extra work
318 if crate_id || crate_name || crate_file_name {
319 let attrs = parse_crate_attrs(&sess, &input);
320 let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
321 attrs.as_slice(), &sess);
322 let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
325 println!("{}", id.to_str());
328 println!("{}", id.name);
331 let crate_types = session::collect_crate_types(&sess,
333 for &style in crate_types.iter() {
334 let fname = link::filename_for_input(&sess, style, &id,
335 &t_outputs.with_extension(""));
336 println!("{}", fname.filename_display());
343 d::compile_input(sess, cfg, &input, &odir, &ofile);
346 fn parse_crate_attrs(sess: &session::Session, input: &d::Input) ->
347 Vec<ast::Attribute> {
348 let result = match *input {
349 d::FileInput(ref ifile) => {
350 parse::parse_crate_attrs_from_file(ifile,
354 d::StrInput(ref src) => {
355 parse::parse_crate_attrs_from_source_str(d::anon_src(),
361 result.move_iter().collect()
364 /// Run a procedure which will detect failures in the compiler and print nicer
365 /// error messages rather than just failing the test.
367 /// The diagnostic emitter yielded to the procedure should be used for reporting
368 /// errors of the compiler.
369 pub fn monitor(f: proc()) {
370 // FIXME: This is a hack for newsched since it doesn't support split stacks.
371 // rustc needs a lot of stack! When optimizations are disabled, it needs
372 // even *more* stack than usual as well.
374 static STACK_SIZE: uint = 6000000; // 6MB
376 static STACK_SIZE: uint = 20000000; // 20MB
378 let mut task_builder = task::task().named("rustc");
380 // FIXME: Hacks on hacks. If the env is trying to override the stack size
381 // then *don't* set it explicitly.
382 if os::getenv("RUST_MIN_STACK").is_none() {
383 task_builder.opts.stack_size = Some(STACK_SIZE);
386 let (tx, rx) = channel();
387 let w = io::ChanWriter::new(tx);
388 let mut r = io::ChanReader::new(rx);
390 match task_builder.try(proc() {
391 io::stdio::set_stderr(~w as ~io::Writer);
394 Ok(()) => { /* fallthrough */ }
396 // Task failed without emitting a fatal diagnostic
397 if !value.is::<diagnostic::FatalError>() {
398 let mut emitter = diagnostic::EmitterWriter::stderr();
400 // a .span_bug or .bug call has already printed what
401 // it wants to print.
402 if !value.is::<diagnostic::ExplicitBug>() {
405 "unexpected failure",
410 ~"the compiler hit an unexpected failure path. this is a bug.",
411 "we would appreciate a bug report: " + BUG_REPORT_URL,
412 ~"run with `RUST_BACKTRACE=1` for a backtrace",
414 for note in xs.iter() {
415 emitter.emit(None, *note, diagnostic::Note)
418 match r.read_to_str() {
419 Ok(s) => println!("{}", s),
420 Err(e) => emitter.emit(None,
421 format!("failed to read internal stderr: {}", e),
426 // Fail so the process returns a failure code, but don't pollute the
427 // output with some unnecessary failure messages, we've already
428 // printed everything that we needed to.
429 io::stdio::set_stderr(~io::util::NullWriter as ~io::Writer);
436 std::os::set_exit_status(main_args(std::os::args()));
439 pub fn main_args(args: &[~str]) -> int {
440 let owned_args = args.to_owned();
441 monitor(proc() run_compiler(owned_args));