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)];
32 #[feature(quote, default_type_params)];
38 extern crate serialize;
41 extern crate collections;
48 use d = driver::driver;
50 use std::any::AnyRefExt;
59 use syntax::diagnostic::Emitter;
60 use syntax::diagnostic;
69 pub mod resolve_lifetime;
78 pub mod mem_categorization;
101 pub mod assign_node_ids_and_map;
102 pub mod feature_gate;
136 pub fn version(argv0: &str) {
137 let vers = match option_env!("CFG_VERSION") {
139 None => "unknown version"
141 println!("{} {}", argv0, vers);
142 println!("host: {}", d::host_triple());
145 pub fn usage(argv0: &str) {
146 let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
149 -C help Print codegen options
150 -W help Print 'lint' options and default settings
151 -Z help Print internal options for debugging rustc\n",
152 getopts::usage(message, d::optgroups()));
155 pub fn describe_warnings() {
157 Available lint options:
158 -W <foo> Warn about <foo>
161 -F <foo> Forbid <foo> (deny, and deny all overrides)
164 let lint_dict = lint::get_lint_dict();
165 let mut lint_dict = lint_dict.move_iter()
166 .map(|(k, v)| (v, k))
167 .collect::<~[(lint::LintSpec, &'static str)]>();
171 for &(_, name) in lint_dict.iter() {
172 max_key = cmp::max(name.len(), max_key);
174 fn padded(max: uint, s: &str) -> ~str {
175 " ".repeat(max - s.len()) + s
177 println!("\nAvailable lint checks:\n");
178 println!(" {} {:7.7s} {}",
179 padded(max_key, "name"), "default", "meaning");
180 println!(" {} {:7.7s} {}\n",
181 padded(max_key, "----"), "-------", "-------");
182 for (spec, name) in lint_dict.move_iter() {
183 let name = name.replace("_", "-");
184 println!(" {} {:7.7s} {}",
185 padded(max_key, name),
186 lint::level_to_str(spec.default),
192 pub fn describe_debug_flags() {
193 println!("\nAvailable debug options:\n");
194 let r = session::debugging_opts_map();
195 for tuple in r.iter() {
197 (ref name, ref desc, _) => {
198 println!(" -Z {:>20s} -- {}", *name, *desc);
204 pub fn describe_codegen_flags() {
205 println!("\nAvailable codegen options:\n");
206 let mut cg = session::basic_codegen_options();
207 for &(name, parser, desc) in session::CG_OPTIONS.iter() {
208 // we invoke the parser function on `None` to see if this option needs
209 // an argument or not.
210 let (width, extra) = if parser(&mut cg, None) {
215 println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"),
216 extra, desc, width=width);
220 pub fn run_compiler(args: &[~str]) {
221 let mut args = args.to_owned();
222 let binary = args.shift().unwrap();
224 if args.is_empty() { usage(binary); return; }
227 &match getopts::getopts(args, d::optgroups()) {
230 d::early_error(f.to_err_msg());
234 if matches.opt_present("h") || matches.opt_present("help") {
239 let lint_flags = vec::append(matches.opt_strs("W"),
240 matches.opt_strs("warn"));
241 if lint_flags.iter().any(|x| x == &~"help") {
246 let r = matches.opt_strs("Z");
247 if r.iter().any(|x| x == &~"help") {
248 describe_debug_flags();
252 let cg_flags = matches.opt_strs("C");
253 if cg_flags.iter().any(|x| x == &~"help") {
254 describe_codegen_flags();
258 if cg_flags.contains(&~"passes=list") {
259 unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); }
263 if matches.opt_present("v") || matches.opt_present("version") {
267 let (input, input_file_path) = match matches.free.len() {
268 0u => d::early_error("no input filename given"),
270 let ifile = matches.free[0].as_slice();
272 let contents = io::stdin().read_to_end().unwrap();
273 let src = str::from_utf8_owned(contents).unwrap();
274 (d::StrInput(src), None)
276 (d::FileInput(Path::new(ifile)), Some(Path::new(ifile)))
279 _ => d::early_error("multiple input filenames provided")
282 let sopts = d::build_session_options(matches);
283 let sess = d::build_session(sopts, input_file_path);
284 let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
285 let ofile = matches.opt_str("o").map(|o| Path::new(o));
286 let cfg = d::build_configuration(sess);
287 let pretty = matches.opt_default("pretty", "normal").map(|a| {
288 d::parse_pretty(sess, a)
291 Some::<d::PpMode>(ppm) => {
292 d::pretty_print_input(sess, cfg, &input, ppm);
295 None::<d::PpMode> => {/* continue */ }
297 let ls = matches.opt_present("ls");
300 d::FileInput(ref ifile) => {
301 let mut stdout = io::stdout();
302 d::list_metadata(sess, &(*ifile), &mut stdout).unwrap();
305 d::early_error("can not list metadata for stdin");
310 let (crate_id, crate_name, crate_file_name) = sopts.print_metas;
311 // these nasty nested conditions are to avoid doing extra work
312 if crate_id || crate_name || crate_file_name {
313 let attrs = parse_crate_attrs(sess, &input);
314 let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
316 let id = link::find_crate_id(attrs, &t_outputs);
319 println!("{}", id.to_str());
322 println!("{}", id.name);
325 let crate_types = session::collect_crate_types(&sess, attrs);
326 for &style in crate_types.iter() {
327 let fname = link::filename_for_input(&sess, style, &id,
328 &t_outputs.with_extension(""));
329 println!("{}", fname.filename_display());
336 d::compile_input(sess, cfg, &input, &odir, &ofile);
339 fn parse_crate_attrs(sess: session::Session, input: &d::Input) ->
341 let result = match *input {
342 d::FileInput(ref ifile) => {
343 parse::parse_crate_attrs_from_file(ifile,
347 d::StrInput(ref src) => {
348 parse::parse_crate_attrs_from_source_str(d::anon_src(),
354 result.move_iter().collect()
357 /// Run a procedure which will detect failures in the compiler and print nicer
358 /// error messages rather than just failing the test.
360 /// The diagnostic emitter yielded to the procedure should be used for reporting
361 /// errors of the compiler.
362 pub fn monitor(f: proc()) {
363 // FIXME: This is a hack for newsched since it doesn't support split stacks.
364 // rustc needs a lot of stack! When optimizations are disabled, it needs
365 // even *more* stack than usual as well.
367 static STACK_SIZE: uint = 6000000; // 6MB
369 static STACK_SIZE: uint = 20000000; // 20MB
371 let mut task_builder = task::task().named("rustc");
373 // FIXME: Hacks on hacks. If the env is trying to override the stack size
374 // then *don't* set it explicitly.
375 if os::getenv("RUST_MIN_STACK").is_none() {
376 task_builder.opts.stack_size = Some(STACK_SIZE);
379 let (p, c) = Chan::new();
380 let w = io::ChanWriter::new(c);
381 let mut r = io::PortReader::new(p);
383 match task_builder.try(proc() {
384 io::stdio::set_stderr(~w as ~io::Writer);
387 Ok(()) => { /* fallthrough */ }
389 // Task failed without emitting a fatal diagnostic
390 if !value.is::<diagnostic::FatalError>() {
391 let mut emitter = diagnostic::EmitterWriter::stderr();
394 diagnostic::ice_msg("unexpected failure"),
398 ~"the compiler hit an unexpected failure path. \
401 for note in xs.iter() {
402 emitter.emit(None, *note, diagnostic::Note)
405 println!("{}", r.read_to_str());
408 // Fail so the process returns a failure code, but don't pollute the
409 // output with some unnecessary failure messages, we've already
410 // printed everything that we needed to.
411 io::stdio::set_stderr(~io::util::NullWriter as ~io::Writer);
418 std::os::set_exit_status(main_args(std::os::args()));
421 pub fn main_args(args: &[~str]) -> int {
422 let owned_args = args.to_owned();
423 monitor(proc() run_compiler(owned_args));