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};
37 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)
187 pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
188 vec!(("verbose", "in general, enable more debug printouts", VERBOSE),
189 ("time-passes", "measure time of each rustc pass", TIME_PASSES),
190 ("count-llvm-insns", "count where LLVM \
191 instrs originate", COUNT_LLVM_INSNS),
192 ("time-llvm-passes", "measure time of each LLVM pass",
194 ("trans-stats", "gather trans statistics", TRANS_STATS),
195 ("asm-comments", "generate comments into the assembly (may change behavior)",
197 ("no-verify", "skip LLVM verification", NO_VERIFY),
198 ("borrowck-stats", "gather borrowck statistics", BORROWCK_STATS),
199 ("no-landing-pads", "omit landing pads for unwinding",
201 ("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
202 ("show-span", "show spans for compiler debugging", SHOW_SPAN),
203 ("count-type-sizes", "count the sizes of aggregate types",
205 ("meta-stats", "gather metadata statistics", META_STATS),
206 ("no-opt", "do not optimize, even if -O is passed", NO_OPT),
207 ("print-link-args", "Print the arguments passed to the linker",
209 ("gc", "Garbage collect shared data (experimental)", GC),
210 ("print-llvm-passes",
211 "Prints the llvm optimization passes being run",
213 ("lto", "Perform LLVM link-time optimizations", LTO),
214 ("ast-json", "Print the AST as JSON and halt", AST_JSON),
215 ("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
216 ("ls", "List the symbols defined by a library crate", LS),
217 ("save-analysis", "Write syntax and type analysis information \
218 in addition to normal output", SAVE_ANALYSIS))
221 /// Declare a macro that will define all CodegenOptions fields and parsers all
222 /// at once. The goal of this macro is to define an interface that can be
223 /// programmatically used by the option parser in order to initialize the struct
224 /// without hardcoding field names all over the place.
226 /// The goal is to invoke this macro once with the correct fields, and then this
227 /// macro generates all necessary code. The main gotcha of this macro is the
228 /// cgsetters module which is a bunch of generated code to parse an option into
229 /// its respective field in the struct. There are a few hand-written parsers for
230 /// parsing specific types of values in this module.
231 macro_rules! cgoptions(
232 ($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
235 pub struct CodegenOptions { $(pub $opt: $t),* }
237 pub fn basic_codegen_options() -> CodegenOptions {
238 CodegenOptions { $($opt: $init),* }
241 pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
242 pub static CG_OPTIONS: &'static [(&'static str, CodegenSetter,
244 &[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
247 use super::CodegenOptions;
250 pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
251 $parse(&mut cg.$opt, v)
255 fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
258 None => { *slot = true; true }
262 fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool {
264 Some(s) => { *slot = Some(s.to_string()); true },
269 fn parse_string(slot: &mut String, v: Option<&str>) -> bool {
271 Some(s) => { *slot = s.to_string(); true },
276 fn parse_list(slot: &mut Vec<String>, v: Option<&str>)
281 slot.push(s.to_string());
293 ar: Option<String> = (None, parse_opt_string,
294 "tool to assemble archives with"),
295 linker: Option<String> = (None, parse_opt_string,
296 "system linker to link outputs with"),
297 link_args: Vec<String> = (Vec::new(), parse_list,
298 "extra arguments to pass to the linker (space separated)"),
299 target_cpu: String = ("generic".to_string(), parse_string,
300 "select target processor (llc -mcpu=help for details)"),
301 target_feature: String = ("".to_string(), parse_string,
302 "target specific attributes (llc -mattr=help for details)"),
303 passes: Vec<String> = (Vec::new(), parse_list,
304 "a list of extra LLVM passes to run (space separated)"),
305 llvm_args: Vec<String> = (Vec::new(), parse_list,
306 "a list of arguments to pass to llvm (space separated)"),
307 save_temps: bool = (false, parse_bool,
308 "save all temporary output files during compilation"),
309 rpath: bool = (false, parse_bool,
310 "set rpath values in libs/exes"),
311 no_prepopulate_passes: bool = (false, parse_bool,
312 "don't pre-populate the pass manager with a list of passes"),
313 no_vectorize_loops: bool = (false, parse_bool,
314 "don't run the loop vectorization optimization passes"),
315 no_vectorize_slp: bool = (false, parse_bool,
316 "don't run LLVM's SLP vectorization pass"),
317 soft_float: bool = (false, parse_bool,
318 "generate software floating point library calls"),
319 prefer_dynamic: bool = (false, parse_bool,
320 "prefer dynamic linking to static linking"),
321 no_integrated_as: bool = (false, parse_bool,
322 "use an external assembler rather than LLVM's integrated one"),
323 relocation_model: String = ("pic".to_string(), parse_string,
324 "choose the relocation model to use (llc -relocation-model for details)"),
325 metadata: Vec<String> = (Vec::new(), parse_list,
326 "metadata to mangle symbol names with"),
327 extra_filename: String = ("".to_string(), parse_string,
328 "extra data to put in each output filename"),
331 pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
333 let mut cg = basic_codegen_options();
334 for option in matches.opt_strs("C").move_iter() {
335 let mut iter = option.as_slice().splitn('=', 1);
336 let key = iter.next().unwrap();
337 let value = iter.next();
338 let option_to_lookup = key.replace("-", "_");
339 let mut found = false;
340 for &(candidate, setter, _) in CG_OPTIONS.iter() {
341 if option_to_lookup.as_slice() != candidate { continue }
342 if !setter(&mut cg, value) {
345 early_error(format!("codegen option `{}` takes no \
346 value", key).as_slice())
349 early_error(format!("codegen option `{0}` requires \
350 a value (-C {0}=<value>)",
359 early_error(format!("unknown codegen option: `{}`",
366 pub fn default_lib_output() -> CrateType {
370 pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
371 let tos = match sess.targ_cfg.os {
372 abi::OsWin32 => InternedString::new("win32"),
373 abi::OsMacos => InternedString::new("macos"),
374 abi::OsLinux => InternedString::new("linux"),
375 abi::OsAndroid => InternedString::new("android"),
376 abi::OsFreebsd => InternedString::new("freebsd"),
377 abi::OsiOS => InternedString::new("ios"),
380 // ARM is bi-endian, however using NDK seems to default
381 // to little-endian unless a flag is provided.
382 let (end,arch,wordsz) = match sess.targ_cfg.arch {
383 abi::X86 => ("little", "x86", "32"),
384 abi::X86_64 => ("little", "x86_64", "64"),
385 abi::Arm => ("little", "arm", "32"),
386 abi::Mips => ("big", "mips", "32"),
387 abi::Mipsel => ("little", "mipsel", "32")
390 let fam = match sess.targ_cfg.os {
391 abi::OsWin32 => InternedString::new("windows"),
392 _ => InternedString::new("unix")
395 let mk = attr::mk_name_value_item_str;
396 return vec!(// Target bindings.
397 attr::mk_word_item(fam.clone()),
398 mk(InternedString::new("target_os"), tos),
399 mk(InternedString::new("target_family"), fam),
400 mk(InternedString::new("target_arch"), InternedString::new(arch)),
401 mk(InternedString::new("target_endian"), InternedString::new(end)),
402 mk(InternedString::new("target_word_size"),
403 InternedString::new(wordsz))
407 pub fn append_configuration(cfg: &mut ast::CrateConfig,
408 name: InternedString) {
409 if !cfg.iter().any(|mi| mi.name() == name) {
410 cfg.push(attr::mk_word_item(name))
414 pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
415 // Combine the configuration requested by the session (command line) with
416 // some default and generated configuration items
417 let default_cfg = default_configuration(sess);
418 let mut user_cfg = sess.opts.cfg.clone();
419 // If the user wants a test runner, then add the test cfg
421 append_configuration(&mut user_cfg, InternedString::new("test"))
423 // If the user requested GC, then add the GC cfg
424 append_configuration(&mut user_cfg, if sess.opts.gc {
425 InternedString::new("gc")
427 InternedString::new("nogc")
429 user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
432 pub fn get_os(triple: &str) -> Option<abi::Os> {
433 for &(name, os) in os_names.iter() {
434 if triple.contains(name) { return Some(os) }
438 static os_names : &'static [(&'static str, abi::Os)] = &[
439 ("mingw32", abi::OsWin32),
440 ("win32", abi::OsWin32),
441 ("darwin", abi::OsMacos),
442 ("android", abi::OsAndroid),
443 ("linux", abi::OsLinux),
444 ("freebsd", abi::OsFreebsd),
445 ("ios", abi::OsiOS)];
447 pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
448 for &(arch, abi) in architecture_abis.iter() {
449 if triple.contains(arch) { return Some(abi) }
453 static architecture_abis : &'static [(&'static str, abi::Architecture)] = &[
460 ("x86_64", abi::X86_64),
463 ("xscale", abi::Arm),
466 ("mipsel", abi::Mipsel),
467 ("mips", abi::Mips)];
469 pub fn build_target_config(sopts: &Options) -> Config {
470 let os = match get_os(sopts.target_triple.as_slice()) {
472 None => early_error("unknown operating system")
474 let arch = match get_arch(sopts.target_triple.as_slice()) {
477 early_error(format!("unknown architecture: {}",
478 sopts.target_triple.as_slice()).as_slice())
481 let (int_type, uint_type) = match arch {
482 abi::X86 => (ast::TyI32, ast::TyU32),
483 abi::X86_64 => (ast::TyI64, ast::TyU64),
484 abi::Arm => (ast::TyI32, ast::TyU32),
485 abi::Mips => (ast::TyI32, ast::TyU32),
486 abi::Mipsel => (ast::TyI32, ast::TyU32)
488 let target_triple = sopts.target_triple.clone();
489 let target_strs = match arch {
490 abi::X86 => x86::get_target_strs(target_triple, os),
491 abi::X86_64 => x86_64::get_target_strs(target_triple, os),
492 abi::Arm => arm::get_target_strs(target_triple, os),
493 abi::Mips => mips::get_target_strs(target_triple, os),
494 abi::Mipsel => mipsel::get_target_strs(target_triple, os)
499 target_strs: target_strs,
501 uint_type: uint_type,
505 // rustc command line options
506 pub fn optgroups() -> Vec<getopts::OptGroup> {
508 optflag("h", "help", "Display this message"),
509 optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
510 optmulti("L", "", "Add a directory to the library search path", "PATH"),
511 optmulti("", "crate-type", "Comma separated list of types of crates
512 for the compiler to emit",
513 "[bin|lib|rlib|dylib|staticlib]"),
514 optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
515 "[asm|bc|ir|obj|link]"),
516 optopt("", "crate-name", "Specify the name of the crate being built",
518 optflag("", "print-crate-name", "Output the crate name and exit"),
519 optflag("", "print-file-name", "Output the file(s) that would be written if compilation \
520 continued and exit"),
521 optflag("", "crate-file-name", "deprecated in favor of --print-file-name"),
522 optflag("g", "", "Equivalent to --debuginfo=2"),
523 optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
525 1 = line-tables only (for stacktraces and breakpoints),
526 2 = full debug info with variable and type information (same as -g)", "LEVEL"),
527 optflag("", "no-trans", "Run all passes except translation; no output"),
528 optflag("", "no-analysis",
529 "Parse and expand the source, but run no analysis and produce no output"),
530 optflag("O", "", "Equivalent to --opt-level=2"),
531 optopt("o", "", "Write output to <filename>", "FILENAME"),
532 optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
533 optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
534 optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
535 optopt("", "explain", "Provide a detailed explanation of an error message", "OPT"),
536 optflagopt("", "pretty",
537 "Pretty-print the input instead of compiling;
538 valid types are: `normal` (un-annotated source),
539 `expanded` (crates expanded),
540 `typed` (crates expanded, with type annotations),
541 `expanded,identified` (fully parenthesized, AST nodes with IDs), or
542 `flowgraph=<nodeid>` (graphviz formatted flowgraph for node)",
544 optflagopt("", "dep-info",
545 "Output dependency info to <filename> after compiling, \
546 in a format suitable for use by Makefiles", "FILENAME"),
547 optopt("", "sysroot", "Override the system root", "PATH"),
548 optflag("", "test", "Build a test harness"),
549 optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
550 to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
551 for details)", "TRIPLE"),
552 optmulti("W", "warn", "Set lint warnings", "OPT"),
553 optmulti("A", "allow", "Set lint allowed", "OPT"),
554 optmulti("D", "deny", "Set lint denied", "OPT"),
555 optmulti("F", "forbid", "Set lint forbidden", "OPT"),
556 optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
557 optmulti("Z", "", "Set internal debugging options", "FLAG"),
558 optflagopt("v", "version", "Print version info and exit", "verbose"),
559 optopt("", "color", "Configure coloring of output:
560 auto = colorize, if output goes to a tty (default);
561 always = always colorize output;
562 never = never colorize output", "auto|always|never"),
563 optmulti("", "extern", "Specify where an external rust library is located",
569 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
570 fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
571 cfgspecs.move_iter().map(|s| {
572 parse::parse_meta_from_source_str("cfgspec".to_string(),
575 &parse::new_parse_sess())
576 }).collect::<ast::CrateConfig>()
579 pub fn build_session_options(matches: &getopts::Matches) -> Options {
580 let mut crate_types: Vec<CrateType> = Vec::new();
581 let unparsed_crate_types = matches.opt_strs("crate-type");
582 for unparsed_crate_type in unparsed_crate_types.iter() {
583 for part in unparsed_crate_type.as_slice().split(',') {
584 let new_part = match part {
585 "lib" => default_lib_output(),
586 "rlib" => CrateTypeRlib,
587 "staticlib" => CrateTypeStaticlib,
588 "dylib" => CrateTypeDylib,
589 "bin" => CrateTypeExecutable,
591 early_error(format!("unknown crate type: `{}`",
595 crate_types.push(new_part)
599 let parse_only = matches.opt_present("parse-only");
600 let no_trans = matches.opt_present("no-trans");
601 let no_analysis = matches.opt_present("no-analysis");
603 let mut lint_opts = vec!();
604 let mut describe_lints = false;
606 for &level in [lint::Allow, lint::Warn, lint::Deny, lint::Forbid].iter() {
607 for lint_name in matches.opt_strs(level.as_str()).move_iter() {
608 if lint_name.as_slice() == "help" {
609 describe_lints = true;
611 lint_opts.push((lint_name.replace("-", "_").into_string(), level));
616 let mut debugging_opts = 0;
617 let debug_flags = matches.opt_strs("Z");
618 let debug_map = debugging_opts_map();
619 for debug_flag in debug_flags.iter() {
620 let mut this_bit = 0;
621 for tuple in debug_map.iter() {
622 let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
623 if *name == debug_flag.as_slice() {
629 early_error(format!("unknown debug flag: {}",
630 *debug_flag).as_slice())
632 debugging_opts |= this_bit;
635 if debugging_opts & DEBUG_LLVM != 0 {
636 unsafe { llvm::LLVMSetDebug(1); }
639 let mut output_types = Vec::new();
640 if !parse_only && !no_trans {
641 let unparsed_output_types = matches.opt_strs("emit");
642 for unparsed_output_type in unparsed_output_types.iter() {
643 for part in unparsed_output_type.as_slice().split(',') {
644 let output_type = match part.as_slice() {
645 "asm" => link::OutputTypeAssembly,
646 "ir" => link::OutputTypeLlvmAssembly,
647 "bc" => link::OutputTypeBitcode,
648 "obj" => link::OutputTypeObject,
649 "link" => link::OutputTypeExe,
651 early_error(format!("unknown emission type: `{}`",
655 output_types.push(output_type)
659 output_types.as_mut_slice().sort();
660 output_types.dedup();
661 if output_types.len() == 0 {
662 output_types.push(link::OutputTypeExe);
665 let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
666 let target = matches.opt_str("target").unwrap_or(
667 driver::host_triple().to_string());
669 if (debugging_opts & NO_OPT) != 0 {
671 } else if matches.opt_present("O") {
672 if matches.opt_present("opt-level") {
673 early_error("-O and --opt-level both provided");
676 } else if matches.opt_present("opt-level") {
677 match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
681 Some("2") => Default,
682 Some("3") => Aggressive,
684 early_error(format!("optimization level needs to be \
685 between 0-3 (instead was `{}`)",
693 let gc = debugging_opts & GC != 0;
694 let debuginfo = if matches.opt_present("g") {
695 if matches.opt_present("debuginfo") {
696 early_error("-g and --debuginfo both provided");
699 } else if matches.opt_present("debuginfo") {
700 match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
701 Some("0") => NoDebugInfo,
702 Some("1") => LimitedDebugInfo,
704 Some("2") => FullDebugInfo,
706 early_error(format!("optimization level needs to be between \
707 0-3 (instead was `{}`)",
715 let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
716 Path::new(s.as_slice())
719 let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
720 let test = matches.opt_present("test");
721 let write_dependency_info = (matches.opt_present("dep-info"),
722 matches.opt_str("dep-info")
723 .map(|p| Path::new(p)));
725 let print_metas = (matches.opt_present("print-crate-name"),
726 matches.opt_present("print-file-name") ||
727 matches.opt_present("crate-file-name"));
728 if matches.opt_present("crate-file-name") {
729 early_warn("the --crate-file-name argument has been renamed to \
732 let cg = build_codegen_options(matches);
734 let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
735 Some("auto") => Auto,
736 Some("always") => Always,
737 Some("never") => Never,
742 early_error(format!("argument for --color must be auto, always \
743 or never (instead was `{}`)",
748 let mut externs = HashMap::new();
749 for arg in matches.opt_strs("extern").iter() {
750 let mut parts = arg.as_slice().splitn('=', 1);
751 let name = match parts.next() {
753 None => early_error("--extern value must not be empty"),
755 let location = match parts.next() {
757 None => early_error("--extern value must be of the format `foo=bar`"),
759 let locs = externs.find_or_insert(name.to_string(), Vec::new());
760 locs.push(location.to_string());
763 let crate_name = matches.opt_str("crate-name");
766 crate_types: crate_types,
769 debuginfo: debuginfo,
770 lint_opts: lint_opts,
771 describe_lints: describe_lints,
772 output_types: output_types,
773 addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
774 maybe_sysroot: sysroot_opt,
775 target_triple: target,
778 parse_only: parse_only,
780 no_analysis: no_analysis,
781 debugging_opts: debugging_opts,
782 write_dependency_info: write_dependency_info,
783 print_metas: print_metas,
787 crate_name: crate_name,
791 impl fmt::Show for CrateType {
792 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
794 CrateTypeExecutable => "bin".fmt(f),
795 CrateTypeDylib => "dylib".fmt(f),
796 CrateTypeRlib => "rlib".fmt(f),
797 CrateTypeStaticlib => "staticlib".fmt(f)
805 use driver::config::{build_configuration, optgroups, build_session_options};
806 use driver::session::build_session;
808 use getopts::getopts;
810 use syntax::attr::AttrMetaMethods;
811 use syntax::diagnostics;
813 // When the user supplies --test we should implicitly supply --cfg test
815 fn test_switch_implies_cfg_test() {
817 &match getopts(["--test".to_string()], optgroups().as_slice()) {
819 Err(f) => fail!("test_switch_implies_cfg_test: {}", f)
821 let registry = diagnostics::registry::Registry::new([]);
822 let sessopts = build_session_options(matches);
823 let sess = build_session(sessopts, None, registry);
824 let cfg = build_configuration(&sess);
825 assert!((attr::contains_name(cfg.as_slice(), "test")));
828 // When the user supplies --test and --cfg test, don't implicitly add
829 // another --cfg test
831 fn test_switch_implies_cfg_test_unless_cfg_test() {
833 &match getopts(["--test".to_string(), "--cfg=test".to_string()],
834 optgroups().as_slice()) {
837 fail!("test_switch_implies_cfg_test_unless_cfg_test: {}", f)
840 let registry = diagnostics::registry::Registry::new([]);
841 let sessopts = build_session_options(matches);
842 let sess = build_session(sessopts, None, registry);
843 let cfg = build_configuration(&sess);
844 let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
845 assert!(test_items.next().is_some());
846 assert!(test_items.next().is_none());