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.11-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)]
37 extern crate serialize;
40 extern crate collections;
44 #[phase(syntax, link)]
51 use d = driver::driver;
53 use std::any::AnyRefExt;
58 use std::task::TaskBuilder;
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;
138 static BUG_REPORT_URL: &'static str =
139 "http://static.rust-lang.org/doc/master/complement-bugreport.html";
141 pub fn version(argv0: &str) {
142 let vers = match option_env!("CFG_VERSION") {
144 None => "unknown version"
146 println!("{} {}", argv0, vers);
147 println!("host: {}", d::host_triple());
150 pub fn usage(argv0: &str) {
151 let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
154 -C help Print codegen options
155 -W help Print 'lint' options and default settings
156 -Z help Print internal options for debugging rustc\n",
157 getopts::usage(message, d::optgroups().as_slice()));
160 pub fn describe_warnings() {
162 Available lint options:
163 -W <foo> Warn about <foo>
166 -F <foo> Forbid <foo> (deny, and deny all overrides)
169 let lint_dict = lint::get_lint_dict();
170 let mut lint_dict = lint_dict.move_iter()
171 .map(|(k, v)| (v, k))
172 .collect::<Vec<(lint::LintSpec, &'static str)> >();
173 lint_dict.as_mut_slice().sort();
176 for &(_, name) in lint_dict.iter() {
177 max_key = cmp::max(name.len(), max_key);
179 fn padded(max: uint, s: &str) -> ~str {
180 " ".repeat(max - s.len()) + s
182 println!("\nAvailable lint checks:\n");
183 println!(" {} {:7.7s} {}",
184 padded(max_key, "name"), "default", "meaning");
185 println!(" {} {:7.7s} {}\n",
186 padded(max_key, "----"), "-------", "-------");
187 for (spec, name) in lint_dict.move_iter() {
188 let name = name.replace("_", "-");
189 println!(" {} {:7.7s} {}",
190 padded(max_key, name),
191 lint::level_to_str(spec.default),
197 pub fn describe_debug_flags() {
198 println!("\nAvailable debug options:\n");
199 let r = session::debugging_opts_map();
200 for tuple in r.iter() {
202 (ref name, ref desc, _) => {
203 println!(" -Z {:>20s} -- {}", *name, *desc);
209 pub fn describe_codegen_flags() {
210 println!("\nAvailable codegen options:\n");
211 let mut cg = session::basic_codegen_options();
212 for &(name, parser, desc) in session::CG_OPTIONS.iter() {
213 // we invoke the parser function on `None` to see if this option needs
214 // an argument or not.
215 let (width, extra) = if parser(&mut cg, None) {
220 println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"),
221 extra, desc, width=width);
225 pub fn run_compiler(args: &[~str]) {
226 let mut args = Vec::from_slice(args);
227 let binary = args.shift().unwrap();
229 if args.is_empty() { usage(binary); return; }
232 &match getopts::getopts(args.as_slice(), d::optgroups().as_slice()) {
235 d::early_error(f.to_err_msg());
239 if matches.opt_present("h") || matches.opt_present("help") {
244 let lint_flags = matches.opt_strs("W").move_iter().collect::<Vec<_>>().append(
245 matches.opt_strs("warn").as_slice());
246 if lint_flags.iter().any(|x| x == &"help".to_owned()) {
251 let r = matches.opt_strs("Z");
252 if r.iter().any(|x| x == &"help".to_owned()) {
253 describe_debug_flags();
257 let cg_flags = matches.opt_strs("C");
258 if cg_flags.iter().any(|x| x == &"help".to_owned()) {
259 describe_codegen_flags();
263 if cg_flags.contains(&"passes=list".to_owned()) {
264 unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); }
268 if matches.opt_present("v") || matches.opt_present("version") {
272 let (input, input_file_path) = match matches.free.len() {
273 0u => d::early_error("no input filename given"),
275 let ifile = matches.free.get(0).as_slice();
277 let contents = io::stdin().read_to_end().unwrap();
278 let src = str::from_utf8(contents.as_slice()).unwrap().to_owned();
279 (d::StrInput(src), None)
281 (d::FileInput(Path::new(ifile)), Some(Path::new(ifile)))
284 _ => d::early_error("multiple input filenames provided")
287 let sopts = d::build_session_options(matches);
288 let sess = d::build_session(sopts, input_file_path);
289 let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
290 let ofile = matches.opt_str("o").map(|o| Path::new(o));
291 let cfg = d::build_configuration(&sess);
292 let pretty = matches.opt_default("pretty", "normal").map(|a| {
293 d::parse_pretty(&sess, a)
296 Some::<d::PpMode>(ppm) => {
297 d::pretty_print_input(sess, cfg, &input, ppm, ofile);
300 None::<d::PpMode> => {/* continue */ }
303 if r.contains(&~"ls") {
305 d::FileInput(ref ifile) => {
306 let mut stdout = io::stdout();
307 d::list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
310 d::early_error("can not list metadata for stdin");
315 let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
316 // these nasty nested conditions are to avoid doing extra work
317 if crate_id || crate_name || crate_file_name {
318 let attrs = parse_crate_attrs(&sess, &input);
319 let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
320 attrs.as_slice(), &sess);
321 let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
324 println!("{}", id.to_str());
327 println!("{}", id.name);
330 let crate_types = session::collect_crate_types(&sess,
332 for &style in crate_types.iter() {
333 let fname = link::filename_for_input(&sess, style, &id,
334 &t_outputs.with_extension(""));
335 println!("{}", fname.filename_display());
342 d::compile_input(sess, cfg, &input, &odir, &ofile);
345 fn parse_crate_attrs(sess: &session::Session, input: &d::Input) ->
346 Vec<ast::Attribute> {
347 let result = match *input {
348 d::FileInput(ref ifile) => {
349 parse::parse_crate_attrs_from_file(ifile,
353 d::StrInput(ref src) => {
354 parse::parse_crate_attrs_from_source_str(d::anon_src(),
360 result.move_iter().collect()
363 /// Run a procedure which will detect failures in the compiler and print nicer
364 /// error messages rather than just failing the test.
366 /// The diagnostic emitter yielded to the procedure should be used for reporting
367 /// errors of the compiler.
368 pub fn monitor(f: proc():Send) {
369 // FIXME: This is a hack for newsched since it doesn't support split stacks.
370 // rustc needs a lot of stack! When optimizations are disabled, it needs
371 // even *more* stack than usual as well.
373 static STACK_SIZE: uint = 6000000; // 6MB
375 static STACK_SIZE: uint = 20000000; // 20MB
377 let mut task_builder = TaskBuilder::new().named("rustc");
379 // FIXME: Hacks on hacks. If the env is trying to override the stack size
380 // then *don't* set it explicitly.
381 if os::getenv("RUST_MIN_STACK").is_none() {
382 task_builder.opts.stack_size = Some(STACK_SIZE);
385 let (tx, rx) = channel();
386 let w = io::ChanWriter::new(tx);
387 let mut r = io::ChanReader::new(rx);
389 match task_builder.try(proc() {
390 io::stdio::set_stderr(~w);
393 Ok(()) => { /* fallthrough */ }
395 // Task failed without emitting a fatal diagnostic
396 if !value.is::<diagnostic::FatalError>() {
397 let mut emitter = diagnostic::EmitterWriter::stderr();
399 // a .span_bug or .bug call has already printed what
400 // it wants to print.
401 if !value.is::<diagnostic::ExplicitBug>() {
404 "unexpected failure",
409 "the compiler hit an unexpected failure path. this is a bug.".to_owned(),
410 "we would appreciate a bug report: " + BUG_REPORT_URL,
411 "run with `RUST_BACKTRACE=1` for a backtrace".to_owned(),
413 for note in xs.iter() {
414 emitter.emit(None, *note, diagnostic::Note)
417 match r.read_to_str() {
418 Ok(s) => println!("{}", s),
419 Err(e) => emitter.emit(None,
420 format!("failed to read internal stderr: {}", e),
425 // Fail so the process returns a failure code, but don't pollute the
426 // output with some unnecessary failure messages, we've already
427 // printed everything that we needed to.
428 io::stdio::set_stderr(~io::util::NullWriter);
435 std::os::set_exit_status(main_args(std::os::args()));
438 pub fn main_args(args: &[~str]) -> int {
439 let owned_args = args.to_owned();
440 monitor(proc() run_compiler(owned_args));