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 pub use self::EntryFnType
::*;
15 pub use self::CrateType
::*;
16 pub use self::Passes
::*;
17 pub use self::DebugInfoLevel
::*;
19 use session
::{early_error, early_warn, Session}
;
20 use session
::search_paths
::SearchPaths
;
22 use rustc_back
::target
::Target
;
26 use syntax
::ast
::{self, IntTy, UintTy}
;
28 use syntax
::attr
::AttrMetaMethods
;
29 use syntax
::errors
::{ColorConfig, Handler}
;
31 use syntax
::parse
::lexer
::Reader
;
32 use syntax
::parse
::token
::InternedString
;
33 use syntax
::feature_gate
::UnstableFeatures
;
36 use std
::collections
::HashMap
;
39 use std
::path
::PathBuf
;
44 pub uint_type
: UintTy
,
47 #[derive(Clone, Copy, PartialEq)]
55 #[derive(Clone, Copy, PartialEq)]
56 pub enum DebugInfoLevel
{
62 #[derive(Clone, Copy, PartialEq, Eq, Hash)]
72 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
73 pub enum ErrorOutputType
{
74 HumanReadable(ColorConfig
),
78 impl Default
for ErrorOutputType
{
79 fn default() -> ErrorOutputType
{
80 ErrorOutputType
::HumanReadable(ColorConfig
::Auto
)
85 fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool
{
88 OutputType
::DepInfo
=> true,
90 OutputType
::Assembly
|
91 OutputType
::LlvmAssembly
|
92 OutputType
::Object
=> false,
96 fn shorthand(&self) -> &'
static str {
98 OutputType
::Bitcode
=> "llvm-bc",
99 OutputType
::Assembly
=> "asm",
100 OutputType
::LlvmAssembly
=> "llvm-ir",
101 OutputType
::Object
=> "obj",
102 OutputType
::Exe
=> "link",
103 OutputType
::DepInfo
=> "dep-info",
110 // The crate config requested for the session, which may be combined
111 // with additional crate configurations during the compile process
112 pub crate_types
: Vec
<CrateType
>,
115 pub optimize
: OptLevel
,
116 pub debug_assertions
: bool
,
117 pub debuginfo
: DebugInfoLevel
,
118 pub lint_opts
: Vec
<(String
, lint
::Level
)>,
119 pub lint_cap
: Option
<lint
::Level
>,
120 pub describe_lints
: bool
,
121 pub output_types
: HashMap
<OutputType
, Option
<PathBuf
>>,
122 // This was mutable for rustpkg, which updates search paths based on the
123 // parsed code. It remains mutable in case its replacements wants to use
125 pub search_paths
: SearchPaths
,
126 pub libs
: Vec
<(String
, cstore
::NativeLibraryKind
)>,
127 pub maybe_sysroot
: Option
<PathBuf
>,
128 pub target_triple
: String
,
129 // User-specified cfg meta items. The compiler itself will add additional
130 // items to the crate config, and during parsing the entire crate config
131 // will be added to the crate AST node. This should not be used for
132 // anything except building the full crate config prior to parsing.
133 pub cfg
: ast
::CrateConfig
,
135 pub parse_only
: bool
,
137 pub error_format
: ErrorOutputType
,
138 pub treat_err_as_bug
: bool
,
139 pub continue_parse_after_error
: bool
,
140 pub mir_opt_level
: usize,
142 /// if Some, enable incremental compilation, using the given
143 /// directory to store intermediate results
144 pub incremental
: Option
<PathBuf
>,
146 pub no_analysis
: bool
,
147 pub debugging_opts
: DebuggingOptions
,
148 pub prints
: Vec
<PrintRequest
>,
149 pub cg
: CodegenOptions
,
150 pub externs
: HashMap
<String
, Vec
<String
>>,
151 pub crate_name
: Option
<String
>,
152 /// An optional name to use as the crate for std during std injection,
153 /// written `extern crate std = "name"`. Default to "std". Used by
154 /// out-of-tree drivers.
155 pub alt_std_name
: Option
<String
>,
156 /// Indicates how the compiler should treat unstable features
157 pub unstable_features
: UnstableFeatures
160 #[derive(Clone, PartialEq, Eq)]
161 pub enum PrintRequest
{
170 /// Load source from file
173 /// String that is shown in place of a filename
175 /// Anonymous source string
181 pub fn filestem(&self) -> String
{
183 Input
::File(ref ifile
) => ifile
.file_stem().unwrap()
184 .to_str().unwrap().to_string(),
185 Input
::Str { .. }
=> "rust_out".to_string(),
191 pub struct OutputFilenames
{
192 pub out_directory
: PathBuf
,
193 pub out_filestem
: String
,
194 pub single_output_file
: Option
<PathBuf
>,
196 pub outputs
: HashMap
<OutputType
, Option
<PathBuf
>>,
199 impl OutputFilenames
{
200 pub fn path(&self, flavor
: OutputType
) -> PathBuf
{
201 self.outputs
.get(&flavor
).and_then(|p
| p
.to_owned())
202 .or_else(|| self.single_output_file
.clone())
203 .unwrap_or_else(|| self.temp_path(flavor
))
206 pub fn temp_path(&self, flavor
: OutputType
) -> PathBuf
{
207 let base
= self.out_directory
.join(&self.filestem());
209 OutputType
::Bitcode
=> base
.with_extension("bc"),
210 OutputType
::Assembly
=> base
.with_extension("s"),
211 OutputType
::LlvmAssembly
=> base
.with_extension("ll"),
212 OutputType
::Object
=> base
.with_extension("o"),
213 OutputType
::DepInfo
=> base
.with_extension("d"),
214 OutputType
::Exe
=> base
,
218 pub fn with_extension(&self, extension
: &str) -> PathBuf
{
219 self.out_directory
.join(&self.filestem()).with_extension(extension
)
222 pub fn filestem(&self) -> String
{
223 format
!("{}{}", self.out_filestem
, self.extra
)
227 pub fn host_triple() -> &'
static str {
228 // Get the host triple out of the build environment. This ensures that our
229 // idea of the host triple is the same as for the set of libraries we've
230 // actually built. We can't just take LLVM's host triple because they
231 // normalize all ix86 architectures to i386.
233 // Instead of grabbing the host triple (for the current host), we grab (at
234 // compile time) the target triple that this rustc is built with and
235 // calling that (at runtime) the host triple.
236 (option_env
!("CFG_COMPILER_HOST_TRIPLE")).
237 expect("CFG_COMPILER_HOST_TRIPLE")
240 /// Some reasonable defaults
241 pub fn basic_options() -> Options
{
243 crate_types
: Vec
::new(),
245 optimize
: OptLevel
::No
,
246 debuginfo
: NoDebugInfo
,
247 lint_opts
: Vec
::new(),
249 describe_lints
: false,
250 output_types
: HashMap
::new(),
251 search_paths
: SearchPaths
::new(),
253 target_triple
: host_triple().to_string(),
258 treat_err_as_bug
: false,
259 continue_parse_after_error
: false,
263 debugging_opts
: basic_debugging_options(),
265 cg
: basic_codegen_options(),
266 error_format
: ErrorOutputType
::default(),
267 externs
: HashMap
::new(),
271 unstable_features
: UnstableFeatures
::Disallow
,
272 debug_assertions
: true,
277 /// True if there is a reason to build the dep graph.
278 pub fn build_dep_graph(&self) -> bool
{
279 self.incremental
.is_some() ||
280 self.debugging_opts
.dump_dep_graph
||
281 self.debugging_opts
.query_dep_graph
285 // The type of entry function, so
286 // users can have their own entry
287 // functions that don't start a
289 #[derive(Copy, Clone, PartialEq)]
290 pub enum EntryFnType
{
296 #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
306 SomePasses(Vec
<String
>),
311 pub fn is_empty(&self) -> bool
{
313 SomePasses(ref v
) => v
.is_empty(),
319 /// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all
320 /// at once. The goal of this macro is to define an interface that can be
321 /// programmatically used by the option parser in order to initialize the struct
322 /// without hardcoding field names all over the place.
324 /// The goal is to invoke this macro once with the correct fields, and then this
325 /// macro generates all necessary code. The main gotcha of this macro is the
326 /// cgsetters module which is a bunch of generated code to parse an option into
327 /// its respective field in the struct. There are a few hand-written parsers for
328 /// parsing specific types of values in this module.
329 macro_rules
! options
{
330 ($struct_name
:ident
, $setter_name
:ident
, $defaultfn
:ident
,
331 $buildfn
:ident
, $prefix
:expr
, $outputname
:expr
,
332 $stat
:ident
, $mod_desc
:ident
, $mod_set
:ident
,
333 $
($opt
:ident
: $t
:ty
= ($init
:expr
, $parse
:ident
, $desc
:expr
)),* ,) =>
336 pub struct $struct_name { $(pub $opt: $t),* }
338 pub fn $
defaultfn() -> $struct_name
{
339 $struct_name { $($opt: $init),* }
342 pub fn $
buildfn(matches
: &getopts
::Matches
, error_format
: ErrorOutputType
) -> $struct_name
344 let mut op
= $
defaultfn();
345 for option
in matches
.opt_strs($prefix
) {
346 let mut iter
= option
.splitn(2, '
='
);
347 let key
= iter
.next().unwrap();
348 let value
= iter
.next();
349 let option_to_lookup
= key
.replace("-", "_");
350 let mut found
= false;
351 for &(candidate
, setter
, opt_type_desc
, _
) in $stat
{
352 if option_to_lookup
!= candidate { continue }
353 if !setter(&mut op
, value
) {
354 match (value
, opt_type_desc
) {
355 (Some(..), None
) => {
356 early_error(error_format
, &format
!("{} option `{}` takes no \
357 value", $outputname
, key
))
359 (None
, Some(type_desc
)) => {
360 early_error(error_format
, &format
!("{0} option `{1}` requires \
361 {2} ({3} {1}=<value>)",
365 (Some(value
), Some(type_desc
)) => {
366 early_error(error_format
, &format
!("incorrect value `{}` for {} \
367 option `{}` - {} was expected",
371 (None
, None
) => bug
!()
378 early_error(error_format
, &format
!("unknown {} option: `{}`",
385 pub type $setter_name
= fn(&mut $struct_name
, v
: Option
<&str>) -> bool
;
386 pub const $stat
: &'
static [(&'
static str, $setter_name
,
387 Option
<&'
static str>, &'
static str)] =
388 &[ $
( (stringify
!($opt
), $mod_set
::$opt
, $mod_desc
::$parse
, $desc
) ),* ];
390 #[allow(non_upper_case_globals, dead_code)]
392 pub const parse_bool
: Option
<&'
static str> = None
;
393 pub const parse_opt_bool
: Option
<&'
static str> =
394 Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`");
395 pub const parse_string
: Option
<&'
static str> = Some("a string");
396 pub const parse_opt_string
: Option
<&'
static str> = Some("a string");
397 pub const parse_list
: Option
<&'
static str> = Some("a space-separated list of strings");
398 pub const parse_opt_list
: Option
<&'
static str> = Some("a space-separated list of strings");
399 pub const parse_uint
: Option
<&'
static str> = Some("a number");
400 pub const parse_passes
: Option
<&'
static str> =
401 Some("a space-separated list of passes, or `all`");
402 pub const parse_opt_uint
: Option
<&'
static str> =
408 use super::{$struct_name, Passes, SomePasses, AllPasses}
;
411 pub fn $
opt(cg
: &mut $struct_name
, v
: Option
<&str>) -> bool
{
412 $
parse(&mut cg
.$opt
, v
)
416 fn parse_bool(slot
: &mut bool
, v
: Option
<&str>) -> bool
{
419 None
=> { *slot = true; true }
423 fn parse_opt_bool(slot
: &mut Option
<bool
>, v
: Option
<&str>) -> bool
{
427 "n" | "no" | "off" => {
430 "y" | "yes" | "on" => {
433 _
=> { return false; }
438 None
=> { *slot = Some(true); true }
442 fn parse_opt_string(slot
: &mut Option
<String
>, v
: Option
<&str>) -> bool
{
444 Some(s
) => { *slot = Some(s.to_string()); true }
,
449 fn parse_string(slot
: &mut String
, v
: Option
<&str>) -> bool
{
451 Some(s
) => { *slot = s.to_string(); true }
,
456 fn parse_list(slot
: &mut Vec
<String
>, v
: Option
<&str>)
460 for s
in s
.split_whitespace() {
461 slot
.push(s
.to_string());
469 fn parse_opt_list(slot
: &mut Option
<Vec
<String
>>, v
: Option
<&str>)
473 let v
= s
.split_whitespace().map(|s
| s
.to_string()).collect();
481 fn parse_uint(slot
: &mut usize, v
: Option
<&str>) -> bool
{
482 match v
.and_then(|s
| s
.parse().ok()) {
483 Some(i
) => { *slot = i; true }
,
488 fn parse_opt_uint(slot
: &mut Option
<usize>, v
: Option
<&str>) -> bool
{
490 Some(s
) => { *slot = s.parse().ok(); slot.is_some() }
491 None
=> { *slot = None; true }
495 fn parse_passes(slot
: &mut Passes
, v
: Option
<&str>) -> bool
{
502 let mut passes
= vec
!();
503 if parse_list(&mut passes
, v
) {
504 *slot
= SomePasses(passes
);
515 options
! {CodegenOptions
, CodegenSetter
, basic_codegen_options
,
516 build_codegen_options
, "C", "codegen",
517 CG_OPTIONS
, cg_type_desc
, cgsetters
,
518 ar
: Option
<String
> = (None
, parse_opt_string
,
519 "tool to assemble archives with"),
520 linker
: Option
<String
> = (None
, parse_opt_string
,
521 "system linker to link outputs with"),
522 link_args
: Option
<Vec
<String
>> = (None
, parse_opt_list
,
523 "extra arguments to pass to the linker (space separated)"),
524 link_dead_code
: bool
= (false, parse_bool
,
525 "don't let linker strip dead code (turning it on can be used for code coverage)"),
526 lto
: bool
= (false, parse_bool
,
527 "perform LLVM link-time optimizations"),
528 target_cpu
: Option
<String
> = (None
, parse_opt_string
,
529 "select target processor (llc -mcpu=help for details)"),
530 target_feature
: String
= ("".to_string(), parse_string
,
531 "target specific attributes (llc -mattr=help for details)"),
532 passes
: Vec
<String
> = (Vec
::new(), parse_list
,
533 "a list of extra LLVM passes to run (space separated)"),
534 llvm_args
: Vec
<String
> = (Vec
::new(), parse_list
,
535 "a list of arguments to pass to llvm (space separated)"),
536 save_temps
: bool
= (false, parse_bool
,
537 "save all temporary output files during compilation"),
538 rpath
: bool
= (false, parse_bool
,
539 "set rpath values in libs/exes"),
540 no_prepopulate_passes
: bool
= (false, parse_bool
,
541 "don't pre-populate the pass manager with a list of passes"),
542 no_vectorize_loops
: bool
= (false, parse_bool
,
543 "don't run the loop vectorization optimization passes"),
544 no_vectorize_slp
: bool
= (false, parse_bool
,
545 "don't run LLVM's SLP vectorization pass"),
546 soft_float
: bool
= (false, parse_bool
,
547 "generate software floating point library calls"),
548 prefer_dynamic
: bool
= (false, parse_bool
,
549 "prefer dynamic linking to static linking"),
550 no_integrated_as
: bool
= (false, parse_bool
,
551 "use an external assembler rather than LLVM's integrated one"),
552 no_redzone
: Option
<bool
> = (None
, parse_opt_bool
,
553 "disable the use of the redzone"),
554 relocation_model
: Option
<String
> = (None
, parse_opt_string
,
555 "choose the relocation model to use (llc -relocation-model for details)"),
556 code_model
: Option
<String
> = (None
, parse_opt_string
,
557 "choose the code model to use (llc -code-model for details)"),
558 metadata
: Vec
<String
> = (Vec
::new(), parse_list
,
559 "metadata to mangle symbol names with"),
560 extra_filename
: String
= ("".to_string(), parse_string
,
561 "extra data to put in each output filename"),
562 codegen_units
: usize = (1, parse_uint
,
563 "divide crate into N units to optimize in parallel"),
564 remark
: Passes
= (SomePasses(Vec
::new()), parse_passes
,
565 "print remarks for these optimization passes (space separated, or \"all\")"),
566 no_stack_check
: bool
= (false, parse_bool
,
567 "disable checks for stack exhaustion (a memory-safety hazard!)"),
568 debuginfo
: Option
<usize> = (None
, parse_opt_uint
,
569 "debug info emission level, 0 = no debug info, 1 = line tables only, \
570 2 = full debug info with variable and type information"),
571 opt_level
: Option
<usize> = (None
, parse_opt_uint
,
572 "optimize with possible levels 0-3"),
573 debug_assertions
: Option
<bool
> = (None
, parse_opt_bool
,
574 "explicitly enable the cfg(debug_assertions) directive"),
575 inline_threshold
: Option
<usize> = (None
, parse_opt_uint
,
576 "set the inlining threshold for"),
580 options
! {DebuggingOptions
, DebuggingSetter
, basic_debugging_options
,
581 build_debugging_options
, "Z", "debugging",
582 DB_OPTIONS
, db_type_desc
, dbsetters
,
583 verbose
: bool
= (false, parse_bool
,
584 "in general, enable more debug printouts"),
585 time_passes
: bool
= (false, parse_bool
,
586 "measure time of each rustc pass"),
587 count_llvm_insns
: bool
= (false, parse_bool
,
588 "count where LLVM instrs originate"),
589 time_llvm_passes
: bool
= (false, parse_bool
,
590 "measure time of each LLVM pass"),
591 input_stats
: bool
= (false, parse_bool
,
592 "gather statistics about the input"),
593 trans_stats
: bool
= (false, parse_bool
,
594 "gather trans statistics"),
595 asm_comments
: bool
= (false, parse_bool
,
596 "generate comments into the assembly (may change behavior)"),
597 no_verify
: bool
= (false, parse_bool
,
598 "skip LLVM verification"),
599 borrowck_stats
: bool
= (false, parse_bool
,
600 "gather borrowck statistics"),
601 no_landing_pads
: bool
= (false, parse_bool
,
602 "omit landing pads for unwinding"),
603 debug_llvm
: bool
= (false, parse_bool
,
604 "enable debug output from LLVM"),
605 count_type_sizes
: bool
= (false, parse_bool
,
606 "count the sizes of aggregate types"),
607 meta_stats
: bool
= (false, parse_bool
,
608 "gather metadata statistics"),
609 print_link_args
: bool
= (false, parse_bool
,
610 "print the arguments passed to the linker"),
611 gc
: bool
= (false, parse_bool
,
612 "garbage collect shared data (experimental)"),
613 print_llvm_passes
: bool
= (false, parse_bool
,
614 "prints the llvm optimization passes being run"),
615 ast_json
: bool
= (false, parse_bool
,
616 "print the AST as JSON and halt"),
617 ast_json_noexpand
: bool
= (false, parse_bool
,
618 "print the pre-expansion AST as JSON and halt"),
619 ls
: bool
= (false, parse_bool
,
620 "list the symbols defined by a library crate"),
621 save_analysis
: bool
= (false, parse_bool
,
622 "write syntax and type analysis information in addition to normal output"),
623 print_move_fragments
: bool
= (false, parse_bool
,
624 "print out move-fragment data for every fn"),
625 flowgraph_print_loans
: bool
= (false, parse_bool
,
626 "include loan analysis data in --unpretty flowgraph output"),
627 flowgraph_print_moves
: bool
= (false, parse_bool
,
628 "include move analysis data in --unpretty flowgraph output"),
629 flowgraph_print_assigns
: bool
= (false, parse_bool
,
630 "include assignment analysis data in --unpretty flowgraph output"),
631 flowgraph_print_all
: bool
= (false, parse_bool
,
632 "include all dataflow analysis data in --unpretty flowgraph output"),
633 print_region_graph
: bool
= (false, parse_bool
,
634 "prints region inference graph. \
635 Use with RUST_REGION_GRAPH=help for more info"),
636 parse_only
: bool
= (false, parse_bool
,
637 "parse only; do not compile, assemble, or link"),
638 no_trans
: bool
= (false, parse_bool
,
639 "run all passes except translation; no output"),
640 treat_err_as_bug
: bool
= (false, parse_bool
,
641 "treat all errors that occur as bugs"),
642 continue_parse_after_error
: bool
= (false, parse_bool
,
643 "attempt to recover from parse errors (experimental)"),
644 incremental
: Option
<String
> = (None
, parse_opt_string
,
645 "enable incremental compilation (experimental)"),
646 dump_dep_graph
: bool
= (false, parse_bool
,
647 "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
648 query_dep_graph
: bool
= (false, parse_bool
,
649 "enable queries of the dependency graph for regression testing"),
650 no_analysis
: bool
= (false, parse_bool
,
651 "parse and expand the source, but run no analysis"),
652 extra_plugins
: Vec
<String
> = (Vec
::new(), parse_list
,
653 "load extra plugins"),
654 unstable_options
: bool
= (false, parse_bool
,
655 "adds unstable command line options to rustc interface"),
656 print_enum_sizes
: bool
= (false, parse_bool
,
657 "print the size of enums and their variants"),
658 force_overflow_checks
: Option
<bool
> = (None
, parse_opt_bool
,
659 "force overflow checks on or off"),
660 force_dropflag_checks
: Option
<bool
> = (None
, parse_opt_bool
,
661 "force drop flag checks on or off"),
662 trace_macros
: bool
= (false, parse_bool
,
663 "for every macro invocation, print its name and arguments"),
664 enable_nonzeroing_move_hints
: bool
= (false, parse_bool
,
665 "force nonzeroing move optimization on"),
666 keep_mtwt_tables
: bool
= (false, parse_bool
,
667 "don't clear the resolution tables after analysis"),
668 keep_ast
: bool
= (false, parse_bool
,
669 "keep the AST after lowering it to HIR"),
670 show_span
: Option
<String
> = (None
, parse_opt_string
,
671 "show spans for compiler debugging (expr|pat|ty)"),
672 print_trans_items
: Option
<String
> = (None
, parse_opt_string
,
673 "print the result of the translation item collection pass"),
674 mir_opt_level
: Option
<usize> = (None
, parse_opt_uint
,
675 "set the MIR optimization level (0-3)"),
676 dump_mir
: Option
<String
> = (None
, parse_opt_string
,
677 "dump MIR state at various points in translation"),
678 orbit
: bool
= (false, parse_bool
,
679 "get MIR where it belongs - everywhere; most importantly, in orbit"),
682 pub fn default_lib_output() -> CrateType
{
686 pub fn default_configuration(sess
: &Session
) -> ast
::CrateConfig
{
687 use syntax
::parse
::token
::intern_and_get_ident
as intern
;
689 let end
= &sess
.target
.target
.target_endian
;
690 let arch
= &sess
.target
.target
.arch
;
691 let wordsz
= &sess
.target
.target
.target_pointer_width
;
692 let os
= &sess
.target
.target
.target_os
;
693 let env
= &sess
.target
.target
.target_env
;
694 let vendor
= &sess
.target
.target
.target_vendor
;
696 let fam
= if let Some(ref fam
) = sess
.target
.target
.options
.target_family
{
698 } else if sess
.target
.target
.options
.is_like_windows
{
699 InternedString
::new("windows")
701 InternedString
::new("unix")
704 let mk
= attr
::mk_name_value_item_str
;
705 let mut ret
= vec
![ // Target bindings.
706 mk(InternedString
::new("target_os"), intern(os
)),
707 mk(InternedString
::new("target_family"), fam
.clone()),
708 mk(InternedString
::new("target_arch"), intern(arch
)),
709 mk(InternedString
::new("target_endian"), intern(end
)),
710 mk(InternedString
::new("target_pointer_width"), intern(wordsz
)),
711 mk(InternedString
::new("target_env"), intern(env
)),
712 mk(InternedString
::new("target_vendor"), intern(vendor
)),
715 "windows" | "unix" => ret
.push(attr
::mk_word_item(fam
)),
718 if sess
.target
.target
.options
.has_elf_tls
{
719 ret
.push(attr
::mk_word_item(InternedString
::new("target_thread_local")));
721 if sess
.opts
.debug_assertions
{
722 ret
.push(attr
::mk_word_item(InternedString
::new("debug_assertions")));
727 pub fn append_configuration(cfg
: &mut ast
::CrateConfig
,
728 name
: InternedString
) {
729 if !cfg
.iter().any(|mi
| mi
.name() == name
) {
730 cfg
.push(attr
::mk_word_item(name
))
734 pub fn build_configuration(sess
: &Session
) -> ast
::CrateConfig
{
735 // Combine the configuration requested by the session (command line) with
736 // some default and generated configuration items
737 let default_cfg
= default_configuration(sess
);
738 let mut user_cfg
= sess
.opts
.cfg
.clone();
739 // If the user wants a test runner, then add the test cfg
741 append_configuration(&mut user_cfg
, InternedString
::new("test"))
743 let mut v
= user_cfg
.into_iter().collect
::<Vec
<_
>>();
744 v
.extend_from_slice(&default_cfg
[..]);
748 pub fn build_target_config(opts
: &Options
, sp
: &Handler
) -> Config
{
749 let target
= match Target
::search(&opts
.target_triple
) {
752 panic
!(sp
.fatal(&format
!("Error loading target specification: {}", e
)));
756 let (int_type
, uint_type
) = match &target
.target_pointer_width
[..] {
757 "32" => (ast
::IntTy
::I32
, ast
::UintTy
::U32
),
758 "64" => (ast
::IntTy
::I64
, ast
::UintTy
::U64
),
759 w
=> panic
!(sp
.fatal(&format
!("target specification was invalid: \
760 unrecognized target-pointer-width {}", w
))),
766 uint_type
: uint_type
,
770 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
771 pub enum OptionStability
{
774 // FIXME: historically there were some options which were either `-Z` or
775 // required the `-Z unstable-options` flag, which were all intended
776 // to be unstable. Unfortunately we didn't actually gate usage of
777 // these options on the stable compiler, so we still allow them there
778 // today. There are some warnings printed out about this in the
780 UnstableButNotReally
,
785 #[derive(Clone, PartialEq, Eq)]
786 pub struct RustcOptGroup
{
787 pub opt_group
: getopts
::OptGroup
,
788 pub stability
: OptionStability
,
792 pub fn is_stable(&self) -> bool
{
793 self.stability
== OptionStability
::Stable
796 pub fn stable(g
: getopts
::OptGroup
) -> RustcOptGroup
{
797 RustcOptGroup { opt_group: g, stability: OptionStability::Stable }
800 #[allow(dead_code)] // currently we have no "truly unstable" options
801 pub fn unstable(g
: getopts
::OptGroup
) -> RustcOptGroup
{
802 RustcOptGroup { opt_group: g, stability: OptionStability::Unstable }
805 fn unstable_bnr(g
: getopts
::OptGroup
) -> RustcOptGroup
{
808 stability
: OptionStability
::UnstableButNotReally
,
813 // The `opt` local module holds wrappers around the `getopts` API that
814 // adds extra rustc-specific metadata to each option; such metadata
815 // is exposed by . The public
816 // functions below ending with `_u` are the functions that return
817 // *unstable* options, i.e. options that are only enabled when the
818 // user also passes the `-Z unstable-options` debugging flag.
820 // The `fn opt_u` etc below are written so that we can use them
821 // in the future; do not warn about them not being used right now.
825 use super::RustcOptGroup
;
827 pub type R
= RustcOptGroup
;
828 pub type S
<'a
> = &'a
str;
830 fn stable(g
: getopts
::OptGroup
) -> R { RustcOptGroup::stable(g) }
831 fn unstable(g
: getopts
::OptGroup
) -> R { RustcOptGroup::unstable(g) }
832 fn unstable_bnr(g
: getopts
::OptGroup
) -> R { RustcOptGroup::unstable_bnr(g) }
834 pub fn opt_s(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
835 stable(getopts
::optopt(a
, b
, c
, d
))
837 pub fn multi_s(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
838 stable(getopts
::optmulti(a
, b
, c
, d
))
840 pub fn flag_s(a
: S
, b
: S
, c
: S
) -> R
{
841 stable(getopts
::optflag(a
, b
, c
))
843 pub fn flagopt_s(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
844 stable(getopts
::optflagopt(a
, b
, c
, d
))
846 pub fn flagmulti_s(a
: S
, b
: S
, c
: S
) -> R
{
847 stable(getopts
::optflagmulti(a
, b
, c
))
850 pub fn opt(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
851 unstable(getopts
::optopt(a
, b
, c
, d
))
853 pub fn multi(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
854 unstable(getopts
::optmulti(a
, b
, c
, d
))
856 pub fn flag(a
: S
, b
: S
, c
: S
) -> R
{
857 unstable(getopts
::optflag(a
, b
, c
))
859 pub fn flagopt(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
860 unstable(getopts
::optflagopt(a
, b
, c
, d
))
862 pub fn flagmulti(a
: S
, b
: S
, c
: S
) -> R
{
863 unstable(getopts
::optflagmulti(a
, b
, c
))
866 // Do not use these functions for any new options added to the compiler, all
867 // new options should use the `*_u` variants above to be truly unstable.
868 pub fn opt_ubnr(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
869 unstable_bnr(getopts
::optopt(a
, b
, c
, d
))
871 pub fn multi_ubnr(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
872 unstable_bnr(getopts
::optmulti(a
, b
, c
, d
))
874 pub fn flag_ubnr(a
: S
, b
: S
, c
: S
) -> R
{
875 unstable_bnr(getopts
::optflag(a
, b
, c
))
877 pub fn flagopt_ubnr(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
878 unstable_bnr(getopts
::optflagopt(a
, b
, c
, d
))
880 pub fn flagmulti_ubnr(a
: S
, b
: S
, c
: S
) -> R
{
881 unstable_bnr(getopts
::optflagmulti(a
, b
, c
))
885 /// Returns the "short" subset of the rustc command line options,
886 /// including metadata for each option, such as whether the option is
887 /// part of the stable long-term interface for rustc.
888 pub fn rustc_short_optgroups() -> Vec
<RustcOptGroup
> {
890 opt
::flag_s("h", "help", "Display this message"),
891 opt
::multi_s("", "cfg", "Configure the compilation environment", "SPEC"),
892 opt
::multi_s("L", "", "Add a directory to the library search path",
894 opt
::multi_s("l", "", "Link the generated crate(s) to the specified native
895 library NAME. The optional KIND can be one of,
896 static, dylib, or framework. If omitted, dylib is
897 assumed.", "[KIND=]NAME"),
898 opt
::multi_s("", "crate-type", "Comma separated list of types of crates
899 for the compiler to emit",
900 "[bin|lib|rlib|dylib|staticlib]"),
901 opt
::opt_s("", "crate-name", "Specify the name of the crate being built",
903 opt
::multi_s("", "emit", "Comma separated list of types of output for \
904 the compiler to emit",
905 "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"),
906 opt
::multi_s("", "print", "Comma separated list of compiler information to \
908 "[crate-name|file-names|sysroot|cfg|target-list]"),
909 opt
::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"),
910 opt
::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
911 opt
::opt_s("o", "", "Write output to <filename>", "FILENAME"),
912 opt
::opt_s("", "out-dir", "Write output to compiler-chosen filename \
914 opt
::opt_s("", "explain", "Provide a detailed explanation of an error \
916 opt
::flag_s("", "test", "Build a test harness"),
917 opt
::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"),
918 opt
::multi_s("W", "warn", "Set lint warnings", "OPT"),
919 opt
::multi_s("A", "allow", "Set lint allowed", "OPT"),
920 opt
::multi_s("D", "deny", "Set lint denied", "OPT"),
921 opt
::multi_s("F", "forbid", "Set lint forbidden", "OPT"),
922 opt
::multi_s("", "cap-lints", "Set the most restrictive lint level. \
923 More restrictive lints are capped at this \
925 opt
::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
926 opt
::flag_s("V", "version", "Print version info and exit"),
927 opt
::flag_s("v", "verbose", "Use verbose output"),
931 /// Returns all rustc command line options, including metadata for
932 /// each option, such as whether the option is part of the stable
933 /// long-term interface for rustc.
934 pub fn rustc_optgroups() -> Vec
<RustcOptGroup
> {
935 let mut opts
= rustc_short_optgroups();
936 opts
.extend_from_slice(&[
937 opt
::multi_s("", "extern", "Specify where an external rust library is located",
939 opt
::opt_s("", "sysroot", "Override the system root", "PATH"),
940 opt
::multi_ubnr("Z", "", "Set internal debugging options", "FLAG"),
941 opt
::opt_ubnr("", "error-format",
942 "How errors and other messages are produced",
944 opt
::opt_s("", "color", "Configure coloring of output:
945 auto = colorize, if output goes to a tty (default);
946 always = always colorize output;
947 never = never colorize output", "auto|always|never"),
949 opt
::flagopt_ubnr("", "pretty",
950 "Pretty-print the input instead of compiling;
951 valid types are: `normal` (un-annotated source),
952 `expanded` (crates expanded), or
953 `expanded,identified` (fully parenthesized, AST nodes with IDs).",
955 opt
::flagopt_ubnr("", "unpretty",
956 "Present the input source, unstable (and less-pretty) variants;
957 valid types are any of the types for `--pretty`, as well as:
958 `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
959 `everybody_loops` (all function bodies replaced with `loop {}`),
960 `hir` (the HIR), `hir,identified`, or
961 `hir,typed` (HIR with types for each node).",
964 // new options here should **not** use the `_ubnr` functions, all new
965 // unstable options should use the short variants to indicate that they
966 // are truly unstable. All `_ubnr` flags are just that way because they
967 // were so historically.
969 // You may also wish to keep this comment at the bottom of this list to
970 // ensure that others see it.
975 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
976 pub fn parse_cfgspecs(cfgspecs
: Vec
<String
> ) -> ast
::CrateConfig
{
977 cfgspecs
.into_iter().map(|s
| {
978 let sess
= parse
::ParseSess
::new();
979 let mut parser
= parse
::new_parser_from_source_str(&sess
,
981 "cfgspec".to_string(),
983 let meta_item
= panictry
!(parser
.parse_meta_item());
985 if !parser
.reader
.is_eof() {
986 early_error(ErrorOutputType
::default(), &format
!("invalid --cfg argument: {}",
991 }).collect
::<ast
::CrateConfig
>()
994 pub fn build_session_options(matches
: &getopts
::Matches
) -> Options
{
995 let color
= match matches
.opt_str("color").as_ref().map(|s
| &s
[..]) {
996 Some("auto") => ColorConfig
::Auto
,
997 Some("always") => ColorConfig
::Always
,
998 Some("never") => ColorConfig
::Never
,
1000 None
=> ColorConfig
::Auto
,
1003 early_error(ErrorOutputType
::default(), &format
!("argument for --color must be auto, \
1004 always or never (instead was `{}`)",
1009 // We need the opts_present check because the driver will send us Matches
1010 // with only stable options if no unstable options are used. Since error-format
1011 // is unstable, it will not be present. We have to use opts_present not
1012 // opt_present because the latter will panic.
1013 let error_format
= if matches
.opts_present(&["error-format".to_owned()]) {
1014 match matches
.opt_str("error-format").as_ref().map(|s
| &s
[..]) {
1015 Some("human") => ErrorOutputType
::HumanReadable(color
),
1016 Some("json") => ErrorOutputType
::Json
,
1018 None
=> ErrorOutputType
::HumanReadable(color
),
1021 early_error(ErrorOutputType
::HumanReadable(color
),
1022 &format
!("argument for --error-format must be human or json (instead \
1028 ErrorOutputType
::HumanReadable(color
)
1031 let unparsed_crate_types
= matches
.opt_strs("crate-type");
1032 let crate_types
= parse_crate_types_from_list(unparsed_crate_types
)
1033 .unwrap_or_else(|e
| early_error(error_format
, &e
[..]));
1035 let mut lint_opts
= vec
!();
1036 let mut describe_lints
= false;
1038 for &level
in &[lint
::Allow
, lint
::Warn
, lint
::Deny
, lint
::Forbid
] {
1039 for lint_name
in matches
.opt_strs(level
.as_str()) {
1040 if lint_name
== "help" {
1041 describe_lints
= true;
1043 lint_opts
.push((lint_name
.replace("-", "_"), level
));
1048 let lint_cap
= matches
.opt_str("cap-lints").map(|cap
| {
1049 lint
::Level
::from_str(&cap
).unwrap_or_else(|| {
1050 early_error(error_format
, &format
!("unknown lint level: `{}`", cap
))
1054 let debugging_opts
= build_debugging_options(matches
, error_format
);
1056 let parse_only
= debugging_opts
.parse_only
;
1057 let no_trans
= debugging_opts
.no_trans
;
1058 let treat_err_as_bug
= debugging_opts
.treat_err_as_bug
;
1059 let continue_parse_after_error
= debugging_opts
.continue_parse_after_error
;
1060 let mir_opt_level
= debugging_opts
.mir_opt_level
.unwrap_or(1);
1061 let no_analysis
= debugging_opts
.no_analysis
;
1063 let mut output_types
= HashMap
::new();
1064 if !debugging_opts
.parse_only
&& !no_trans
{
1065 for list
in matches
.opt_strs("emit") {
1066 for output_type
in list
.split('
,'
) {
1067 let mut parts
= output_type
.splitn(2, '
='
);
1068 let output_type
= match parts
.next().unwrap() {
1069 "asm" => OutputType
::Assembly
,
1070 "llvm-ir" => OutputType
::LlvmAssembly
,
1071 "llvm-bc" => OutputType
::Bitcode
,
1072 "obj" => OutputType
::Object
,
1073 "link" => OutputType
::Exe
,
1074 "dep-info" => OutputType
::DepInfo
,
1076 early_error(error_format
, &format
!("unknown emission type: `{}`",
1080 let path
= parts
.next().map(PathBuf
::from
);
1081 output_types
.insert(output_type
, path
);
1085 if output_types
.is_empty() {
1086 output_types
.insert(OutputType
::Exe
, None
);
1089 let mut cg
= build_codegen_options(matches
, error_format
);
1091 // Issue #30063: if user requests llvm-related output to one
1092 // particular path, disable codegen-units.
1093 if matches
.opt_present("o") && cg
.codegen_units
!= 1 {
1094 let incompatible
: Vec
<_
> = output_types
.iter()
1095 .map(|ot_path
| ot_path
.0)
1097 !ot
.is_compatible_with_codegen_units_and_single_output_file()
1099 if !incompatible
.is_empty() {
1100 for ot
in &incompatible
{
1101 early_warn(error_format
, &format
!("--emit={} with -o incompatible with \
1102 -C codegen-units=N for N > 1",
1105 early_warn(error_format
, "resetting to default -C codegen-units=1");
1106 cg
.codegen_units
= 1;
1110 if cg
.codegen_units
< 1 {
1111 early_error(error_format
, "Value for codegen units must be a positive nonzero integer");
1116 let sysroot_opt
= matches
.opt_str("sysroot").map(|m
| PathBuf
::from(&m
));
1117 let target
= matches
.opt_str("target").unwrap_or(
1118 host_triple().to_string());
1120 if matches
.opt_present("O") {
1121 if cg
.opt_level
.is_some() {
1122 early_error(error_format
, "-O and -C opt-level both provided");
1126 match cg
.opt_level
{
1127 None
=> OptLevel
::No
,
1128 Some(0) => OptLevel
::No
,
1129 Some(1) => OptLevel
::Less
,
1130 Some(2) => OptLevel
::Default
,
1131 Some(3) => OptLevel
::Aggressive
,
1133 early_error(error_format
, &format
!("optimization level needs to be \
1134 between 0-3 (instead was `{}`)",
1140 let debug_assertions
= cg
.debug_assertions
.unwrap_or(opt_level
== OptLevel
::No
);
1141 let gc
= debugging_opts
.gc
;
1142 let debuginfo
= if matches
.opt_present("g") {
1143 if cg
.debuginfo
.is_some() {
1144 early_error(error_format
, "-g and -C debuginfo both provided");
1148 match cg
.debuginfo
{
1149 None
| Some(0) => NoDebugInfo
,
1150 Some(1) => LimitedDebugInfo
,
1151 Some(2) => FullDebugInfo
,
1153 early_error(error_format
, &format
!("debug info level needs to be between \
1154 0-2 (instead was `{}`)",
1160 let mut search_paths
= SearchPaths
::new();
1161 for s
in &matches
.opt_strs("L") {
1162 search_paths
.add_path(&s
[..], error_format
);
1165 let libs
= matches
.opt_strs("l").into_iter().map(|s
| {
1166 let mut parts
= s
.splitn(2, '
='
);
1167 let kind
= parts
.next().unwrap();
1168 let (name
, kind
) = match (parts
.next(), kind
) {
1170 (Some(name
), "dylib") => (name
, cstore
::NativeUnknown
),
1171 (Some(name
), "framework") => (name
, cstore
::NativeFramework
),
1172 (Some(name
), "static") => (name
, cstore
::NativeStatic
),
1174 early_error(error_format
, &format
!("unknown library kind `{}`, expected \
1175 one of dylib, framework, or static",
1179 (name
.to_string(), kind
)
1182 let cfg
= parse_cfgspecs(matches
.opt_strs("cfg"));
1183 let test
= matches
.opt_present("test");
1185 let prints
= matches
.opt_strs("print").into_iter().map(|s
| {
1187 "crate-name" => PrintRequest
::CrateName
,
1188 "file-names" => PrintRequest
::FileNames
,
1189 "sysroot" => PrintRequest
::Sysroot
,
1190 "cfg" => PrintRequest
::Cfg
,
1191 "target-list" => PrintRequest
::TargetList
,
1193 early_error(error_format
, &format
!("unknown print request `{}`", req
))
1196 }).collect
::<Vec
<_
>>();
1198 if !cg
.remark
.is_empty() && debuginfo
== NoDebugInfo
{
1199 early_warn(error_format
, "-C remark will not show source locations without \
1203 let mut externs
= HashMap
::new();
1204 for arg
in &matches
.opt_strs("extern") {
1205 let mut parts
= arg
.splitn(2, '
='
);
1206 let name
= match parts
.next() {
1208 None
=> early_error(error_format
, "--extern value must not be empty"),
1210 let location
= match parts
.next() {
1212 None
=> early_error(error_format
, "--extern value must be of the format `foo=bar`"),
1215 externs
.entry(name
.to_string()).or_insert(vec
![]).push(location
.to_string());
1218 let crate_name
= matches
.opt_str("crate-name");
1220 let incremental
= debugging_opts
.incremental
.as_ref().map(|m
| PathBuf
::from(m
));
1223 crate_types
: crate_types
,
1225 optimize
: opt_level
,
1226 debuginfo
: debuginfo
,
1227 lint_opts
: lint_opts
,
1229 describe_lints
: describe_lints
,
1230 output_types
: output_types
,
1231 search_paths
: search_paths
,
1232 maybe_sysroot
: sysroot_opt
,
1233 target_triple
: target
,
1236 parse_only
: parse_only
,
1238 treat_err_as_bug
: treat_err_as_bug
,
1239 continue_parse_after_error
: continue_parse_after_error
,
1240 mir_opt_level
: mir_opt_level
,
1241 incremental
: incremental
,
1242 no_analysis
: no_analysis
,
1243 debugging_opts
: debugging_opts
,
1246 error_format
: error_format
,
1248 crate_name
: crate_name
,
1251 unstable_features
: get_unstable_features_setting(),
1252 debug_assertions
: debug_assertions
,
1256 pub fn get_unstable_features_setting() -> UnstableFeatures
{
1257 // Whether this is a feature-staged build, i.e. on the beta or stable channel
1258 let disable_unstable_features
= option_env
!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
1259 // The secret key needed to get through the rustc build itself by
1260 // subverting the unstable features lints
1261 let bootstrap_secret_key
= option_env
!("CFG_BOOTSTRAP_KEY");
1262 // The matching key to the above, only known by the build system
1263 let bootstrap_provided_key
= env
::var("RUSTC_BOOTSTRAP_KEY").ok();
1264 match (disable_unstable_features
, bootstrap_secret_key
, bootstrap_provided_key
) {
1265 (_
, Some(ref s
), Some(ref p
)) if s
== p
=> UnstableFeatures
::Cheat
,
1266 (true, _
, _
) => UnstableFeatures
::Disallow
,
1267 (false, _
, _
) => UnstableFeatures
::Allow
1271 pub fn parse_crate_types_from_list(list_list
: Vec
<String
>) -> Result
<Vec
<CrateType
>, String
> {
1272 let mut crate_types
: Vec
<CrateType
> = Vec
::new();
1273 for unparsed_crate_type
in &list_list
{
1274 for part
in unparsed_crate_type
.split('
,'
) {
1275 let new_part
= match part
{
1276 "lib" => default_lib_output(),
1277 "rlib" => CrateTypeRlib
,
1278 "staticlib" => CrateTypeStaticlib
,
1279 "dylib" => CrateTypeDylib
,
1280 "bin" => CrateTypeExecutable
,
1282 return Err(format
!("unknown crate type: `{}`",
1286 if !crate_types
.contains(&new_part
) {
1287 crate_types
.push(new_part
)
1292 return Ok(crate_types
);
1295 pub mod nightly_options
{
1297 use syntax
::feature_gate
::UnstableFeatures
;
1298 use super::{ErrorOutputType, OptionStability, RustcOptGroup, get_unstable_features_setting}
;
1299 use session
::{early_error, early_warn}
;
1301 pub fn is_unstable_enabled(matches
: &getopts
::Matches
) -> bool
{
1302 is_nightly_build() && matches
.opt_strs("Z").iter().any(|x
| *x
== "unstable-options")
1305 fn is_nightly_build() -> bool
{
1306 match get_unstable_features_setting() {
1307 UnstableFeatures
::Allow
| UnstableFeatures
::Cheat
=> true,
1312 pub fn check_nightly_options(matches
: &getopts
::Matches
, flags
: &[RustcOptGroup
]) {
1313 let has_z_unstable_option
= matches
.opt_strs("Z").iter().any(|x
| *x
== "unstable-options");
1314 let really_allows_unstable_options
= match get_unstable_features_setting() {
1315 UnstableFeatures
::Disallow
=> false,
1319 for opt
in flags
.iter() {
1320 if opt
.stability
== OptionStability
::Stable
{
1323 let opt_name
= if opt
.opt_group
.long_name
.is_empty() {
1324 &opt
.opt_group
.short_name
1326 &opt
.opt_group
.long_name
1328 if !matches
.opt_present(opt_name
) {
1331 if opt_name
!= "Z" && !has_z_unstable_option
{
1332 early_error(ErrorOutputType
::default(),
1333 &format
!("the `-Z unstable-options` flag must also be passed to enable \
1337 if really_allows_unstable_options
{
1340 match opt
.stability
{
1341 OptionStability
::Unstable
=> {
1342 let msg
= format
!("the option `{}` is only accepted on the \
1343 nightly compiler", opt_name
);
1344 early_error(ErrorOutputType
::default(), &msg
);
1346 OptionStability
::UnstableButNotReally
=> {
1347 let msg
= format
!("the option `{}` is is unstable and should \
1348 only be used on the nightly compiler, but \
1349 it is currently accepted for backwards \
1350 compatibility; this will soon change, \
1351 see issue #31847 for more details",
1353 early_warn(ErrorOutputType
::default(), &msg
);
1355 OptionStability
::Stable
=> {}
1361 impl fmt
::Display
for CrateType
{
1362 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
1364 CrateTypeExecutable
=> "bin".fmt(f
),
1365 CrateTypeDylib
=> "dylib".fmt(f
),
1366 CrateTypeRlib
=> "rlib".fmt(f
),
1367 CrateTypeStaticlib
=> "staticlib".fmt(f
)
1374 use middle
::cstore
::DummyCrateStore
;
1375 use session
::config
::{build_configuration, build_session_options}
;
1376 use session
::build_session
;
1379 use getopts
::{getopts, OptGroup}
;
1381 use syntax
::attr
::AttrMetaMethods
;
1382 use syntax
::diagnostics
;
1384 fn optgroups() -> Vec
<OptGroup
> {
1385 super::rustc_optgroups().into_iter()
1386 .map(|a
| a
.opt_group
)
1390 // When the user supplies --test we should implicitly supply --cfg test
1392 fn test_switch_implies_cfg_test() {
1394 &match getopts(&["--test".to_string()], &optgroups()) {
1396 Err(f
) => panic
!("test_switch_implies_cfg_test: {}", f
)
1398 let registry
= diagnostics
::registry
::Registry
::new(&[]);
1399 let sessopts
= build_session_options(matches
);
1400 let sess
= build_session(sessopts
, None
, registry
, Rc
::new(DummyCrateStore
));
1401 let cfg
= build_configuration(&sess
);
1402 assert
!((attr
::contains_name(&cfg
[..], "test")));
1405 // When the user supplies --test and --cfg test, don't implicitly add
1406 // another --cfg test
1408 fn test_switch_implies_cfg_test_unless_cfg_test() {
1410 &match getopts(&["--test".to_string(), "--cfg=test".to_string()],
1414 panic
!("test_switch_implies_cfg_test_unless_cfg_test: {}", f
)
1417 let registry
= diagnostics
::registry
::Registry
::new(&[]);
1418 let sessopts
= build_session_options(matches
);
1419 let sess
= build_session(sessopts
, None
, registry
,
1420 Rc
::new(DummyCrateStore
));
1421 let cfg
= build_configuration(&sess
);
1422 let mut test_items
= cfg
.iter().filter(|m
| m
.name() == "test");
1423 assert
!(test_items
.next().is_some());
1424 assert
!(test_items
.next().is_none());
1428 fn test_can_print_warnings() {
1430 let matches
= getopts(&[
1431 "-Awarnings".to_string()
1432 ], &optgroups()).unwrap();
1433 let registry
= diagnostics
::registry
::Registry
::new(&[]);
1434 let sessopts
= build_session_options(&matches
);
1435 let sess
= build_session(sessopts
, None
, registry
,
1436 Rc
::new(DummyCrateStore
));
1437 assert
!(!sess
.diagnostic().can_emit_warnings
);
1441 let matches
= getopts(&[
1442 "-Awarnings".to_string(),
1443 "-Dwarnings".to_string()
1444 ], &optgroups()).unwrap();
1445 let registry
= diagnostics
::registry
::Registry
::new(&[]);
1446 let sessopts
= build_session_options(&matches
);
1447 let sess
= build_session(sessopts
, None
, registry
,
1448 Rc
::new(DummyCrateStore
));
1449 assert
!(sess
.diagnostic().can_emit_warnings
);
1453 let matches
= getopts(&[
1454 "-Adead_code".to_string()
1455 ], &optgroups()).unwrap();
1456 let registry
= diagnostics
::registry
::Registry
::new(&[]);
1457 let sessopts
= build_session_options(&matches
);
1458 let sess
= build_session(sessopts
, None
, registry
,
1459 Rc
::new(DummyCrateStore
));
1460 assert
!(sess
.diagnostic().can_emit_warnings
);