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>,
100 /// An optional name to use as the crate for std during std injection,
101 /// written `extern crate std = "name"`. Default to "std". Used by
102 /// out-of-tree drivers.
103 pub alt_std_name: Option<String>
106 /// Some reasonable defaults
107 pub fn basic_options() -> Options {
109 crate_types: Vec::new(),
112 debuginfo: NoDebugInfo,
113 lint_opts: Vec::new(),
114 describe_lints: false,
115 output_types: Vec::new(),
116 addl_lib_search_paths: RefCell::new(HashSet::new()),
118 target_triple: driver::host_triple().to_string(),
125 write_dependency_info: (false, None),
126 print_metas: (false, false),
127 cg: basic_codegen_options(),
129 externs: HashMap::new(),
135 // The type of entry function, so
136 // users can have their own entry
137 // functions that don't start a
139 #[deriving(PartialEq)]
140 pub enum EntryFnType {
146 #[deriving(PartialEq, PartialOrd, Clone, Ord, Eq, Hash)]
154 macro_rules! debugging_opts(
155 ([ $opt:ident ] $cnt:expr ) => (
156 pub static $opt: u64 = 1 << $cnt;
158 ([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
159 pub static $opt: u64 = 1 << $cnt;
160 debugging_opts!([ $($rest),* ] $cnt + 1)
188 FLOWGRAPH_PRINT_LOANS,
189 FLOWGRAPH_PRINT_MOVES,
190 FLOWGRAPH_PRINT_ASSIGNS,
196 pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
197 vec!(("verbose", "in general, enable more debug printouts", VERBOSE),
198 ("time-passes", "measure time of each rustc pass", TIME_PASSES),
199 ("count-llvm-insns", "count where LLVM \
200 instrs originate", COUNT_LLVM_INSNS),
201 ("time-llvm-passes", "measure time of each LLVM pass",
203 ("trans-stats", "gather trans statistics", TRANS_STATS),
204 ("asm-comments", "generate comments into the assembly (may change behavior)",
206 ("no-verify", "skip LLVM verification", NO_VERIFY),
207 ("borrowck-stats", "gather borrowck statistics", BORROWCK_STATS),
208 ("no-landing-pads", "omit landing pads for unwinding",
210 ("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
211 ("show-span", "show spans for compiler debugging", SHOW_SPAN),
212 ("count-type-sizes", "count the sizes of aggregate types",
214 ("meta-stats", "gather metadata statistics", META_STATS),
215 ("no-opt", "do not optimize, even if -O is passed", NO_OPT),
216 ("print-link-args", "Print the arguments passed to the linker",
218 ("gc", "Garbage collect shared data (experimental)", GC),
219 ("print-llvm-passes",
220 "Prints the llvm optimization passes being run",
222 ("lto", "Perform LLVM link-time optimizations", LTO),
223 ("ast-json", "Print the AST as JSON and halt", AST_JSON),
224 ("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
225 ("ls", "List the symbols defined by a library crate", LS),
226 ("save-analysis", "Write syntax and type analysis information \
227 in addition to normal output", SAVE_ANALYSIS),
228 ("flowgraph-print-loans", "Include loan analysis data in \
229 --pretty flowgraph output", FLOWGRAPH_PRINT_LOANS),
230 ("flowgraph-print-moves", "Include move analysis data in \
231 --pretty flowgraph output", FLOWGRAPH_PRINT_MOVES),
232 ("flowgraph-print-assigns", "Include assignment analysis data in \
233 --pretty flowgraph output", FLOWGRAPH_PRINT_ASSIGNS),
234 ("flowgraph-print-all", "Include all dataflow analysis data in \
235 --pretty flowgraph output", FLOWGRAPH_PRINT_ALL))
238 /// Declare a macro that will define all CodegenOptions fields and parsers all
239 /// at once. The goal of this macro is to define an interface that can be
240 /// programmatically used by the option parser in order to initialize the struct
241 /// without hardcoding field names all over the place.
243 /// The goal is to invoke this macro once with the correct fields, and then this
244 /// macro generates all necessary code. The main gotcha of this macro is the
245 /// cgsetters module which is a bunch of generated code to parse an option into
246 /// its respective field in the struct. There are a few hand-written parsers for
247 /// parsing specific types of values in this module.
248 macro_rules! cgoptions(
249 ($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
252 pub struct CodegenOptions { $(pub $opt: $t),* }
254 pub fn basic_codegen_options() -> CodegenOptions {
255 CodegenOptions { $($opt: $init),* }
258 pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
259 pub static CG_OPTIONS: &'static [(&'static str, CodegenSetter,
261 &[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
264 use super::CodegenOptions;
267 pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
268 $parse(&mut cg.$opt, v)
272 fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
275 None => { *slot = true; true }
279 fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool {
281 Some(s) => { *slot = Some(s.to_string()); true },
286 fn parse_string(slot: &mut String, v: Option<&str>) -> bool {
288 Some(s) => { *slot = s.to_string(); true },
293 fn parse_list(slot: &mut Vec<String>, v: Option<&str>)
298 slot.push(s.to_string());
310 ar: Option<String> = (None, parse_opt_string,
311 "tool to assemble archives with"),
312 linker: Option<String> = (None, parse_opt_string,
313 "system linker to link outputs with"),
314 link_args: Vec<String> = (Vec::new(), parse_list,
315 "extra arguments to pass to the linker (space separated)"),
316 target_cpu: String = ("generic".to_string(), parse_string,
317 "select target processor (llc -mcpu=help for details)"),
318 target_feature: String = ("".to_string(), parse_string,
319 "target specific attributes (llc -mattr=help for details)"),
320 passes: Vec<String> = (Vec::new(), parse_list,
321 "a list of extra LLVM passes to run (space separated)"),
322 llvm_args: Vec<String> = (Vec::new(), parse_list,
323 "a list of arguments to pass to llvm (space separated)"),
324 save_temps: bool = (false, parse_bool,
325 "save all temporary output files during compilation"),
326 rpath: bool = (false, parse_bool,
327 "set rpath values in libs/exes"),
328 no_prepopulate_passes: bool = (false, parse_bool,
329 "don't pre-populate the pass manager with a list of passes"),
330 no_vectorize_loops: bool = (false, parse_bool,
331 "don't run the loop vectorization optimization passes"),
332 no_vectorize_slp: bool = (false, parse_bool,
333 "don't run LLVM's SLP vectorization pass"),
334 soft_float: bool = (false, parse_bool,
335 "generate software floating point library calls"),
336 prefer_dynamic: bool = (false, parse_bool,
337 "prefer dynamic linking to static linking"),
338 no_integrated_as: bool = (false, parse_bool,
339 "use an external assembler rather than LLVM's integrated one"),
340 no_redzone: bool = (false, parse_bool,
341 "disable the use of the redzone"),
342 relocation_model: String = ("pic".to_string(), parse_string,
343 "choose the relocation model to use (llc -relocation-model for details)"),
344 code_model: String = ("default".to_string(), parse_string,
345 "choose the code model to use (llc -code-model for details)"),
346 metadata: Vec<String> = (Vec::new(), parse_list,
347 "metadata to mangle symbol names with"),
348 extra_filename: String = ("".to_string(), parse_string,
349 "extra data to put in each output filename"),
352 pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
354 let mut cg = basic_codegen_options();
355 for option in matches.opt_strs("C").move_iter() {
356 let mut iter = option.as_slice().splitn('=', 1);
357 let key = iter.next().unwrap();
358 let value = iter.next();
359 let option_to_lookup = key.replace("-", "_");
360 let mut found = false;
361 for &(candidate, setter, _) in CG_OPTIONS.iter() {
362 if option_to_lookup.as_slice() != candidate { continue }
363 if !setter(&mut cg, value) {
366 early_error(format!("codegen option `{}` takes no \
367 value", key).as_slice())
370 early_error(format!("codegen option `{0}` requires \
371 a value (-C {0}=<value>)",
380 early_error(format!("unknown codegen option: `{}`",
387 pub fn default_lib_output() -> CrateType {
391 pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
392 let tos = match sess.targ_cfg.os {
393 abi::OsWin32 => InternedString::new("win32"),
394 abi::OsMacos => InternedString::new("macos"),
395 abi::OsLinux => InternedString::new("linux"),
396 abi::OsAndroid => InternedString::new("android"),
397 abi::OsFreebsd => InternedString::new("freebsd"),
398 abi::OsDragonfly => InternedString::new("dragonfly"),
399 abi::OsiOS => InternedString::new("ios"),
402 // ARM is bi-endian, however using NDK seems to default
403 // to little-endian unless a flag is provided.
404 let (end,arch,wordsz) = match sess.targ_cfg.arch {
405 abi::X86 => ("little", "x86", "32"),
406 abi::X86_64 => ("little", "x86_64", "64"),
407 abi::Arm => ("little", "arm", "32"),
408 abi::Mips => ("big", "mips", "32"),
409 abi::Mipsel => ("little", "mipsel", "32")
412 let fam = match sess.targ_cfg.os {
413 abi::OsWin32 => InternedString::new("windows"),
414 _ => InternedString::new("unix")
417 let mk = attr::mk_name_value_item_str;
418 return vec!(// Target bindings.
419 attr::mk_word_item(fam.clone()),
420 mk(InternedString::new("target_os"), tos),
421 mk(InternedString::new("target_family"), fam),
422 mk(InternedString::new("target_arch"), InternedString::new(arch)),
423 mk(InternedString::new("target_endian"), InternedString::new(end)),
424 mk(InternedString::new("target_word_size"),
425 InternedString::new(wordsz))
429 pub fn append_configuration(cfg: &mut ast::CrateConfig,
430 name: InternedString) {
431 if !cfg.iter().any(|mi| mi.name() == name) {
432 cfg.push(attr::mk_word_item(name))
436 pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
437 // Combine the configuration requested by the session (command line) with
438 // some default and generated configuration items
439 let default_cfg = default_configuration(sess);
440 let mut user_cfg = sess.opts.cfg.clone();
441 // If the user wants a test runner, then add the test cfg
443 append_configuration(&mut user_cfg, InternedString::new("test"))
445 user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
448 pub fn get_os(triple: &str) -> Option<abi::Os> {
449 for &(name, os) in os_names.iter() {
450 if triple.contains(name) { return Some(os) }
454 static os_names : &'static [(&'static str, abi::Os)] = &[
455 ("mingw32", abi::OsWin32),
456 ("win32", abi::OsWin32),
457 ("darwin", abi::OsMacos),
458 ("android", abi::OsAndroid),
459 ("linux", abi::OsLinux),
460 ("freebsd", abi::OsFreebsd),
461 ("dragonfly", abi::OsDragonfly),
462 ("ios", abi::OsiOS)];
464 pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
465 for &(arch, abi) in architecture_abis.iter() {
466 if triple.contains(arch) { return Some(abi) }
470 static architecture_abis : &'static [(&'static str, abi::Architecture)] = &[
477 ("x86_64", abi::X86_64),
480 ("xscale", abi::Arm),
483 ("mipsel", abi::Mipsel),
484 ("mips", abi::Mips)];
486 pub fn build_target_config(sopts: &Options) -> Config {
487 let os = match get_os(sopts.target_triple.as_slice()) {
489 None => early_error("unknown operating system")
491 let arch = match get_arch(sopts.target_triple.as_slice()) {
494 early_error(format!("unknown architecture: {}",
495 sopts.target_triple.as_slice()).as_slice())
498 let (int_type, uint_type) = match arch {
499 abi::X86 => (ast::TyI32, ast::TyU32),
500 abi::X86_64 => (ast::TyI64, ast::TyU64),
501 abi::Arm => (ast::TyI32, ast::TyU32),
502 abi::Mips => (ast::TyI32, ast::TyU32),
503 abi::Mipsel => (ast::TyI32, ast::TyU32)
505 let target_triple = sopts.target_triple.clone();
506 let target_strs = match arch {
507 abi::X86 => x86::get_target_strs(target_triple, os),
508 abi::X86_64 => x86_64::get_target_strs(target_triple, os),
509 abi::Arm => arm::get_target_strs(target_triple, os),
510 abi::Mips => mips::get_target_strs(target_triple, os),
511 abi::Mipsel => mipsel::get_target_strs(target_triple, os)
516 target_strs: target_strs,
518 uint_type: uint_type,
522 // rustc command line options
523 pub fn optgroups() -> Vec<getopts::OptGroup> {
525 optflag("h", "help", "Display this message"),
526 optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
527 optmulti("L", "", "Add a directory to the library search path", "PATH"),
528 optmulti("", "crate-type", "Comma separated list of types of crates
529 for the compiler to emit",
530 "[bin|lib|rlib|dylib|staticlib]"),
531 optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
532 "[asm|bc|ir|obj|link]"),
533 optopt("", "crate-name", "Specify the name of the crate being built",
535 optflag("", "print-crate-name", "Output the crate name and exit"),
536 optflag("", "print-file-name", "Output the file(s) that would be written if compilation \
537 continued and exit"),
538 optflag("", "crate-file-name", "deprecated in favor of --print-file-name"),
539 optflag("g", "", "Equivalent to --debuginfo=2"),
540 optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
542 1 = line-tables only (for stacktraces and breakpoints),
543 2 = full debug info with variable and type information (same as -g)", "LEVEL"),
544 optflag("", "no-trans", "Run all passes except translation; no output"),
545 optflag("", "no-analysis",
546 "Parse and expand the source, but run no analysis and produce no output"),
547 optflag("O", "", "Equivalent to --opt-level=2"),
548 optopt("o", "", "Write output to <filename>", "FILENAME"),
549 optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
550 optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
551 optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
552 optopt("", "explain", "Provide a detailed explanation of an error message", "OPT"),
553 optflagopt("", "pretty",
554 "Pretty-print the input instead of compiling;
555 valid types are: `normal` (un-annotated source),
556 `expanded` (crates expanded),
557 `typed` (crates expanded, with type annotations),
558 `expanded,identified` (fully parenthesized, AST nodes with IDs), or
559 `flowgraph=<nodeid>` (graphviz formatted flowgraph for node)",
561 optflagopt("", "dep-info",
562 "Output dependency info to <filename> after compiling, \
563 in a format suitable for use by Makefiles", "FILENAME"),
564 optopt("", "sysroot", "Override the system root", "PATH"),
565 optflag("", "test", "Build a test harness"),
566 optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
567 to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
568 for details)", "TRIPLE"),
569 optmulti("W", "warn", "Set lint warnings", "OPT"),
570 optmulti("A", "allow", "Set lint allowed", "OPT"),
571 optmulti("D", "deny", "Set lint denied", "OPT"),
572 optmulti("F", "forbid", "Set lint forbidden", "OPT"),
573 optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
574 optmulti("Z", "", "Set internal debugging options", "FLAG"),
575 optflagopt("v", "version", "Print version info and exit", "verbose"),
576 optopt("", "color", "Configure coloring of output:
577 auto = colorize, if output goes to a tty (default);
578 always = always colorize output;
579 never = never colorize output", "auto|always|never"),
580 optmulti("", "extern", "Specify where an external rust library is located",
586 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
587 fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
588 cfgspecs.move_iter().map(|s| {
589 parse::parse_meta_from_source_str("cfgspec".to_string(),
592 &parse::new_parse_sess())
593 }).collect::<ast::CrateConfig>()
596 pub fn build_session_options(matches: &getopts::Matches) -> Options {
598 let unparsed_crate_types = matches.opt_strs("crate-type");
599 let crate_types = parse_crate_types_from_list(unparsed_crate_types)
600 .unwrap_or_else(|e| early_error(e.as_slice()));
602 let parse_only = matches.opt_present("parse-only");
603 let no_trans = matches.opt_present("no-trans");
604 let no_analysis = matches.opt_present("no-analysis");
606 let mut lint_opts = vec!();
607 let mut describe_lints = false;
609 for &level in [lint::Allow, lint::Warn, lint::Deny, lint::Forbid].iter() {
610 for lint_name in matches.opt_strs(level.as_str()).move_iter() {
611 if lint_name.as_slice() == "help" {
612 describe_lints = true;
614 lint_opts.push((lint_name.replace("-", "_").into_string(), level));
619 let mut debugging_opts = 0;
620 let debug_flags = matches.opt_strs("Z");
621 let debug_map = debugging_opts_map();
622 for debug_flag in debug_flags.iter() {
623 let mut this_bit = 0;
624 for tuple in debug_map.iter() {
625 let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
626 if *name == debug_flag.as_slice() {
632 early_error(format!("unknown debug flag: {}",
633 *debug_flag).as_slice())
635 debugging_opts |= this_bit;
638 if debugging_opts & DEBUG_LLVM != 0 {
639 unsafe { llvm::LLVMSetDebug(1); }
642 let mut output_types = Vec::new();
643 if !parse_only && !no_trans {
644 let unparsed_output_types = matches.opt_strs("emit");
645 for unparsed_output_type in unparsed_output_types.iter() {
646 for part in unparsed_output_type.as_slice().split(',') {
647 let output_type = match part.as_slice() {
648 "asm" => link::OutputTypeAssembly,
649 "ir" => link::OutputTypeLlvmAssembly,
650 "bc" => link::OutputTypeBitcode,
651 "obj" => link::OutputTypeObject,
652 "link" => link::OutputTypeExe,
654 early_error(format!("unknown emission type: `{}`",
658 output_types.push(output_type)
662 output_types.as_mut_slice().sort();
663 output_types.dedup();
664 if output_types.len() == 0 {
665 output_types.push(link::OutputTypeExe);
668 let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
669 let target = matches.opt_str("target").unwrap_or(
670 driver::host_triple().to_string());
672 if (debugging_opts & NO_OPT) != 0 {
674 } else if matches.opt_present("O") {
675 if matches.opt_present("opt-level") {
676 early_error("-O and --opt-level both provided");
679 } else if matches.opt_present("opt-level") {
680 match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
684 Some("2") => Default,
685 Some("3") => Aggressive,
687 early_error(format!("optimization level needs to be \
688 between 0-3 (instead was `{}`)",
696 let gc = debugging_opts & GC != 0;
697 let debuginfo = if matches.opt_present("g") {
698 if matches.opt_present("debuginfo") {
699 early_error("-g and --debuginfo both provided");
702 } else if matches.opt_present("debuginfo") {
703 match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
704 Some("0") => NoDebugInfo,
705 Some("1") => LimitedDebugInfo,
707 Some("2") => FullDebugInfo,
709 early_error(format!("optimization level needs to be between \
710 0-3 (instead was `{}`)",
718 let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
719 Path::new(s.as_slice())
722 let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
723 let test = matches.opt_present("test");
724 let write_dependency_info = (matches.opt_present("dep-info"),
725 matches.opt_str("dep-info")
726 .map(|p| Path::new(p)));
728 let print_metas = (matches.opt_present("print-crate-name"),
729 matches.opt_present("print-file-name") ||
730 matches.opt_present("crate-file-name"));
731 if matches.opt_present("crate-file-name") {
732 early_warn("the --crate-file-name argument has been renamed to \
735 let cg = build_codegen_options(matches);
737 let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
738 Some("auto") => Auto,
739 Some("always") => Always,
740 Some("never") => Never,
745 early_error(format!("argument for --color must be auto, always \
746 or never (instead was `{}`)",
751 let mut externs = HashMap::new();
752 for arg in matches.opt_strs("extern").iter() {
753 let mut parts = arg.as_slice().splitn('=', 1);
754 let name = match parts.next() {
756 None => early_error("--extern value must not be empty"),
758 let location = match parts.next() {
760 None => early_error("--extern value must be of the format `foo=bar`"),
762 let locs = externs.find_or_insert(name.to_string(), Vec::new());
763 locs.push(location.to_string());
766 let crate_name = matches.opt_str("crate-name");
769 crate_types: crate_types,
772 debuginfo: debuginfo,
773 lint_opts: lint_opts,
774 describe_lints: describe_lints,
775 output_types: output_types,
776 addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
777 maybe_sysroot: sysroot_opt,
778 target_triple: target,
781 parse_only: parse_only,
783 no_analysis: no_analysis,
784 debugging_opts: debugging_opts,
785 write_dependency_info: write_dependency_info,
786 print_metas: print_metas,
790 crate_name: crate_name,
795 pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
797 let mut crate_types: Vec<CrateType> = Vec::new();
798 for unparsed_crate_type in list_list.iter() {
799 for part in unparsed_crate_type.as_slice().split(',') {
800 let new_part = match part {
801 "lib" => default_lib_output(),
802 "rlib" => CrateTypeRlib,
803 "staticlib" => CrateTypeStaticlib,
804 "dylib" => CrateTypeDylib,
805 "bin" => CrateTypeExecutable,
807 return Err(format!("unknown crate type: `{}`",
811 crate_types.push(new_part)
815 return Ok(crate_types);
818 impl fmt::Show for CrateType {
819 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
821 CrateTypeExecutable => "bin".fmt(f),
822 CrateTypeDylib => "dylib".fmt(f),
823 CrateTypeRlib => "rlib".fmt(f),
824 CrateTypeStaticlib => "staticlib".fmt(f)
832 use driver::config::{build_configuration, optgroups, build_session_options};
833 use driver::session::build_session;
835 use getopts::getopts;
837 use syntax::attr::AttrMetaMethods;
838 use syntax::diagnostics;
840 // When the user supplies --test we should implicitly supply --cfg test
842 fn test_switch_implies_cfg_test() {
844 &match getopts(["--test".to_string()], optgroups().as_slice()) {
846 Err(f) => fail!("test_switch_implies_cfg_test: {}", f)
848 let registry = diagnostics::registry::Registry::new([]);
849 let sessopts = build_session_options(matches);
850 let sess = build_session(sessopts, None, registry);
851 let cfg = build_configuration(&sess);
852 assert!((attr::contains_name(cfg.as_slice(), "test")));
855 // When the user supplies --test and --cfg test, don't implicitly add
856 // another --cfg test
858 fn test_switch_implies_cfg_test_unless_cfg_test() {
860 &match getopts(["--test".to_string(), "--cfg=test".to_string()],
861 optgroups().as_slice()) {
864 fail!("test_switch_implies_cfg_test_unless_cfg_test: {}", f)
867 let registry = diagnostics::registry::Registry::new([]);
868 let sessopts = build_session_options(matches);
869 let sess = build_session(sessopts, None, registry);
870 let cfg = build_configuration(&sess);
871 let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
872 assert!(test_items.next().is_some());
873 assert!(test_items.next().is_none());