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 no_rpath: bool = (false, parse_bool,
310 "disables setting the rpath 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 optflagopt("", "pretty",
536 "Pretty-print the input instead of compiling;
537 valid types are: `normal` (un-annotated source),
538 `expanded` (crates expanded),
539 `typed` (crates expanded, with type annotations),
540 `expanded,identified` (fully parenthesized, AST nodes with IDs), or
541 `flowgraph=<nodeid>` (graphviz formatted flowgraph for node)",
543 optflagopt("", "dep-info",
544 "Output dependency info to <filename> after compiling, \
545 in a format suitable for use by Makefiles", "FILENAME"),
546 optopt("", "sysroot", "Override the system root", "PATH"),
547 optflag("", "test", "Build a test harness"),
548 optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
549 to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
550 for details)", "TRIPLE"),
551 optmulti("W", "warn", "Set lint warnings", "OPT"),
552 optmulti("A", "allow", "Set lint allowed", "OPT"),
553 optmulti("D", "deny", "Set lint denied", "OPT"),
554 optmulti("F", "forbid", "Set lint forbidden", "OPT"),
555 optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
556 optmulti("Z", "", "Set internal debugging options", "FLAG"),
557 optflagopt("v", "version", "Print version info and exit", "verbose"),
558 optopt("", "color", "Configure coloring of output:
559 auto = colorize, if output goes to a tty (default);
560 always = always colorize output;
561 never = never colorize output", "auto|always|never"),
562 optmulti("", "extern", "Specify where an external rust library is located",
568 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
569 fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
570 cfgspecs.move_iter().map(|s| {
571 parse::parse_meta_from_source_str("cfgspec".to_string(),
574 &parse::new_parse_sess())
575 }).collect::<ast::CrateConfig>()
578 pub fn build_session_options(matches: &getopts::Matches) -> Options {
579 let mut crate_types: Vec<CrateType> = Vec::new();
580 let unparsed_crate_types = matches.opt_strs("crate-type");
581 for unparsed_crate_type in unparsed_crate_types.iter() {
582 for part in unparsed_crate_type.as_slice().split(',') {
583 let new_part = match part {
584 "lib" => default_lib_output(),
585 "rlib" => CrateTypeRlib,
586 "staticlib" => CrateTypeStaticlib,
587 "dylib" => CrateTypeDylib,
588 "bin" => CrateTypeExecutable,
590 early_error(format!("unknown crate type: `{}`",
594 crate_types.push(new_part)
598 let parse_only = matches.opt_present("parse-only");
599 let no_trans = matches.opt_present("no-trans");
600 let no_analysis = matches.opt_present("no-analysis");
602 let mut lint_opts = vec!();
603 let mut describe_lints = false;
605 for &level in [lint::Allow, lint::Warn, lint::Deny, lint::Forbid].iter() {
606 for lint_name in matches.opt_strs(level.as_str()).move_iter() {
607 if lint_name.as_slice() == "help" {
608 describe_lints = true;
610 lint_opts.push((lint_name.replace("-", "_").into_string(), level));
615 let mut debugging_opts = 0;
616 let debug_flags = matches.opt_strs("Z");
617 let debug_map = debugging_opts_map();
618 for debug_flag in debug_flags.iter() {
619 let mut this_bit = 0;
620 for tuple in debug_map.iter() {
621 let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
622 if *name == debug_flag.as_slice() {
628 early_error(format!("unknown debug flag: {}",
629 *debug_flag).as_slice())
631 debugging_opts |= this_bit;
634 if debugging_opts & DEBUG_LLVM != 0 {
635 unsafe { llvm::LLVMSetDebug(1); }
638 let mut output_types = Vec::new();
639 if !parse_only && !no_trans {
640 let unparsed_output_types = matches.opt_strs("emit");
641 for unparsed_output_type in unparsed_output_types.iter() {
642 for part in unparsed_output_type.as_slice().split(',') {
643 let output_type = match part.as_slice() {
644 "asm" => link::OutputTypeAssembly,
645 "ir" => link::OutputTypeLlvmAssembly,
646 "bc" => link::OutputTypeBitcode,
647 "obj" => link::OutputTypeObject,
648 "link" => link::OutputTypeExe,
650 early_error(format!("unknown emission type: `{}`",
654 output_types.push(output_type)
658 output_types.as_mut_slice().sort();
659 output_types.dedup();
660 if output_types.len() == 0 {
661 output_types.push(link::OutputTypeExe);
664 let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
665 let target = matches.opt_str("target").unwrap_or(
666 driver::host_triple().to_string());
668 if (debugging_opts & NO_OPT) != 0 {
670 } else if matches.opt_present("O") {
671 if matches.opt_present("opt-level") {
672 early_error("-O and --opt-level both provided");
675 } else if matches.opt_present("opt-level") {
676 match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
680 Some("2") => Default,
681 Some("3") => Aggressive,
683 early_error(format!("optimization level needs to be \
684 between 0-3 (instead was `{}`)",
692 let gc = debugging_opts & GC != 0;
693 let debuginfo = if matches.opt_present("g") {
694 if matches.opt_present("debuginfo") {
695 early_error("-g and --debuginfo both provided");
698 } else if matches.opt_present("debuginfo") {
699 match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
700 Some("0") => NoDebugInfo,
701 Some("1") => LimitedDebugInfo,
703 Some("2") => FullDebugInfo,
705 early_error(format!("optimization level needs to be between \
706 0-3 (instead was `{}`)",
714 let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
715 Path::new(s.as_slice())
718 let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
719 let test = matches.opt_present("test");
720 let write_dependency_info = (matches.opt_present("dep-info"),
721 matches.opt_str("dep-info")
722 .map(|p| Path::new(p)));
724 let print_metas = (matches.opt_present("print-crate-name"),
725 matches.opt_present("print-file-name") ||
726 matches.opt_present("crate-file-name"));
727 if matches.opt_present("crate-file-name") {
728 early_warn("the --crate-file-name argument has been renamed to \
731 let cg = build_codegen_options(matches);
733 let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
734 Some("auto") => Auto,
735 Some("always") => Always,
736 Some("never") => Never,
741 early_error(format!("argument for --color must be auto, always \
742 or never (instead was `{}`)",
747 let mut externs = HashMap::new();
748 for arg in matches.opt_strs("extern").iter() {
749 let mut parts = arg.as_slice().splitn('=', 1);
750 let name = match parts.next() {
752 None => early_error("--extern value must not be empty"),
754 let location = match parts.next() {
756 None => early_error("--extern value must be of the format `foo=bar`"),
758 let locs = externs.find_or_insert(name.to_string(), Vec::new());
759 locs.push(location.to_string());
762 let crate_name = matches.opt_str("crate-name");
765 crate_types: crate_types,
768 debuginfo: debuginfo,
769 lint_opts: lint_opts,
770 describe_lints: describe_lints,
771 output_types: output_types,
772 addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
773 maybe_sysroot: sysroot_opt,
774 target_triple: target,
777 parse_only: parse_only,
779 no_analysis: no_analysis,
780 debugging_opts: debugging_opts,
781 write_dependency_info: write_dependency_info,
782 print_metas: print_metas,
786 crate_name: crate_name,
790 impl fmt::Show for CrateType {
791 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
793 CrateTypeExecutable => "bin".fmt(f),
794 CrateTypeDylib => "dylib".fmt(f),
795 CrateTypeRlib => "rlib".fmt(f),
796 CrateTypeStaticlib => "staticlib".fmt(f)
804 use driver::config::{build_configuration, optgroups, build_session_options};
805 use driver::session::build_session;
807 use getopts::getopts;
809 use syntax::attr::AttrMetaMethods;
811 // When the user supplies --test we should implicitly supply --cfg test
813 fn test_switch_implies_cfg_test() {
815 &match getopts(["--test".to_string()], optgroups().as_slice()) {
817 Err(f) => fail!("test_switch_implies_cfg_test: {}", f)
819 let sessopts = build_session_options(matches);
820 let sess = build_session(sessopts, None);
821 let cfg = build_configuration(&sess);
822 assert!((attr::contains_name(cfg.as_slice(), "test")));
825 // When the user supplies --test and --cfg test, don't implicitly add
826 // another --cfg test
828 fn test_switch_implies_cfg_test_unless_cfg_test() {
830 &match getopts(["--test".to_string(), "--cfg=test".to_string()],
831 optgroups().as_slice()) {
834 fail!("test_switch_implies_cfg_test_unless_cfg_test: {}", f)
837 let sessopts = build_session_options(matches);
838 let sess = build_session(sessopts, None);
839 let cfg = build_configuration(&sess);
840 let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
841 assert!(test_items.next().is_some());
842 assert!(test_items.next().is_none());