1 // Copyright 2014 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.
11 //! Contains infrastructure for configuring the compiler, including parsing
12 //! command line options.
14 use driver::{early_error, early_warn};
16 use driver::session::Session;
20 use back::target_strs;
21 use back::{arm, x86, x86_64, mips, mipsel};
26 use syntax::ast::{IntTy, UintTy};
28 use syntax::attr::AttrMetaMethods;
29 use syntax::diagnostic::{ColorConfig, Auto, Always, Never};
31 use syntax::parse::token::InternedString;
33 use std::collections::{HashSet, HashMap};
34 use getopts::{optopt, optmulti, optflag, optflagopt};
36 use std::cell::{RefCell};
43 pub arch: abi::Architecture,
44 pub target_strs: target_strs::t,
46 pub uint_type: UintTy,
49 #[deriving(Clone, PartialEq)]
57 #[deriving(Clone, PartialEq)]
58 pub enum DebugInfoLevel {
66 // The crate config requested for the session, which may be combined
67 // with additional crate configurations during the compile process
68 pub crate_types: Vec<CrateType>,
71 pub optimize: OptLevel,
72 pub debuginfo: DebugInfoLevel,
73 pub lint_opts: Vec<(String, lint::Level)>,
74 pub describe_lints: bool,
75 pub output_types: Vec<back::link::OutputType> ,
76 // This was mutable for rustpkg, which updates search paths based on the
77 // parsed code. It remains mutable in case its replacements wants to use
79 pub addl_lib_search_paths: RefCell<HashSet<Path>>,
80 pub maybe_sysroot: Option<Path>,
81 pub target_triple: String,
82 // User-specified cfg meta items. The compiler itself will add additional
83 // items to the crate config, and during parsing the entire crate config
84 // will be added to the crate AST node. This should not be used for
85 // anything except building the full crate config prior to parsing.
86 pub cfg: ast::CrateConfig,
90 pub no_analysis: bool,
91 pub debugging_opts: u64,
92 /// Whether to write dependency files. It's (enabled, optional filename).
93 pub write_dependency_info: (bool, Option<Path>),
94 /// Crate id-related things to maybe print. It's (crate_name, crate_file_name).
95 pub print_metas: (bool, bool),
96 pub cg: CodegenOptions,
97 pub color: ColorConfig,
98 pub externs: HashMap<String, Vec<String>>,
99 pub crate_name: Option<String>,
102 /// Some reasonable defaults
103 pub fn basic_options() -> Options {
105 crate_types: Vec::new(),
108 debuginfo: NoDebugInfo,
109 lint_opts: Vec::new(),
110 describe_lints: false,
111 output_types: Vec::new(),
112 addl_lib_search_paths: RefCell::new(HashSet::new()),
114 target_triple: driver::host_triple().to_string(),
121 write_dependency_info: (false, None),
122 print_metas: (false, false),
123 cg: basic_codegen_options(),
125 externs: HashMap::new(),
130 // The type of entry function, so
131 // users can have their own entry
132 // functions that don't start a
134 #[deriving(PartialEq)]
135 pub enum EntryFnType {
141 #[deriving(PartialEq, PartialOrd, Clone, Ord, Eq, Hash)]
149 macro_rules! debugging_opts(
150 ([ $opt:ident ] $cnt:expr ) => (
151 pub static $opt: u64 = 1 << $cnt;
153 ([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
154 pub static $opt: u64 = 1 << $cnt;
155 debugging_opts!([ $($rest),* ] $cnt + 1)
183 FLOWGRAPH_PRINT_LOANS,
184 FLOWGRAPH_PRINT_MOVES,
185 FLOWGRAPH_PRINT_ASSIGNS,
191 pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
192 vec!(("verbose", "in general, enable more debug printouts", VERBOSE),
193 ("time-passes", "measure time of each rustc pass", TIME_PASSES),
194 ("count-llvm-insns", "count where LLVM \
195 instrs originate", COUNT_LLVM_INSNS),
196 ("time-llvm-passes", "measure time of each LLVM pass",
198 ("trans-stats", "gather trans statistics", TRANS_STATS),
199 ("asm-comments", "generate comments into the assembly (may change behavior)",
201 ("no-verify", "skip LLVM verification", NO_VERIFY),
202 ("borrowck-stats", "gather borrowck statistics", BORROWCK_STATS),
203 ("no-landing-pads", "omit landing pads for unwinding",
205 ("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
206 ("show-span", "show spans for compiler debugging", SHOW_SPAN),
207 ("count-type-sizes", "count the sizes of aggregate types",
209 ("meta-stats", "gather metadata statistics", META_STATS),
210 ("no-opt", "do not optimize, even if -O is passed", NO_OPT),
211 ("print-link-args", "Print the arguments passed to the linker",
213 ("gc", "Garbage collect shared data (experimental)", GC),
214 ("print-llvm-passes",
215 "Prints the llvm optimization passes being run",
217 ("lto", "Perform LLVM link-time optimizations", LTO),
218 ("ast-json", "Print the AST as JSON and halt", AST_JSON),
219 ("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
220 ("ls", "List the symbols defined by a library crate", LS),
221 ("save-analysis", "Write syntax and type analysis information \
222 in addition to normal output", SAVE_ANALYSIS),
223 ("flowgraph-print-loans", "Include loan analysis data in \
224 --pretty flowgraph output", FLOWGRAPH_PRINT_LOANS),
225 ("flowgraph-print-moves", "Include move analysis data in \
226 --pretty flowgraph output", FLOWGRAPH_PRINT_MOVES),
227 ("flowgraph-print-assigns", "Include assignment analysis data in \
228 --pretty flowgraph output", FLOWGRAPH_PRINT_ASSIGNS),
229 ("flowgraph-print-all", "Include all dataflow analysis data in \
230 --pretty flowgraph output", FLOWGRAPH_PRINT_ALL))
233 /// Declare a macro that will define all CodegenOptions fields and parsers all
234 /// at once. The goal of this macro is to define an interface that can be
235 /// programmatically used by the option parser in order to initialize the struct
236 /// without hardcoding field names all over the place.
238 /// The goal is to invoke this macro once with the correct fields, and then this
239 /// macro generates all necessary code. The main gotcha of this macro is the
240 /// cgsetters module which is a bunch of generated code to parse an option into
241 /// its respective field in the struct. There are a few hand-written parsers for
242 /// parsing specific types of values in this module.
243 macro_rules! cgoptions(
244 ($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
247 pub struct CodegenOptions { $(pub $opt: $t),* }
249 pub fn basic_codegen_options() -> CodegenOptions {
250 CodegenOptions { $($opt: $init),* }
253 pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
254 pub static CG_OPTIONS: &'static [(&'static str, CodegenSetter,
256 &[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
259 use super::CodegenOptions;
262 pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
263 $parse(&mut cg.$opt, v)
267 fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
270 None => { *slot = true; true }
274 fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool {
276 Some(s) => { *slot = Some(s.to_string()); true },
281 fn parse_string(slot: &mut String, v: Option<&str>) -> bool {
283 Some(s) => { *slot = s.to_string(); true },
288 fn parse_list(slot: &mut Vec<String>, v: Option<&str>)
293 slot.push(s.to_string());
305 ar: Option<String> = (None, parse_opt_string,
306 "tool to assemble archives with"),
307 linker: Option<String> = (None, parse_opt_string,
308 "system linker to link outputs with"),
309 link_args: Vec<String> = (Vec::new(), parse_list,
310 "extra arguments to pass to the linker (space separated)"),
311 target_cpu: String = ("generic".to_string(), parse_string,
312 "select target processor (llc -mcpu=help for details)"),
313 target_feature: String = ("".to_string(), parse_string,
314 "target specific attributes (llc -mattr=help for details)"),
315 passes: Vec<String> = (Vec::new(), parse_list,
316 "a list of extra LLVM passes to run (space separated)"),
317 llvm_args: Vec<String> = (Vec::new(), parse_list,
318 "a list of arguments to pass to llvm (space separated)"),
319 save_temps: bool = (false, parse_bool,
320 "save all temporary output files during compilation"),
321 rpath: bool = (false, parse_bool,
322 "set rpath values in libs/exes"),
323 no_prepopulate_passes: bool = (false, parse_bool,
324 "don't pre-populate the pass manager with a list of passes"),
325 no_vectorize_loops: bool = (false, parse_bool,
326 "don't run the loop vectorization optimization passes"),
327 no_vectorize_slp: bool = (false, parse_bool,
328 "don't run LLVM's SLP vectorization pass"),
329 soft_float: bool = (false, parse_bool,
330 "generate software floating point library calls"),
331 prefer_dynamic: bool = (false, parse_bool,
332 "prefer dynamic linking to static linking"),
333 no_integrated_as: bool = (false, parse_bool,
334 "use an external assembler rather than LLVM's integrated one"),
335 relocation_model: String = ("pic".to_string(), parse_string,
336 "choose the relocation model to use (llc -relocation-model for details)"),
337 metadata: Vec<String> = (Vec::new(), parse_list,
338 "metadata to mangle symbol names with"),
339 extra_filename: String = ("".to_string(), parse_string,
340 "extra data to put in each output filename"),
343 pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
345 let mut cg = basic_codegen_options();
346 for option in matches.opt_strs("C").move_iter() {
347 let mut iter = option.as_slice().splitn('=', 1);
348 let key = iter.next().unwrap();
349 let value = iter.next();
350 let option_to_lookup = key.replace("-", "_");
351 let mut found = false;
352 for &(candidate, setter, _) in CG_OPTIONS.iter() {
353 if option_to_lookup.as_slice() != candidate { continue }
354 if !setter(&mut cg, value) {
357 early_error(format!("codegen option `{}` takes no \
358 value", key).as_slice())
361 early_error(format!("codegen option `{0}` requires \
362 a value (-C {0}=<value>)",
371 early_error(format!("unknown codegen option: `{}`",
378 pub fn default_lib_output() -> CrateType {
382 pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
383 let tos = match sess.targ_cfg.os {
384 abi::OsWin32 => InternedString::new("win32"),
385 abi::OsMacos => InternedString::new("macos"),
386 abi::OsLinux => InternedString::new("linux"),
387 abi::OsAndroid => InternedString::new("android"),
388 abi::OsFreebsd => InternedString::new("freebsd"),
389 abi::OsiOS => InternedString::new("ios"),
392 // ARM is bi-endian, however using NDK seems to default
393 // to little-endian unless a flag is provided.
394 let (end,arch,wordsz) = match sess.targ_cfg.arch {
395 abi::X86 => ("little", "x86", "32"),
396 abi::X86_64 => ("little", "x86_64", "64"),
397 abi::Arm => ("little", "arm", "32"),
398 abi::Mips => ("big", "mips", "32"),
399 abi::Mipsel => ("little", "mipsel", "32")
402 let fam = match sess.targ_cfg.os {
403 abi::OsWin32 => InternedString::new("windows"),
404 _ => InternedString::new("unix")
407 let mk = attr::mk_name_value_item_str;
408 return vec!(// Target bindings.
409 attr::mk_word_item(fam.clone()),
410 mk(InternedString::new("target_os"), tos),
411 mk(InternedString::new("target_family"), fam),
412 mk(InternedString::new("target_arch"), InternedString::new(arch)),
413 mk(InternedString::new("target_endian"), InternedString::new(end)),
414 mk(InternedString::new("target_word_size"),
415 InternedString::new(wordsz))
419 pub fn append_configuration(cfg: &mut ast::CrateConfig,
420 name: InternedString) {
421 if !cfg.iter().any(|mi| mi.name() == name) {
422 cfg.push(attr::mk_word_item(name))
426 pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
427 // Combine the configuration requested by the session (command line) with
428 // some default and generated configuration items
429 let default_cfg = default_configuration(sess);
430 let mut user_cfg = sess.opts.cfg.clone();
431 // If the user wants a test runner, then add the test cfg
433 append_configuration(&mut user_cfg, InternedString::new("test"))
435 // If the user requested GC, then add the GC cfg
436 append_configuration(&mut user_cfg, if sess.opts.gc {
437 InternedString::new("gc")
439 InternedString::new("nogc")
441 user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
444 pub fn get_os(triple: &str) -> Option<abi::Os> {
445 for &(name, os) in os_names.iter() {
446 if triple.contains(name) { return Some(os) }
450 static os_names : &'static [(&'static str, abi::Os)] = &[
451 ("mingw32", abi::OsWin32),
452 ("win32", abi::OsWin32),
453 ("darwin", abi::OsMacos),
454 ("android", abi::OsAndroid),
455 ("linux", abi::OsLinux),
456 ("freebsd", abi::OsFreebsd),
457 ("ios", abi::OsiOS)];
459 pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
460 for &(arch, abi) in architecture_abis.iter() {
461 if triple.contains(arch) { return Some(abi) }
465 static architecture_abis : &'static [(&'static str, abi::Architecture)] = &[
472 ("x86_64", abi::X86_64),
475 ("xscale", abi::Arm),
478 ("mipsel", abi::Mipsel),
479 ("mips", abi::Mips)];
481 pub fn build_target_config(sopts: &Options) -> Config {
482 let os = match get_os(sopts.target_triple.as_slice()) {
484 None => early_error("unknown operating system")
486 let arch = match get_arch(sopts.target_triple.as_slice()) {
489 early_error(format!("unknown architecture: {}",
490 sopts.target_triple.as_slice()).as_slice())
493 let (int_type, uint_type) = match arch {
494 abi::X86 => (ast::TyI32, ast::TyU32),
495 abi::X86_64 => (ast::TyI64, ast::TyU64),
496 abi::Arm => (ast::TyI32, ast::TyU32),
497 abi::Mips => (ast::TyI32, ast::TyU32),
498 abi::Mipsel => (ast::TyI32, ast::TyU32)
500 let target_triple = sopts.target_triple.clone();
501 let target_strs = match arch {
502 abi::X86 => x86::get_target_strs(target_triple, os),
503 abi::X86_64 => x86_64::get_target_strs(target_triple, os),
504 abi::Arm => arm::get_target_strs(target_triple, os),
505 abi::Mips => mips::get_target_strs(target_triple, os),
506 abi::Mipsel => mipsel::get_target_strs(target_triple, os)
511 target_strs: target_strs,
513 uint_type: uint_type,
517 // rustc command line options
518 pub fn optgroups() -> Vec<getopts::OptGroup> {
520 optflag("h", "help", "Display this message"),
521 optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
522 optmulti("L", "", "Add a directory to the library search path", "PATH"),
523 optmulti("", "crate-type", "Comma separated list of types of crates
524 for the compiler to emit",
525 "[bin|lib|rlib|dylib|staticlib]"),
526 optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
527 "[asm|bc|ir|obj|link]"),
528 optopt("", "crate-name", "Specify the name of the crate being built",
530 optflag("", "print-crate-name", "Output the crate name and exit"),
531 optflag("", "print-file-name", "Output the file(s) that would be written if compilation \
532 continued and exit"),
533 optflag("", "crate-file-name", "deprecated in favor of --print-file-name"),
534 optflag("g", "", "Equivalent to --debuginfo=2"),
535 optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
537 1 = line-tables only (for stacktraces and breakpoints),
538 2 = full debug info with variable and type information (same as -g)", "LEVEL"),
539 optflag("", "no-trans", "Run all passes except translation; no output"),
540 optflag("", "no-analysis",
541 "Parse and expand the source, but run no analysis and produce no output"),
542 optflag("O", "", "Equivalent to --opt-level=2"),
543 optopt("o", "", "Write output to <filename>", "FILENAME"),
544 optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
545 optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
546 optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
547 optopt("", "explain", "Provide a detailed explanation of an error message", "OPT"),
548 optflagopt("", "pretty",
549 "Pretty-print the input instead of compiling;
550 valid types are: `normal` (un-annotated source),
551 `expanded` (crates expanded),
552 `typed` (crates expanded, with type annotations),
553 `expanded,identified` (fully parenthesized, AST nodes with IDs), or
554 `flowgraph=<nodeid>` (graphviz formatted flowgraph for node)",
556 optflagopt("", "dep-info",
557 "Output dependency info to <filename> after compiling, \
558 in a format suitable for use by Makefiles", "FILENAME"),
559 optopt("", "sysroot", "Override the system root", "PATH"),
560 optflag("", "test", "Build a test harness"),
561 optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
562 to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
563 for details)", "TRIPLE"),
564 optmulti("W", "warn", "Set lint warnings", "OPT"),
565 optmulti("A", "allow", "Set lint allowed", "OPT"),
566 optmulti("D", "deny", "Set lint denied", "OPT"),
567 optmulti("F", "forbid", "Set lint forbidden", "OPT"),
568 optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
569 optmulti("Z", "", "Set internal debugging options", "FLAG"),
570 optflagopt("v", "version", "Print version info and exit", "verbose"),
571 optopt("", "color", "Configure coloring of output:
572 auto = colorize, if output goes to a tty (default);
573 always = always colorize output;
574 never = never colorize output", "auto|always|never"),
575 optmulti("", "extern", "Specify where an external rust library is located",
581 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
582 fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
583 cfgspecs.move_iter().map(|s| {
584 parse::parse_meta_from_source_str("cfgspec".to_string(),
587 &parse::new_parse_sess())
588 }).collect::<ast::CrateConfig>()
591 pub fn build_session_options(matches: &getopts::Matches) -> Options {
592 let mut crate_types: Vec<CrateType> = Vec::new();
593 let unparsed_crate_types = matches.opt_strs("crate-type");
594 for unparsed_crate_type in unparsed_crate_types.iter() {
595 for part in unparsed_crate_type.as_slice().split(',') {
596 let new_part = match part {
597 "lib" => default_lib_output(),
598 "rlib" => CrateTypeRlib,
599 "staticlib" => CrateTypeStaticlib,
600 "dylib" => CrateTypeDylib,
601 "bin" => CrateTypeExecutable,
603 early_error(format!("unknown crate type: `{}`",
607 crate_types.push(new_part)
611 let parse_only = matches.opt_present("parse-only");
612 let no_trans = matches.opt_present("no-trans");
613 let no_analysis = matches.opt_present("no-analysis");
615 let mut lint_opts = vec!();
616 let mut describe_lints = false;
618 for &level in [lint::Allow, lint::Warn, lint::Deny, lint::Forbid].iter() {
619 for lint_name in matches.opt_strs(level.as_str()).move_iter() {
620 if lint_name.as_slice() == "help" {
621 describe_lints = true;
623 lint_opts.push((lint_name.replace("-", "_").into_string(), level));
628 let mut debugging_opts = 0;
629 let debug_flags = matches.opt_strs("Z");
630 let debug_map = debugging_opts_map();
631 for debug_flag in debug_flags.iter() {
632 let mut this_bit = 0;
633 for tuple in debug_map.iter() {
634 let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
635 if *name == debug_flag.as_slice() {
641 early_error(format!("unknown debug flag: {}",
642 *debug_flag).as_slice())
644 debugging_opts |= this_bit;
647 if debugging_opts & DEBUG_LLVM != 0 {
648 unsafe { llvm::LLVMSetDebug(1); }
651 let mut output_types = Vec::new();
652 if !parse_only && !no_trans {
653 let unparsed_output_types = matches.opt_strs("emit");
654 for unparsed_output_type in unparsed_output_types.iter() {
655 for part in unparsed_output_type.as_slice().split(',') {
656 let output_type = match part.as_slice() {
657 "asm" => link::OutputTypeAssembly,
658 "ir" => link::OutputTypeLlvmAssembly,
659 "bc" => link::OutputTypeBitcode,
660 "obj" => link::OutputTypeObject,
661 "link" => link::OutputTypeExe,
663 early_error(format!("unknown emission type: `{}`",
667 output_types.push(output_type)
671 output_types.as_mut_slice().sort();
672 output_types.dedup();
673 if output_types.len() == 0 {
674 output_types.push(link::OutputTypeExe);
677 let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
678 let target = matches.opt_str("target").unwrap_or(
679 driver::host_triple().to_string());
681 if (debugging_opts & NO_OPT) != 0 {
683 } else if matches.opt_present("O") {
684 if matches.opt_present("opt-level") {
685 early_error("-O and --opt-level both provided");
688 } else if matches.opt_present("opt-level") {
689 match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
693 Some("2") => Default,
694 Some("3") => Aggressive,
696 early_error(format!("optimization level needs to be \
697 between 0-3 (instead was `{}`)",
705 let gc = debugging_opts & GC != 0;
706 let debuginfo = if matches.opt_present("g") {
707 if matches.opt_present("debuginfo") {
708 early_error("-g and --debuginfo both provided");
711 } else if matches.opt_present("debuginfo") {
712 match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
713 Some("0") => NoDebugInfo,
714 Some("1") => LimitedDebugInfo,
716 Some("2") => FullDebugInfo,
718 early_error(format!("optimization level needs to be between \
719 0-3 (instead was `{}`)",
727 let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
728 Path::new(s.as_slice())
731 let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
732 let test = matches.opt_present("test");
733 let write_dependency_info = (matches.opt_present("dep-info"),
734 matches.opt_str("dep-info")
735 .map(|p| Path::new(p)));
737 let print_metas = (matches.opt_present("print-crate-name"),
738 matches.opt_present("print-file-name") ||
739 matches.opt_present("crate-file-name"));
740 if matches.opt_present("crate-file-name") {
741 early_warn("the --crate-file-name argument has been renamed to \
744 let cg = build_codegen_options(matches);
746 let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
747 Some("auto") => Auto,
748 Some("always") => Always,
749 Some("never") => Never,
754 early_error(format!("argument for --color must be auto, always \
755 or never (instead was `{}`)",
760 let mut externs = HashMap::new();
761 for arg in matches.opt_strs("extern").iter() {
762 let mut parts = arg.as_slice().splitn('=', 1);
763 let name = match parts.next() {
765 None => early_error("--extern value must not be empty"),
767 let location = match parts.next() {
769 None => early_error("--extern value must be of the format `foo=bar`"),
771 let locs = externs.find_or_insert(name.to_string(), Vec::new());
772 locs.push(location.to_string());
775 let crate_name = matches.opt_str("crate-name");
778 crate_types: crate_types,
781 debuginfo: debuginfo,
782 lint_opts: lint_opts,
783 describe_lints: describe_lints,
784 output_types: output_types,
785 addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
786 maybe_sysroot: sysroot_opt,
787 target_triple: target,
790 parse_only: parse_only,
792 no_analysis: no_analysis,
793 debugging_opts: debugging_opts,
794 write_dependency_info: write_dependency_info,
795 print_metas: print_metas,
799 crate_name: crate_name,
803 impl fmt::Show for CrateType {
804 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
806 CrateTypeExecutable => "bin".fmt(f),
807 CrateTypeDylib => "dylib".fmt(f),
808 CrateTypeRlib => "rlib".fmt(f),
809 CrateTypeStaticlib => "staticlib".fmt(f)
817 use driver::config::{build_configuration, optgroups, build_session_options};
818 use driver::session::build_session;
820 use getopts::getopts;
822 use syntax::attr::AttrMetaMethods;
823 use syntax::diagnostics;
825 // When the user supplies --test we should implicitly supply --cfg test
827 fn test_switch_implies_cfg_test() {
829 &match getopts(["--test".to_string()], optgroups().as_slice()) {
831 Err(f) => fail!("test_switch_implies_cfg_test: {}", f)
833 let registry = diagnostics::registry::Registry::new([]);
834 let sessopts = build_session_options(matches);
835 let sess = build_session(sessopts, None, registry);
836 let cfg = build_configuration(&sess);
837 assert!((attr::contains_name(cfg.as_slice(), "test")));
840 // When the user supplies --test and --cfg test, don't implicitly add
841 // another --cfg test
843 fn test_switch_implies_cfg_test_unless_cfg_test() {
845 &match getopts(["--test".to_string(), "--cfg=test".to_string()],
846 optgroups().as_slice()) {
849 fail!("test_switch_implies_cfg_test_unless_cfg_test: {}", f)
852 let registry = diagnostics::registry::Registry::new([]);
853 let sessopts = build_session_options(matches);
854 let sess = build_session(sessopts, None, registry);
855 let cfg = build_configuration(&sess);
856 let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
857 assert!(test_items.next().is_some());
858 assert!(test_items.next().is_none());