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::OsiOS => InternedString::new("ios"),
401 // ARM is bi-endian, however using NDK seems to default
402 // to little-endian unless a flag is provided.
403 let (end,arch,wordsz) = match sess.targ_cfg.arch {
404 abi::X86 => ("little", "x86", "32"),
405 abi::X86_64 => ("little", "x86_64", "64"),
406 abi::Arm => ("little", "arm", "32"),
407 abi::Mips => ("big", "mips", "32"),
408 abi::Mipsel => ("little", "mipsel", "32")
411 let fam = match sess.targ_cfg.os {
412 abi::OsWin32 => InternedString::new("windows"),
413 _ => InternedString::new("unix")
416 let mk = attr::mk_name_value_item_str;
417 return vec!(// Target bindings.
418 attr::mk_word_item(fam.clone()),
419 mk(InternedString::new("target_os"), tos),
420 mk(InternedString::new("target_family"), fam),
421 mk(InternedString::new("target_arch"), InternedString::new(arch)),
422 mk(InternedString::new("target_endian"), InternedString::new(end)),
423 mk(InternedString::new("target_word_size"),
424 InternedString::new(wordsz))
428 pub fn append_configuration(cfg: &mut ast::CrateConfig,
429 name: InternedString) {
430 if !cfg.iter().any(|mi| mi.name() == name) {
431 cfg.push(attr::mk_word_item(name))
435 pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
436 // Combine the configuration requested by the session (command line) with
437 // some default and generated configuration items
438 let default_cfg = default_configuration(sess);
439 let mut user_cfg = sess.opts.cfg.clone();
440 // If the user wants a test runner, then add the test cfg
442 append_configuration(&mut user_cfg, InternedString::new("test"))
444 // If the user requested GC, then add the GC cfg
445 append_configuration(&mut user_cfg, if sess.opts.gc {
446 InternedString::new("gc")
448 InternedString::new("nogc")
450 user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
453 pub fn get_os(triple: &str) -> Option<abi::Os> {
454 for &(name, os) in os_names.iter() {
455 if triple.contains(name) { return Some(os) }
459 static os_names : &'static [(&'static str, abi::Os)] = &[
460 ("mingw32", abi::OsWin32),
461 ("win32", abi::OsWin32),
462 ("darwin", abi::OsMacos),
463 ("android", abi::OsAndroid),
464 ("linux", abi::OsLinux),
465 ("freebsd", abi::OsFreebsd),
466 ("ios", abi::OsiOS)];
468 pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
469 for &(arch, abi) in architecture_abis.iter() {
470 if triple.contains(arch) { return Some(abi) }
474 static architecture_abis : &'static [(&'static str, abi::Architecture)] = &[
481 ("x86_64", abi::X86_64),
484 ("xscale", abi::Arm),
487 ("mipsel", abi::Mipsel),
488 ("mips", abi::Mips)];
490 pub fn build_target_config(sopts: &Options) -> Config {
491 let os = match get_os(sopts.target_triple.as_slice()) {
493 None => early_error("unknown operating system")
495 let arch = match get_arch(sopts.target_triple.as_slice()) {
498 early_error(format!("unknown architecture: {}",
499 sopts.target_triple.as_slice()).as_slice())
502 let (int_type, uint_type) = match arch {
503 abi::X86 => (ast::TyI32, ast::TyU32),
504 abi::X86_64 => (ast::TyI64, ast::TyU64),
505 abi::Arm => (ast::TyI32, ast::TyU32),
506 abi::Mips => (ast::TyI32, ast::TyU32),
507 abi::Mipsel => (ast::TyI32, ast::TyU32)
509 let target_triple = sopts.target_triple.clone();
510 let target_strs = match arch {
511 abi::X86 => x86::get_target_strs(target_triple, os),
512 abi::X86_64 => x86_64::get_target_strs(target_triple, os),
513 abi::Arm => arm::get_target_strs(target_triple, os),
514 abi::Mips => mips::get_target_strs(target_triple, os),
515 abi::Mipsel => mipsel::get_target_strs(target_triple, os)
520 target_strs: target_strs,
522 uint_type: uint_type,
526 // rustc command line options
527 pub fn optgroups() -> Vec<getopts::OptGroup> {
529 optflag("h", "help", "Display this message"),
530 optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
531 optmulti("L", "", "Add a directory to the library search path", "PATH"),
532 optmulti("", "crate-type", "Comma separated list of types of crates
533 for the compiler to emit",
534 "[bin|lib|rlib|dylib|staticlib]"),
535 optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
536 "[asm|bc|ir|obj|link]"),
537 optopt("", "crate-name", "Specify the name of the crate being built",
539 optflag("", "print-crate-name", "Output the crate name and exit"),
540 optflag("", "print-file-name", "Output the file(s) that would be written if compilation \
541 continued and exit"),
542 optflag("", "crate-file-name", "deprecated in favor of --print-file-name"),
543 optflag("g", "", "Equivalent to --debuginfo=2"),
544 optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
546 1 = line-tables only (for stacktraces and breakpoints),
547 2 = full debug info with variable and type information (same as -g)", "LEVEL"),
548 optflag("", "no-trans", "Run all passes except translation; no output"),
549 optflag("", "no-analysis",
550 "Parse and expand the source, but run no analysis and produce no output"),
551 optflag("O", "", "Equivalent to --opt-level=2"),
552 optopt("o", "", "Write output to <filename>", "FILENAME"),
553 optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
554 optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
555 optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
556 optopt("", "explain", "Provide a detailed explanation of an error message", "OPT"),
557 optflagopt("", "pretty",
558 "Pretty-print the input instead of compiling;
559 valid types are: `normal` (un-annotated source),
560 `expanded` (crates expanded),
561 `typed` (crates expanded, with type annotations),
562 `expanded,identified` (fully parenthesized, AST nodes with IDs), or
563 `flowgraph=<nodeid>` (graphviz formatted flowgraph for node)",
565 optflagopt("", "dep-info",
566 "Output dependency info to <filename> after compiling, \
567 in a format suitable for use by Makefiles", "FILENAME"),
568 optopt("", "sysroot", "Override the system root", "PATH"),
569 optflag("", "test", "Build a test harness"),
570 optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
571 to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
572 for details)", "TRIPLE"),
573 optmulti("W", "warn", "Set lint warnings", "OPT"),
574 optmulti("A", "allow", "Set lint allowed", "OPT"),
575 optmulti("D", "deny", "Set lint denied", "OPT"),
576 optmulti("F", "forbid", "Set lint forbidden", "OPT"),
577 optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
578 optmulti("Z", "", "Set internal debugging options", "FLAG"),
579 optflagopt("v", "version", "Print version info and exit", "verbose"),
580 optopt("", "color", "Configure coloring of output:
581 auto = colorize, if output goes to a tty (default);
582 always = always colorize output;
583 never = never colorize output", "auto|always|never"),
584 optmulti("", "extern", "Specify where an external rust library is located",
590 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
591 fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
592 cfgspecs.move_iter().map(|s| {
593 parse::parse_meta_from_source_str("cfgspec".to_string(),
596 &parse::new_parse_sess())
597 }).collect::<ast::CrateConfig>()
600 pub fn build_session_options(matches: &getopts::Matches) -> Options {
602 let unparsed_crate_types = matches.opt_strs("crate-type");
603 let crate_types = parse_crate_types_from_list(unparsed_crate_types)
604 .unwrap_or_else(|e| early_error(e.as_slice()));
606 let parse_only = matches.opt_present("parse-only");
607 let no_trans = matches.opt_present("no-trans");
608 let no_analysis = matches.opt_present("no-analysis");
610 let mut lint_opts = vec!();
611 let mut describe_lints = false;
613 for &level in [lint::Allow, lint::Warn, lint::Deny, lint::Forbid].iter() {
614 for lint_name in matches.opt_strs(level.as_str()).move_iter() {
615 if lint_name.as_slice() == "help" {
616 describe_lints = true;
618 lint_opts.push((lint_name.replace("-", "_").into_string(), level));
623 let mut debugging_opts = 0;
624 let debug_flags = matches.opt_strs("Z");
625 let debug_map = debugging_opts_map();
626 for debug_flag in debug_flags.iter() {
627 let mut this_bit = 0;
628 for tuple in debug_map.iter() {
629 let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
630 if *name == debug_flag.as_slice() {
636 early_error(format!("unknown debug flag: {}",
637 *debug_flag).as_slice())
639 debugging_opts |= this_bit;
642 if debugging_opts & DEBUG_LLVM != 0 {
643 unsafe { llvm::LLVMSetDebug(1); }
646 let mut output_types = Vec::new();
647 if !parse_only && !no_trans {
648 let unparsed_output_types = matches.opt_strs("emit");
649 for unparsed_output_type in unparsed_output_types.iter() {
650 for part in unparsed_output_type.as_slice().split(',') {
651 let output_type = match part.as_slice() {
652 "asm" => link::OutputTypeAssembly,
653 "ir" => link::OutputTypeLlvmAssembly,
654 "bc" => link::OutputTypeBitcode,
655 "obj" => link::OutputTypeObject,
656 "link" => link::OutputTypeExe,
658 early_error(format!("unknown emission type: `{}`",
662 output_types.push(output_type)
666 output_types.as_mut_slice().sort();
667 output_types.dedup();
668 if output_types.len() == 0 {
669 output_types.push(link::OutputTypeExe);
672 let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
673 let target = matches.opt_str("target").unwrap_or(
674 driver::host_triple().to_string());
676 if (debugging_opts & NO_OPT) != 0 {
678 } else if matches.opt_present("O") {
679 if matches.opt_present("opt-level") {
680 early_error("-O and --opt-level both provided");
683 } else if matches.opt_present("opt-level") {
684 match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
688 Some("2") => Default,
689 Some("3") => Aggressive,
691 early_error(format!("optimization level needs to be \
692 between 0-3 (instead was `{}`)",
700 let gc = debugging_opts & GC != 0;
701 let debuginfo = if matches.opt_present("g") {
702 if matches.opt_present("debuginfo") {
703 early_error("-g and --debuginfo both provided");
706 } else if matches.opt_present("debuginfo") {
707 match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
708 Some("0") => NoDebugInfo,
709 Some("1") => LimitedDebugInfo,
711 Some("2") => FullDebugInfo,
713 early_error(format!("optimization level needs to be between \
714 0-3 (instead was `{}`)",
722 let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
723 Path::new(s.as_slice())
726 let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
727 let test = matches.opt_present("test");
728 let write_dependency_info = (matches.opt_present("dep-info"),
729 matches.opt_str("dep-info")
730 .map(|p| Path::new(p)));
732 let print_metas = (matches.opt_present("print-crate-name"),
733 matches.opt_present("print-file-name") ||
734 matches.opt_present("crate-file-name"));
735 if matches.opt_present("crate-file-name") {
736 early_warn("the --crate-file-name argument has been renamed to \
739 let cg = build_codegen_options(matches);
741 let color = match matches.opt_str("color").as_ref().map(|s| s.as_slice()) {
742 Some("auto") => Auto,
743 Some("always") => Always,
744 Some("never") => Never,
749 early_error(format!("argument for --color must be auto, always \
750 or never (instead was `{}`)",
755 let mut externs = HashMap::new();
756 for arg in matches.opt_strs("extern").iter() {
757 let mut parts = arg.as_slice().splitn('=', 1);
758 let name = match parts.next() {
760 None => early_error("--extern value must not be empty"),
762 let location = match parts.next() {
764 None => early_error("--extern value must be of the format `foo=bar`"),
766 let locs = externs.find_or_insert(name.to_string(), Vec::new());
767 locs.push(location.to_string());
770 let crate_name = matches.opt_str("crate-name");
773 crate_types: crate_types,
776 debuginfo: debuginfo,
777 lint_opts: lint_opts,
778 describe_lints: describe_lints,
779 output_types: output_types,
780 addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
781 maybe_sysroot: sysroot_opt,
782 target_triple: target,
785 parse_only: parse_only,
787 no_analysis: no_analysis,
788 debugging_opts: debugging_opts,
789 write_dependency_info: write_dependency_info,
790 print_metas: print_metas,
794 crate_name: crate_name,
799 pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
801 let mut crate_types: Vec<CrateType> = Vec::new();
802 for unparsed_crate_type in list_list.iter() {
803 for part in unparsed_crate_type.as_slice().split(',') {
804 let new_part = match part {
805 "lib" => default_lib_output(),
806 "rlib" => CrateTypeRlib,
807 "staticlib" => CrateTypeStaticlib,
808 "dylib" => CrateTypeDylib,
809 "bin" => CrateTypeExecutable,
811 return Err(format!("unknown crate type: `{}`",
815 crate_types.push(new_part)
819 return Ok(crate_types);
822 impl fmt::Show for CrateType {
823 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
825 CrateTypeExecutable => "bin".fmt(f),
826 CrateTypeDylib => "dylib".fmt(f),
827 CrateTypeRlib => "rlib".fmt(f),
828 CrateTypeStaticlib => "staticlib".fmt(f)
836 use driver::config::{build_configuration, optgroups, build_session_options};
837 use driver::session::build_session;
839 use getopts::getopts;
841 use syntax::attr::AttrMetaMethods;
842 use syntax::diagnostics;
844 // When the user supplies --test we should implicitly supply --cfg test
846 fn test_switch_implies_cfg_test() {
848 &match getopts(["--test".to_string()], optgroups().as_slice()) {
850 Err(f) => fail!("test_switch_implies_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 assert!((attr::contains_name(cfg.as_slice(), "test")));
859 // When the user supplies --test and --cfg test, don't implicitly add
860 // another --cfg test
862 fn test_switch_implies_cfg_test_unless_cfg_test() {
864 &match getopts(["--test".to_string(), "--cfg=test".to_string()],
865 optgroups().as_slice()) {
868 fail!("test_switch_implies_cfg_test_unless_cfg_test: {}", f)
871 let registry = diagnostics::registry::Registry::new([]);
872 let sessopts = build_session_options(matches);
873 let sess = build_session(sessopts, None, registry);
874 let cfg = build_configuration(&sess);
875 let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
876 assert!(test_items.next().is_some());
877 assert!(test_items.next().is_none());