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