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 ich
::StableHashingContext
;
23 use rustc_back
::{LinkerFlavor, PanicStrategy, RelroLevel}
;
24 use rustc_back
::target
::Target
;
25 use rustc_data_structures
::stable_hasher
::ToStableHashKey
;
29 use syntax
::ast
::{self, IntTy, UintTy}
;
30 use syntax
::codemap
::{FilePathMapping, FileName}
;
31 use syntax
::parse
::token
;
33 use syntax
::symbol
::Symbol
;
34 use syntax
::feature_gate
::UnstableFeatures
;
36 use errors
::{ColorConfig, FatalError, Handler}
;
39 use std
::collections
::{BTreeMap, BTreeSet}
;
40 use std
::collections
::btree_map
::Iter
as BTreeMapIter
;
41 use std
::collections
::btree_map
::Keys
as BTreeMapKeysIter
;
42 use std
::collections
::btree_map
::Values
as BTreeMapValuesIter
;
45 use std
::hash
::Hasher
;
46 use std
::collections
::hash_map
::DefaultHasher
;
47 use std
::collections
::HashSet
;
48 use std
::iter
::FromIterator
;
49 use std
::path
::PathBuf
;
57 #[derive(Clone, Hash, Debug)]
65 #[derive(Clone, Copy, PartialEq, Hash)]
75 #[derive(Clone, Copy, PartialEq, Hash)]
76 pub enum DebugInfoLevel
{
82 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord,
83 RustcEncodable
, RustcDecodable
)]
95 impl_stable_hash_for
!(enum self::OutputType
{
106 impl<'tcx
> ToStableHashKey
<StableHashingContext
<'tcx
>> for OutputType
{
107 type KeyType
= OutputType
;
109 fn to_stable_hash_key(&self, _
: &StableHashingContext
<'tcx
>) -> Self::KeyType
{
115 fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool
{
118 OutputType
::DepInfo
=> true,
119 OutputType
::Bitcode
|
120 OutputType
::Assembly
|
121 OutputType
::LlvmAssembly
|
124 OutputType
::Metadata
=> false,
128 fn shorthand(&self) -> &'
static str {
130 OutputType
::Bitcode
=> "llvm-bc",
131 OutputType
::Assembly
=> "asm",
132 OutputType
::LlvmAssembly
=> "llvm-ir",
133 OutputType
::Mir
=> "mir",
134 OutputType
::Object
=> "obj",
135 OutputType
::Metadata
=> "metadata",
136 OutputType
::Exe
=> "link",
137 OutputType
::DepInfo
=> "dep-info",
141 fn from_shorthand(shorthand
: &str) -> Option
<Self> {
142 Some(match shorthand
{
143 "asm" => OutputType
::Assembly
,
144 "llvm-ir" => OutputType
::LlvmAssembly
,
145 "mir" => OutputType
::Mir
,
146 "llvm-bc" => OutputType
::Bitcode
,
147 "obj" => OutputType
::Object
,
148 "metadata" => OutputType
::Metadata
,
149 "link" => OutputType
::Exe
,
150 "dep-info" => OutputType
::DepInfo
,
155 fn shorthands_display() -> String
{
157 "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`",
158 OutputType
::Bitcode
.shorthand(),
159 OutputType
::Assembly
.shorthand(),
160 OutputType
::LlvmAssembly
.shorthand(),
161 OutputType
::Mir
.shorthand(),
162 OutputType
::Object
.shorthand(),
163 OutputType
::Metadata
.shorthand(),
164 OutputType
::Exe
.shorthand(),
165 OutputType
::DepInfo
.shorthand(),
169 pub fn extension(&self) -> &'
static str {
171 OutputType
::Bitcode
=> "bc",
172 OutputType
::Assembly
=> "s",
173 OutputType
::LlvmAssembly
=> "ll",
174 OutputType
::Mir
=> "mir",
175 OutputType
::Object
=> "o",
176 OutputType
::Metadata
=> "rmeta",
177 OutputType
::DepInfo
=> "d",
178 OutputType
::Exe
=> "",
183 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
184 pub enum ErrorOutputType
{
185 HumanReadable(ColorConfig
),
190 impl Default
for ErrorOutputType
{
191 fn default() -> ErrorOutputType
{
192 ErrorOutputType
::HumanReadable(ColorConfig
::Auto
)
196 // Use tree-based collections to cheaply get a deterministic Hash implementation.
197 // DO NOT switch BTreeMap out for an unsorted container type! That would break
198 // dependency tracking for commandline arguments.
199 #[derive(Clone, Hash)]
200 pub struct OutputTypes(BTreeMap
<OutputType
, Option
<PathBuf
>>);
202 impl_stable_hash_for
!(tuple_struct
self::OutputTypes
{
207 pub fn new(entries
: &[(OutputType
, Option
<PathBuf
>)]) -> OutputTypes
{
208 OutputTypes(BTreeMap
::from_iter(entries
.iter()
209 .map(|&(k
, ref v
)| (k
, v
.clone()))))
212 pub fn get(&self, key
: &OutputType
) -> Option
<&Option
<PathBuf
>> {
216 pub fn contains_key(&self, key
: &OutputType
) -> bool
{
217 self.0.contains_key(key
)
220 pub fn keys
<'a
>(&'a
self) -> BTreeMapKeysIter
<'a
, OutputType
, Option
<PathBuf
>> {
224 pub fn values
<'a
>(&'a
self) -> BTreeMapValuesIter
<'a
, OutputType
, Option
<PathBuf
>> {
228 // True if any of the output types require codegen or linking.
229 pub fn should_trans(&self) -> bool
{
230 self.0.keys().any(|k
| match *k
{
231 OutputType
::Bitcode
|
232 OutputType
::Assembly
|
233 OutputType
::LlvmAssembly
|
236 OutputType
::Exe
=> true,
237 OutputType
::Metadata
|
238 OutputType
::DepInfo
=> false,
244 // Use tree-based collections to cheaply get a deterministic Hash implementation.
245 // DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That
246 // would break dependency tracking for commandline arguments.
247 #[derive(Clone, Hash)]
248 pub struct Externs(BTreeMap
<String
, BTreeSet
<String
>>);
251 pub fn new(data
: BTreeMap
<String
, BTreeSet
<String
>>) -> Externs
{
255 pub fn get(&self, key
: &str) -> Option
<&BTreeSet
<String
>> {
259 pub fn iter
<'a
>(&'a
self) -> BTreeMapIter
<'a
, String
, BTreeSet
<String
>> {
264 macro_rules
! hash_option
{
265 ($opt_name
:ident
, $opt_expr
:expr
, $sub_hashes
:expr
, [UNTRACKED
]) => ({}
);
266 ($opt_name
:ident
, $opt_expr
:expr
, $sub_hashes
:expr
, [TRACKED
]) => ({
267 if $sub_hashes
.insert(stringify
!($opt_name
),
268 $opt_expr
as &dep_tracking
::DepTrackingHash
).is_some() {
269 bug
!("Duplicate key in CLI DepTrackingHash: {}", stringify
!($opt_name
))
275 [UNTRACKED_WITH_WARNING $warn_val
:expr
, $warn_text
:expr
, $error_format
:expr
]) => ({
276 if *$opt_expr
== $warn_val
{
277 early_warn($error_format
, $warn_text
)
282 macro_rules
! top_level_options
{
283 (pub struct Options
{ $
(
284 $opt
:ident
: $t
:ty
[$dep_tracking_marker
:ident $
($warn_val
:expr
, $warn_text
:expr
)*],
292 pub fn dep_tracking_hash(&self) -> u64 {
293 let mut sub_hashes
= BTreeMap
::new();
298 [$dep_tracking_marker $
($warn_val
,
300 self.error_format
)*]);
302 let mut hasher
= DefaultHasher
::new();
303 dep_tracking
::stable_hash(sub_hashes
,
312 // The top-level commandline options struct
314 // For each option, one has to specify how it behaves with regard to the
315 // dependency tracking system of incremental compilation. This is done via the
316 // square-bracketed directive after the field type. The options are:
319 // A change in the given field will cause the compiler to completely clear the
320 // incremental compilation cache before proceeding.
323 // Incremental compilation is not influenced by this option.
325 // [UNTRACKED_WITH_WARNING(val, warning)]
326 // The option is incompatible with incremental compilation in some way. If it
327 // has the value `val`, the string `warning` is emitted as a warning.
329 // If you add a new option to this struct or one of the sub-structs like
330 // CodegenOptions, think about how it influences incremental compilation. If in
331 // doubt, specify [TRACKED], which is always "correct" but might lead to
332 // unnecessary re-compilation.
335 // The crate config requested for the session, which may be combined
336 // with additional crate configurations during the compile process
337 crate_types
: Vec
<CrateType
> [TRACKED
],
338 optimize
: OptLevel
[TRACKED
],
339 // Include the debug_assertions flag into dependency tracking, since it
340 // can influence whether overflow checks are done or not.
341 debug_assertions
: bool
[TRACKED
],
342 debuginfo
: DebugInfoLevel
[TRACKED
],
343 lint_opts
: Vec
<(String
, lint
::Level
)> [TRACKED
],
344 lint_cap
: Option
<lint
::Level
> [TRACKED
],
345 describe_lints
: bool
[UNTRACKED
],
346 output_types
: OutputTypes
[TRACKED
],
347 // FIXME(mw): We track this for now but it actually doesn't make too
348 // much sense: The search path can stay the same while the
349 // things discovered there might have changed on disk.
350 search_paths
: SearchPaths
[TRACKED
],
351 libs
: Vec
<(String
, Option
<String
>, Option
<cstore
::NativeLibraryKind
>)> [TRACKED
],
352 maybe_sysroot
: Option
<PathBuf
> [TRACKED
],
354 target_triple
: String
[TRACKED
],
356 test
: bool
[TRACKED
],
357 error_format
: ErrorOutputType
[UNTRACKED
],
359 // if Some, enable incremental compilation, using the given
360 // directory to store intermediate results
361 incremental
: Option
<PathBuf
> [UNTRACKED
],
363 debugging_opts
: DebuggingOptions
[TRACKED
],
364 prints
: Vec
<PrintRequest
> [UNTRACKED
],
365 // Determines which borrow checker(s) to run. This is the parsed, sanitized
366 // version of `debugging_opts.borrowck`, which is just a plain string.
367 borrowck_mode
: BorrowckMode
[UNTRACKED
],
368 cg
: CodegenOptions
[TRACKED
],
369 // FIXME(mw): We track this for now but it actually doesn't make too
370 // much sense: The value of this option can stay the same
371 // while the files they refer to might have changed on disk.
372 externs
: Externs
[TRACKED
],
373 crate_name
: Option
<String
> [TRACKED
],
374 // An optional name to use as the crate for std during std injection,
375 // written `extern crate std = "name"`. Default to "std". Used by
376 // out-of-tree drivers.
377 alt_std_name
: Option
<String
> [TRACKED
],
378 // Indicates how the compiler should treat unstable features
379 unstable_features
: UnstableFeatures
[TRACKED
],
381 // Indicates whether this run of the compiler is actually rustdoc. This
382 // is currently just a hack and will be removed eventually, so please
383 // try to not rely on this too much.
384 actually_rustdoc
: bool
[TRACKED
],
386 // Specifications of codegen units / ThinLTO which are forced as a
387 // result of parsing command line options. These are not necessarily
388 // what rustc was invoked with, but massaged a bit to agree with
389 // commands like `--emit llvm-ir` which they're often incompatible with
390 // if we otherwise use the defaults of rustc.
391 cli_forced_codegen_units
: Option
<usize> [UNTRACKED
],
392 cli_forced_thinlto
: Option
<bool
> [UNTRACKED
],
396 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
397 pub enum PrintRequest
{
412 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
413 pub enum BorrowckMode
{
420 /// Should we emit the AST-based borrow checker errors?
421 pub fn use_ast(self) -> bool
{
423 BorrowckMode
::Ast
=> true,
424 BorrowckMode
::Compare
=> true,
425 BorrowckMode
::Mir
=> false,
428 /// Should we emit the MIR-based borrow checker errors?
429 pub fn use_mir(self) -> bool
{
431 BorrowckMode
::Ast
=> false,
432 BorrowckMode
::Compare
=> true,
433 BorrowckMode
::Mir
=> true,
439 /// Load source from file
442 /// String that is shown in place of a filename
444 /// Anonymous source string
450 pub fn filestem(&self) -> String
{
452 Input
::File(ref ifile
) => ifile
.file_stem().unwrap()
453 .to_str().unwrap().to_string(),
454 Input
::Str { .. }
=> "rust_out".to_string(),
460 pub struct OutputFilenames
{
461 pub out_directory
: PathBuf
,
462 pub out_filestem
: String
,
463 pub single_output_file
: Option
<PathBuf
>,
465 pub outputs
: OutputTypes
,
468 impl_stable_hash_for
!(struct self::OutputFilenames
{
476 pub const RUST_CGU_EXT
: &str = "rcgu";
478 impl OutputFilenames
{
479 pub fn path(&self, flavor
: OutputType
) -> PathBuf
{
480 self.outputs
.get(&flavor
).and_then(|p
| p
.to_owned())
481 .or_else(|| self.single_output_file
.clone())
482 .unwrap_or_else(|| self.temp_path(flavor
, None
))
485 /// Get the path where a compilation artifact of the given type for the
486 /// given codegen unit should be placed on disk. If codegen_unit_name is
487 /// None, a path distinct from those of any codegen unit will be generated.
488 pub fn temp_path(&self,
490 codegen_unit_name
: Option
<&str>)
492 let extension
= flavor
.extension();
493 self.temp_path_ext(extension
, codegen_unit_name
)
496 /// Like temp_path, but also supports things where there is no corresponding
497 /// OutputType, like no-opt-bitcode or lto-bitcode.
498 pub fn temp_path_ext(&self,
500 codegen_unit_name
: Option
<&str>)
502 let base
= self.out_directory
.join(&self.filestem());
504 let mut extension
= String
::new();
506 if let Some(codegen_unit_name
) = codegen_unit_name
{
507 extension
.push_str(codegen_unit_name
);
511 if !extension
.is_empty() {
512 extension
.push_str(".");
513 extension
.push_str(RUST_CGU_EXT
);
514 extension
.push_str(".");
517 extension
.push_str(ext
);
520 let path
= base
.with_extension(&extension
[..]);
524 pub fn with_extension(&self, extension
: &str) -> PathBuf
{
525 self.out_directory
.join(&self.filestem()).with_extension(extension
)
528 pub fn filestem(&self) -> String
{
529 format
!("{}{}", self.out_filestem
, self.extra
)
532 pub fn contains_path(&self, input_path
: &PathBuf
) -> bool
{
533 let input_path
= input_path
.canonicalize().ok();
534 if input_path
.is_none() {
537 match self.single_output_file
{
538 Some(ref output_path
) => output_path
.canonicalize().ok() == input_path
,
540 for k
in self.outputs
.keys() {
541 let output_path
= self.path(k
.to_owned());
542 if output_path
.canonicalize().ok() == input_path
{
552 pub fn host_triple() -> &'
static str {
553 // Get the host triple out of the build environment. This ensures that our
554 // idea of the host triple is the same as for the set of libraries we've
555 // actually built. We can't just take LLVM's host triple because they
556 // normalize all ix86 architectures to i386.
558 // Instead of grabbing the host triple (for the current host), we grab (at
559 // compile time) the target triple that this rustc is built with and
560 // calling that (at runtime) the host triple.
561 (option_env
!("CFG_COMPILER_HOST_TRIPLE")).
562 expect("CFG_COMPILER_HOST_TRIPLE")
565 /// Some reasonable defaults
566 pub fn basic_options() -> Options
{
568 crate_types
: Vec
::new(),
569 optimize
: OptLevel
::No
,
570 debuginfo
: NoDebugInfo
,
571 lint_opts
: Vec
::new(),
573 describe_lints
: false,
574 output_types
: OutputTypes(BTreeMap
::new()),
575 search_paths
: SearchPaths
::new(),
577 target_triple
: host_triple().to_string(),
580 debugging_opts
: basic_debugging_options(),
582 borrowck_mode
: BorrowckMode
::Ast
,
583 cg
: basic_codegen_options(),
584 error_format
: ErrorOutputType
::default(),
585 externs
: Externs(BTreeMap
::new()),
589 unstable_features
: UnstableFeatures
::Disallow
,
590 debug_assertions
: true,
591 actually_rustdoc
: false,
592 cli_forced_codegen_units
: None
,
593 cli_forced_thinlto
: None
,
598 /// True if there is a reason to build the dep graph.
599 pub fn build_dep_graph(&self) -> bool
{
600 self.incremental
.is_some() ||
601 self.debugging_opts
.dump_dep_graph
||
602 self.debugging_opts
.query_dep_graph
606 pub fn enable_dep_node_debug_strs(&self) -> bool
{
607 cfg
!(debug_assertions
) &&
608 (self.debugging_opts
.query_dep_graph
|| self.debugging_opts
.incremental_info
)
611 pub fn file_path_mapping(&self) -> FilePathMapping
{
612 FilePathMapping
::new(
613 self.debugging_opts
.remap_path_prefix_from
.iter().zip(
614 self.debugging_opts
.remap_path_prefix_to
.iter()
615 ).map(|(src
, dst
)| (src
.clone(), dst
.clone())).collect()
619 /// True if there will be an output file generated
620 pub fn will_create_output_file(&self) -> bool
{
621 !self.debugging_opts
.parse_only
&& // The file is just being parsed
622 !self.debugging_opts
.ls
// The file is just being queried
626 // The type of entry function, so
627 // users can have their own entry
628 // functions that don't start a
630 #[derive(Copy, Clone, PartialEq)]
631 pub enum EntryFnType
{
637 #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
647 #[derive(Clone, Hash)]
649 SomePasses(Vec
<String
>),
654 pub fn is_empty(&self) -> bool
{
656 SomePasses(ref v
) => v
.is_empty(),
662 /// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all
663 /// at once. The goal of this macro is to define an interface that can be
664 /// programmatically used by the option parser in order to initialize the struct
665 /// without hardcoding field names all over the place.
667 /// The goal is to invoke this macro once with the correct fields, and then this
668 /// macro generates all necessary code. The main gotcha of this macro is the
669 /// cgsetters module which is a bunch of generated code to parse an option into
670 /// its respective field in the struct. There are a few hand-written parsers for
671 /// parsing specific types of values in this module.
672 macro_rules
! options
{
673 ($struct_name
:ident
, $setter_name
:ident
, $defaultfn
:ident
,
674 $buildfn
:ident
, $prefix
:expr
, $outputname
:expr
,
675 $stat
:ident
, $mod_desc
:ident
, $mod_set
:ident
,
676 $
($opt
:ident
: $t
:ty
= (
679 [$dep_tracking_marker
:ident $
(($dep_warn_val
:expr
, $dep_warn_text
:expr
))*],
684 pub struct $struct_name { $(pub $opt: $t),* }
686 pub fn $
defaultfn() -> $struct_name
{
687 $struct_name { $($opt: $init),* }
690 pub fn $
buildfn(matches
: &getopts
::Matches
, error_format
: ErrorOutputType
) -> $struct_name
692 let mut op
= $
defaultfn();
693 for option
in matches
.opt_strs($prefix
) {
694 let mut iter
= option
.splitn(2, '
='
);
695 let key
= iter
.next().unwrap();
696 let value
= iter
.next();
697 let option_to_lookup
= key
.replace("-", "_");
698 let mut found
= false;
699 for &(candidate
, setter
, opt_type_desc
, _
) in $stat
{
700 if option_to_lookup
!= candidate { continue }
701 if !setter(&mut op
, value
) {
702 match (value
, opt_type_desc
) {
703 (Some(..), None
) => {
704 early_error(error_format
, &format
!("{} option `{}` takes no \
705 value", $outputname
, key
))
707 (None
, Some(type_desc
)) => {
708 early_error(error_format
, &format
!("{0} option `{1}` requires \
709 {2} ({3} {1}=<value>)",
713 (Some(value
), Some(type_desc
)) => {
714 early_error(error_format
, &format
!("incorrect value `{}` for {} \
715 option `{}` - {} was expected",
719 (None
, None
) => bug
!()
726 early_error(error_format
, &format
!("unknown {} option: `{}`",
733 impl<'a
> dep_tracking
::DepTrackingHash
for $struct_name
{
735 fn hash(&self, hasher
: &mut DefaultHasher
, error_format
: ErrorOutputType
) {
736 let mut sub_hashes
= BTreeMap
::new();
741 [$dep_tracking_marker $
($dep_warn_val
,
745 dep_tracking
::stable_hash(sub_hashes
, hasher
, error_format
);
749 pub type $setter_name
= fn(&mut $struct_name
, v
: Option
<&str>) -> bool
;
750 pub const $stat
: &'
static [(&'
static str, $setter_name
,
751 Option
<&'
static str>, &'
static str)] =
752 &[ $
( (stringify
!($opt
), $mod_set
::$opt
, $mod_desc
::$parse
, $desc
) ),* ];
754 #[allow(non_upper_case_globals, dead_code)]
756 pub const parse_bool
: Option
<&'
static str> = None
;
757 pub const parse_opt_bool
: Option
<&'
static str> =
758 Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`");
759 pub const parse_string
: Option
<&'
static str> = Some("a string");
760 pub const parse_string_push
: Option
<&'
static str> = Some("a string");
761 pub const parse_pathbuf_push
: Option
<&'
static str> = Some("a path");
762 pub const parse_opt_string
: Option
<&'
static str> = Some("a string");
763 pub const parse_opt_pathbuf
: Option
<&'
static str> = Some("a path");
764 pub const parse_list
: Option
<&'
static str> = Some("a space-separated list of strings");
765 pub const parse_opt_list
: Option
<&'
static str> = Some("a space-separated list of strings");
766 pub const parse_uint
: Option
<&'
static str> = Some("a number");
767 pub const parse_passes
: Option
<&'
static str> =
768 Some("a space-separated list of passes, or `all`");
769 pub const parse_opt_uint
: Option
<&'
static str> =
771 pub const parse_panic_strategy
: Option
<&'
static str> =
772 Some("either `panic` or `abort`");
773 pub const parse_relro_level
: Option
<&'
static str> =
774 Some("one of: `full`, `partial`, or `off`");
775 pub const parse_sanitizer
: Option
<&'
static str> =
776 Some("one of: `address`, `leak`, `memory` or `thread`");
777 pub const parse_linker_flavor
: Option
<&'
static str> =
778 Some(::rustc_back
::LinkerFlavor
::one_of());
779 pub const parse_optimization_fuel
: Option
<&'
static str> =
780 Some("crate=integer");
785 use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer}
;
786 use rustc_back
::{LinkerFlavor, PanicStrategy, RelroLevel}
;
787 use std
::path
::PathBuf
;
790 pub fn $
opt(cg
: &mut $struct_name
, v
: Option
<&str>) -> bool
{
791 $
parse(&mut cg
.$opt
, v
)
795 fn parse_bool(slot
: &mut bool
, v
: Option
<&str>) -> bool
{
798 None
=> { *slot = true; true }
802 fn parse_opt_bool(slot
: &mut Option
<bool
>, v
: Option
<&str>) -> bool
{
806 "n" | "no" | "off" => {
809 "y" | "yes" | "on" => {
812 _
=> { return false; }
817 None
=> { *slot = Some(true); true }
821 fn parse_opt_string(slot
: &mut Option
<String
>, v
: Option
<&str>) -> bool
{
823 Some(s
) => { *slot = Some(s.to_string()); true }
,
828 fn parse_opt_pathbuf(slot
: &mut Option
<PathBuf
>, v
: Option
<&str>) -> bool
{
830 Some(s
) => { *slot = Some(PathBuf::from(s)); true }
,
835 fn parse_string(slot
: &mut String
, v
: Option
<&str>) -> bool
{
837 Some(s
) => { *slot = s.to_string(); true }
,
842 fn parse_string_push(slot
: &mut Vec
<String
>, v
: Option
<&str>) -> bool
{
844 Some(s
) => { slot.push(s.to_string()); true }
,
849 fn parse_pathbuf_push(slot
: &mut Vec
<PathBuf
>, v
: Option
<&str>) -> bool
{
851 Some(s
) => { slot.push(PathBuf::from(s)); true }
,
856 fn parse_list(slot
: &mut Vec
<String
>, v
: Option
<&str>)
860 for s
in s
.split_whitespace() {
861 slot
.push(s
.to_string());
869 fn parse_opt_list(slot
: &mut Option
<Vec
<String
>>, v
: Option
<&str>)
873 let v
= s
.split_whitespace().map(|s
| s
.to_string()).collect();
881 fn parse_uint(slot
: &mut usize, v
: Option
<&str>) -> bool
{
882 match v
.and_then(|s
| s
.parse().ok()) {
883 Some(i
) => { *slot = i; true }
,
888 fn parse_opt_uint(slot
: &mut Option
<usize>, v
: Option
<&str>) -> bool
{
890 Some(s
) => { *slot = s.parse().ok(); slot.is_some() }
891 None
=> { *slot = None; false }
895 fn parse_passes(slot
: &mut Passes
, v
: Option
<&str>) -> bool
{
902 let mut passes
= vec
![];
903 if parse_list(&mut passes
, v
) {
904 *slot
= SomePasses(passes
);
913 fn parse_panic_strategy(slot
: &mut Option
<PanicStrategy
>, v
: Option
<&str>) -> bool
{
915 Some("unwind") => *slot
= Some(PanicStrategy
::Unwind
),
916 Some("abort") => *slot
= Some(PanicStrategy
::Abort
),
922 fn parse_relro_level(slot
: &mut Option
<RelroLevel
>, v
: Option
<&str>) -> bool
{
925 match s
.parse
::<RelroLevel
>() {
926 Ok(level
) => *slot
= Some(level
),
935 fn parse_sanitizer(slote
: &mut Option
<Sanitizer
>, v
: Option
<&str>) -> bool
{
937 Some("address") => *slote
= Some(Sanitizer
::Address
),
938 Some("leak") => *slote
= Some(Sanitizer
::Leak
),
939 Some("memory") => *slote
= Some(Sanitizer
::Memory
),
940 Some("thread") => *slote
= Some(Sanitizer
::Thread
),
946 fn parse_linker_flavor(slote
: &mut Option
<LinkerFlavor
>, v
: Option
<&str>) -> bool
{
947 match v
.and_then(LinkerFlavor
::from_str
) {
948 Some(lf
) => *slote
= Some(lf
),
954 fn parse_optimization_fuel(slot
: &mut Option
<(String
, u64)>, v
: Option
<&str>) -> bool
{
958 let parts
= s
.split('
='
).collect
::<Vec
<_
>>();
959 if parts
.len() != 2 { return false; }
960 let crate_name
= parts
[0].to_string();
961 let fuel
= parts
[1].parse
::<u64>();
962 if fuel
.is_err() { return false; }
963 *slot
= Some((crate_name
, fuel
.unwrap()));
971 options
! {CodegenOptions
, CodegenSetter
, basic_codegen_options
,
972 build_codegen_options
, "C", "codegen",
973 CG_OPTIONS
, cg_type_desc
, cgsetters
,
974 ar
: Option
<String
> = (None
, parse_opt_string
, [UNTRACKED
],
975 "this option is deprecated and does nothing"),
976 linker
: Option
<PathBuf
> = (None
, parse_opt_pathbuf
, [UNTRACKED
],
977 "system linker to link outputs with"),
978 link_arg
: Vec
<String
> = (vec
![], parse_string_push
, [UNTRACKED
],
979 "a single extra argument to append to the linker invocation (can be used several times)"),
980 link_args
: Option
<Vec
<String
>> = (None
, parse_opt_list
, [UNTRACKED
],
981 "extra arguments to append to the linker invocation (space separated)"),
982 link_dead_code
: bool
= (false, parse_bool
, [UNTRACKED
],
983 "don't let linker strip dead code (turning it on can be used for code coverage)"),
984 lto
: bool
= (false, parse_bool
, [TRACKED
],
985 "perform LLVM link-time optimizations"),
986 target_cpu
: Option
<String
> = (None
, parse_opt_string
, [TRACKED
],
987 "select target processor (rustc --print target-cpus for details)"),
988 target_feature
: String
= ("".to_string(), parse_string
, [TRACKED
],
989 "target specific attributes (rustc --print target-features for details)"),
990 passes
: Vec
<String
> = (Vec
::new(), parse_list
, [TRACKED
],
991 "a list of extra LLVM passes to run (space separated)"),
992 llvm_args
: Vec
<String
> = (Vec
::new(), parse_list
, [TRACKED
],
993 "a list of arguments to pass to llvm (space separated)"),
994 save_temps
: bool
= (false, parse_bool
, [UNTRACKED_WITH_WARNING(true,
995 "`-C save-temps` might not produce all requested temporary products \
996 when incremental compilation is enabled.")],
997 "save all temporary output files during compilation"),
998 rpath
: bool
= (false, parse_bool
, [UNTRACKED
],
999 "set rpath values in libs/exes"),
1000 overflow_checks
: Option
<bool
> = (None
, parse_opt_bool
, [TRACKED
],
1001 "use overflow checks for integer arithmetic"),
1002 no_prepopulate_passes
: bool
= (false, parse_bool
, [TRACKED
],
1003 "don't pre-populate the pass manager with a list of passes"),
1004 no_vectorize_loops
: bool
= (false, parse_bool
, [TRACKED
],
1005 "don't run the loop vectorization optimization passes"),
1006 no_vectorize_slp
: bool
= (false, parse_bool
, [TRACKED
],
1007 "don't run LLVM's SLP vectorization pass"),
1008 soft_float
: bool
= (false, parse_bool
, [TRACKED
],
1009 "use soft float ABI (*eabihf targets only)"),
1010 prefer_dynamic
: bool
= (false, parse_bool
, [TRACKED
],
1011 "prefer dynamic linking to static linking"),
1012 no_integrated_as
: bool
= (false, parse_bool
, [TRACKED
],
1013 "use an external assembler rather than LLVM's integrated one"),
1014 no_redzone
: Option
<bool
> = (None
, parse_opt_bool
, [TRACKED
],
1015 "disable the use of the redzone"),
1016 relocation_model
: Option
<String
> = (None
, parse_opt_string
, [TRACKED
],
1017 "choose the relocation model to use (rustc --print relocation-models for details)"),
1018 code_model
: Option
<String
> = (None
, parse_opt_string
, [TRACKED
],
1019 "choose the code model to use (rustc --print code-models for details)"),
1020 metadata
: Vec
<String
> = (Vec
::new(), parse_list
, [TRACKED
],
1021 "metadata to mangle symbol names with"),
1022 extra_filename
: String
= ("".to_string(), parse_string
, [UNTRACKED
],
1023 "extra data to put in each output filename"),
1024 codegen_units
: Option
<usize> = (None
, parse_opt_uint
, [UNTRACKED
],
1025 "divide crate into N units to optimize in parallel"),
1026 remark
: Passes
= (SomePasses(Vec
::new()), parse_passes
, [UNTRACKED
],
1027 "print remarks for these optimization passes (space separated, or \"all\")"),
1028 no_stack_check
: bool
= (false, parse_bool
, [UNTRACKED
],
1029 "the --no-stack-check flag is deprecated and does nothing"),
1030 debuginfo
: Option
<usize> = (None
, parse_opt_uint
, [TRACKED
],
1031 "debug info emission level, 0 = no debug info, 1 = line tables only, \
1032 2 = full debug info with variable and type information"),
1033 opt_level
: Option
<String
> = (None
, parse_opt_string
, [TRACKED
],
1034 "optimize with possible levels 0-3, s, or z"),
1035 debug_assertions
: Option
<bool
> = (None
, parse_opt_bool
, [TRACKED
],
1036 "explicitly enable the cfg(debug_assertions) directive"),
1037 inline_threshold
: Option
<usize> = (None
, parse_opt_uint
, [TRACKED
],
1038 "set the threshold for inlining a function (default: 225)"),
1039 panic
: Option
<PanicStrategy
> = (None
, parse_panic_strategy
,
1040 [TRACKED
], "panic strategy to compile crate with"),
1041 incremental
: Option
<String
> = (None
, parse_opt_string
, [UNTRACKED
],
1042 "enable incremental compilation"),
1045 options
! {DebuggingOptions
, DebuggingSetter
, basic_debugging_options
,
1046 build_debugging_options
, "Z", "debugging",
1047 DB_OPTIONS
, db_type_desc
, dbsetters
,
1048 verbose
: bool
= (false, parse_bool
, [UNTRACKED
],
1049 "in general, enable more debug printouts"),
1050 span_free_formats
: bool
= (false, parse_bool
, [UNTRACKED
],
1051 "when debug-printing compiler state, do not include spans"), // o/w tests have closure@path
1052 identify_regions
: bool
= (false, parse_bool
, [UNTRACKED
],
1053 "make unnamed regions display as '# (where # is some non-ident unique id)"),
1054 emit_end_regions
: bool
= (false, parse_bool
, [UNTRACKED
],
1055 "emit EndRegion as part of MIR; enable transforms that solely process EndRegion"),
1056 borrowck
: Option
<String
> = (None
, parse_opt_string
, [UNTRACKED
],
1057 "select which borrowck is used (`ast`, `mir`, or `compare`)"),
1058 two_phase_borrows
: bool
= (false, parse_bool
, [UNTRACKED
],
1059 "use two-phase reserved/active distinction for `&mut` borrows in MIR borrowck"),
1060 time_passes
: bool
= (false, parse_bool
, [UNTRACKED
],
1061 "measure time of each rustc pass"),
1062 count_llvm_insns
: bool
= (false, parse_bool
,
1063 [UNTRACKED_WITH_WARNING(true,
1064 "The output generated by `-Z count_llvm_insns` might not be reliable \
1065 when used with incremental compilation")],
1066 "count where LLVM instrs originate"),
1067 time_llvm_passes
: bool
= (false, parse_bool
, [UNTRACKED_WITH_WARNING(true,
1068 "The output of `-Z time-llvm-passes` will only reflect timings of \
1069 re-translated modules when used with incremental compilation" )],
1070 "measure time of each LLVM pass"),
1071 input_stats
: bool
= (false, parse_bool
, [UNTRACKED
],
1072 "gather statistics about the input"),
1073 trans_stats
: bool
= (false, parse_bool
, [UNTRACKED_WITH_WARNING(true,
1074 "The output of `-Z trans-stats` might not be accurate when incremental \
1075 compilation is enabled")],
1076 "gather trans statistics"),
1077 asm_comments
: bool
= (false, parse_bool
, [TRACKED
],
1078 "generate comments into the assembly (may change behavior)"),
1079 no_verify
: bool
= (false, parse_bool
, [TRACKED
],
1080 "skip LLVM verification"),
1081 borrowck_stats
: bool
= (false, parse_bool
, [UNTRACKED
],
1082 "gather borrowck statistics"),
1083 no_landing_pads
: bool
= (false, parse_bool
, [TRACKED
],
1084 "omit landing pads for unwinding"),
1085 fewer_names
: bool
= (false, parse_bool
, [TRACKED
],
1086 "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR)"),
1087 debug_llvm
: bool
= (false, parse_bool
, [UNTRACKED
],
1088 "enable debug output from LLVM"),
1089 meta_stats
: bool
= (false, parse_bool
, [UNTRACKED
],
1090 "gather metadata statistics"),
1091 print_link_args
: bool
= (false, parse_bool
, [UNTRACKED
],
1092 "print the arguments passed to the linker"),
1093 print_llvm_passes
: bool
= (false, parse_bool
, [UNTRACKED
],
1094 "prints the llvm optimization passes being run"),
1095 ast_json
: bool
= (false, parse_bool
, [UNTRACKED
],
1096 "print the AST as JSON and halt"),
1097 query_threads
: Option
<usize> = (None
, parse_opt_uint
, [UNTRACKED
],
1098 "execute queries on a thread pool with N threads"),
1099 ast_json_noexpand
: bool
= (false, parse_bool
, [UNTRACKED
],
1100 "print the pre-expansion AST as JSON and halt"),
1101 ls
: bool
= (false, parse_bool
, [UNTRACKED
],
1102 "list the symbols defined by a library crate"),
1103 save_analysis
: bool
= (false, parse_bool
, [UNTRACKED
],
1104 "write syntax and type analysis (in JSON format) information, in \
1105 addition to normal output"),
1106 flowgraph_print_loans
: bool
= (false, parse_bool
, [UNTRACKED
],
1107 "include loan analysis data in --unpretty flowgraph output"),
1108 flowgraph_print_moves
: bool
= (false, parse_bool
, [UNTRACKED
],
1109 "include move analysis data in --unpretty flowgraph output"),
1110 flowgraph_print_assigns
: bool
= (false, parse_bool
, [UNTRACKED
],
1111 "include assignment analysis data in --unpretty flowgraph output"),
1112 flowgraph_print_all
: bool
= (false, parse_bool
, [UNTRACKED
],
1113 "include all dataflow analysis data in --unpretty flowgraph output"),
1114 print_region_graph
: bool
= (false, parse_bool
, [UNTRACKED
],
1115 "prints region inference graph. \
1116 Use with RUST_REGION_GRAPH=help for more info"),
1117 parse_only
: bool
= (false, parse_bool
, [UNTRACKED
],
1118 "parse only; do not compile, assemble, or link"),
1119 no_trans
: bool
= (false, parse_bool
, [TRACKED
],
1120 "run all passes except translation; no output"),
1121 treat_err_as_bug
: bool
= (false, parse_bool
, [TRACKED
],
1122 "treat all errors that occur as bugs"),
1123 external_macro_backtrace
: bool
= (false, parse_bool
, [UNTRACKED
],
1124 "show macro backtraces even for non-local macros"),
1125 continue_parse_after_error
: bool
= (false, parse_bool
, [TRACKED
],
1126 "attempt to recover from parse errors (experimental)"),
1127 incremental
: Option
<String
> = (None
, parse_opt_string
, [UNTRACKED
],
1128 "enable incremental compilation (experimental)"),
1129 incremental_queries
: bool
= (true, parse_bool
, [UNTRACKED
],
1130 "enable incremental compilation support for queries (experimental)"),
1131 incremental_info
: bool
= (false, parse_bool
, [UNTRACKED
],
1132 "print high-level information about incremental reuse (or the lack thereof)"),
1133 incremental_dump_hash
: bool
= (false, parse_bool
, [UNTRACKED
],
1134 "dump hash information in textual format to stdout"),
1135 incremental_verify_ich
: bool
= (false, parse_bool
, [UNTRACKED
],
1136 "verify incr. comp. hashes of green query instances"),
1137 incremental_ignore_spans
: bool
= (false, parse_bool
, [UNTRACKED
],
1138 "ignore spans during ICH computation -- used for testing"),
1139 dump_dep_graph
: bool
= (false, parse_bool
, [UNTRACKED
],
1140 "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
1141 query_dep_graph
: bool
= (false, parse_bool
, [UNTRACKED
],
1142 "enable queries of the dependency graph for regression testing"),
1143 profile_queries
: bool
= (false, parse_bool
, [UNTRACKED
],
1144 "trace and profile the queries of the incremental compilation framework"),
1145 profile_queries_and_keys
: bool
= (false, parse_bool
, [UNTRACKED
],
1146 "trace and profile the queries and keys of the incremental compilation framework"),
1147 no_analysis
: bool
= (false, parse_bool
, [UNTRACKED
],
1148 "parse and expand the source, but run no analysis"),
1149 extra_plugins
: Vec
<String
> = (Vec
::new(), parse_list
, [TRACKED
],
1150 "load extra plugins"),
1151 unstable_options
: bool
= (false, parse_bool
, [UNTRACKED
],
1152 "adds unstable command line options to rustc interface"),
1153 force_overflow_checks
: Option
<bool
> = (None
, parse_opt_bool
, [TRACKED
],
1154 "force overflow checks on or off"),
1155 trace_macros
: bool
= (false, parse_bool
, [UNTRACKED
],
1156 "for every macro invocation, print its name and arguments"),
1157 debug_macros
: bool
= (false, parse_bool
, [TRACKED
],
1158 "emit line numbers debug info inside macros"),
1159 enable_nonzeroing_move_hints
: bool
= (false, parse_bool
, [TRACKED
],
1160 "force nonzeroing move optimization on"),
1161 keep_hygiene_data
: bool
= (false, parse_bool
, [UNTRACKED
],
1162 "don't clear the hygiene data after analysis"),
1163 keep_ast
: bool
= (false, parse_bool
, [UNTRACKED
],
1164 "keep the AST after lowering it to HIR"),
1165 show_span
: Option
<String
> = (None
, parse_opt_string
, [TRACKED
],
1166 "show spans for compiler debugging (expr|pat|ty)"),
1167 print_type_sizes
: bool
= (false, parse_bool
, [UNTRACKED
],
1168 "print layout information for each type encountered"),
1169 print_trans_items
: Option
<String
> = (None
, parse_opt_string
, [UNTRACKED
],
1170 "print the result of the translation item collection pass"),
1171 mir_opt_level
: usize = (1, parse_uint
, [TRACKED
],
1172 "set the MIR optimization level (0-3, default: 1)"),
1173 mutable_noalias
: bool
= (false, parse_bool
, [UNTRACKED
],
1174 "emit noalias metadata for mutable references"),
1175 dump_mir
: Option
<String
> = (None
, parse_opt_string
, [UNTRACKED
],
1176 "dump MIR state at various points in translation"),
1177 dump_mir_dir
: Option
<String
> = (None
, parse_opt_string
, [UNTRACKED
],
1178 "the directory the MIR is dumped into"),
1179 dump_mir_graphviz
: bool
= (false, parse_bool
, [UNTRACKED
],
1180 "in addition to `.mir` files, create graphviz `.dot` files"),
1181 dump_mir_exclude_pass_number
: bool
= (false, parse_bool
, [UNTRACKED
],
1182 "if set, exclude the pass number when dumping MIR (used in tests)"),
1183 mir_emit_validate
: usize = (0, parse_uint
, [TRACKED
],
1184 "emit Validate MIR statements, interpreted e.g. by miri (0: do not emit; 1: if function \
1185 contains unsafe block, only validate arguments; 2: always emit full validation)"),
1186 perf_stats
: bool
= (false, parse_bool
, [UNTRACKED
],
1187 "print some performance-related statistics"),
1188 hir_stats
: bool
= (false, parse_bool
, [UNTRACKED
],
1189 "print some statistics about AST and HIR"),
1190 mir_stats
: bool
= (false, parse_bool
, [UNTRACKED
],
1191 "print some statistics about MIR"),
1192 always_encode_mir
: bool
= (false, parse_bool
, [TRACKED
],
1193 "encode MIR of all functions into the crate metadata"),
1194 miri
: bool
= (false, parse_bool
, [TRACKED
],
1195 "check the miri const evaluator against the old ctfe"),
1196 osx_rpath_install_name
: bool
= (false, parse_bool
, [TRACKED
],
1197 "pass `-install_name @rpath/...` to the macOS linker"),
1198 sanitizer
: Option
<Sanitizer
> = (None
, parse_sanitizer
, [TRACKED
],
1200 linker_flavor
: Option
<LinkerFlavor
> = (None
, parse_linker_flavor
, [UNTRACKED
],
1202 fuel
: Option
<(String
, u64)> = (None
, parse_optimization_fuel
, [TRACKED
],
1203 "set the optimization fuel quota for a crate"),
1204 print_fuel
: Option
<String
> = (None
, parse_opt_string
, [TRACKED
],
1205 "make Rustc print the total optimization fuel used by a crate"),
1206 remap_path_prefix_from
: Vec
<PathBuf
> = (vec
![], parse_pathbuf_push
, [TRACKED
],
1207 "add a source pattern to the file path remapping config"),
1208 remap_path_prefix_to
: Vec
<PathBuf
> = (vec
![], parse_pathbuf_push
, [TRACKED
],
1209 "add a mapping target to the file path remapping config"),
1210 force_unstable_if_unmarked
: bool
= (false, parse_bool
, [TRACKED
],
1211 "force all crates to be `rustc_private` unstable"),
1212 pre_link_arg
: Vec
<String
> = (vec
![], parse_string_push
, [UNTRACKED
],
1213 "a single extra argument to prepend the linker invocation (can be used several times)"),
1214 pre_link_args
: Option
<Vec
<String
>> = (None
, parse_opt_list
, [UNTRACKED
],
1215 "extra arguments to prepend to the linker invocation (space separated)"),
1216 profile
: bool
= (false, parse_bool
, [TRACKED
],
1217 "insert profiling code"),
1218 relro_level
: Option
<RelroLevel
> = (None
, parse_relro_level
, [TRACKED
],
1219 "choose which RELRO level to use"),
1220 nll
: bool
= (false, parse_bool
, [UNTRACKED
],
1221 "run the non-lexical lifetimes MIR pass"),
1222 nll_dump_cause
: bool
= (false, parse_bool
, [UNTRACKED
],
1223 "dump cause information when reporting errors from NLL"),
1224 trans_time_graph
: bool
= (false, parse_bool
, [UNTRACKED
],
1225 "generate a graphical HTML report of time spent in trans and LLVM"),
1226 thinlto
: Option
<bool
> = (None
, parse_opt_bool
, [TRACKED
],
1227 "enable ThinLTO when possible"),
1228 inline_in_all_cgus
: Option
<bool
> = (None
, parse_opt_bool
, [TRACKED
],
1229 "control whether #[inline] functions are in all cgus"),
1230 tls_model
: Option
<String
> = (None
, parse_opt_string
, [TRACKED
],
1231 "choose the TLS model to use (rustc --print tls-models for details)"),
1232 saturating_float_casts
: bool
= (false, parse_bool
, [TRACKED
],
1233 "make float->int casts UB-free: numbers outside the integer type's range are clipped to \
1234 the max/min integer respectively, and NaN is mapped to 0"),
1235 lower_128bit_ops
: Option
<bool
> = (None
, parse_opt_bool
, [TRACKED
],
1236 "rewrite operators on i128 and u128 into lang item calls (typically provided \
1237 by compiler-builtins) so translation doesn't need to support them,
1238 overriding the default for the current target"),
1239 human_readable_cgu_names
: bool
= (false, parse_bool
, [TRACKED
],
1240 "generate human-readable, predictable names for codegen units"),
1243 pub fn default_lib_output() -> CrateType
{
1247 pub fn default_configuration(sess
: &Session
) -> ast
::CrateConfig
{
1248 let end
= &sess
.target
.target
.target_endian
;
1249 let arch
= &sess
.target
.target
.arch
;
1250 let wordsz
= &sess
.target
.target
.target_pointer_width
;
1251 let os
= &sess
.target
.target
.target_os
;
1252 let env
= &sess
.target
.target
.target_env
;
1253 let vendor
= &sess
.target
.target
.target_vendor
;
1254 let min_atomic_width
= sess
.target
.target
.min_atomic_width();
1255 let max_atomic_width
= sess
.target
.target
.max_atomic_width();
1257 let mut ret
= HashSet
::new();
1259 ret
.insert((Symbol
::intern("target_os"), Some(Symbol
::intern(os
))));
1260 if let Some(ref fam
) = sess
.target
.target
.options
.target_family
{
1261 ret
.insert((Symbol
::intern("target_family"), Some(Symbol
::intern(fam
))));
1262 if fam
== "windows" || fam
== "unix" {
1263 ret
.insert((Symbol
::intern(fam
), None
));
1266 ret
.insert((Symbol
::intern("target_arch"), Some(Symbol
::intern(arch
))));
1267 ret
.insert((Symbol
::intern("target_endian"), Some(Symbol
::intern(end
))));
1268 ret
.insert((Symbol
::intern("target_pointer_width"), Some(Symbol
::intern(wordsz
))));
1269 ret
.insert((Symbol
::intern("target_env"), Some(Symbol
::intern(env
))));
1270 ret
.insert((Symbol
::intern("target_vendor"), Some(Symbol
::intern(vendor
))));
1271 if sess
.target
.target
.options
.has_elf_tls
{
1272 ret
.insert((Symbol
::intern("target_thread_local"), None
));
1274 for &i
in &[8, 16, 32, 64, 128] {
1275 if i
>= min_atomic_width
&& i
<= max_atomic_width
{
1276 let s
= i
.to_string();
1277 ret
.insert((Symbol
::intern("target_has_atomic"), Some(Symbol
::intern(&s
))));
1279 ret
.insert((Symbol
::intern("target_has_atomic"), Some(Symbol
::intern("ptr"))));
1283 if sess
.opts
.debug_assertions
{
1284 ret
.insert((Symbol
::intern("debug_assertions"), None
));
1286 if sess
.opts
.crate_types
.contains(&CrateTypeProcMacro
) {
1287 ret
.insert((Symbol
::intern("proc_macro"), None
));
1292 pub fn build_configuration(sess
: &Session
,
1293 mut user_cfg
: ast
::CrateConfig
)
1294 -> ast
::CrateConfig
{
1295 // Combine the configuration requested by the session (command line) with
1296 // some default and generated configuration items
1297 let default_cfg
= default_configuration(sess
);
1298 // If the user wants a test runner, then add the test cfg
1300 user_cfg
.insert((Symbol
::intern("test"), None
));
1302 user_cfg
.extend(default_cfg
.iter().cloned());
1306 pub fn build_target_config(opts
: &Options
, sp
: &Handler
) -> Config
{
1307 let target
= match Target
::search(&opts
.target_triple
) {
1310 sp
.struct_fatal(&format
!("Error loading target specification: {}", e
))
1311 .help("Use `--print target-list` for a list of built-in targets")
1317 let (isize_ty
, usize_ty
) = match &target
.target_pointer_width
[..] {
1318 "16" => (ast
::IntTy
::I16
, ast
::UintTy
::U16
),
1319 "32" => (ast
::IntTy
::I32
, ast
::UintTy
::U32
),
1320 "64" => (ast
::IntTy
::I64
, ast
::UintTy
::U64
),
1321 w
=> panic
!(sp
.fatal(&format
!("target specification was invalid: \
1322 unrecognized target-pointer-width {}", w
))),
1332 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
1333 pub enum OptionStability
{
1339 pub struct RustcOptGroup
{
1340 pub apply
: Box
<Fn(&mut getopts
::Options
) -> &mut getopts
::Options
>,
1341 pub name
: &'
static str,
1342 pub stability
: OptionStability
,
1345 impl RustcOptGroup
{
1346 pub fn is_stable(&self) -> bool
{
1347 self.stability
== OptionStability
::Stable
1350 pub fn stable
<F
>(name
: &'
static str, f
: F
) -> RustcOptGroup
1351 where F
: Fn(&mut getopts
::Options
) -> &mut getopts
::Options
+ '
static,
1356 stability
: OptionStability
::Stable
,
1360 pub fn unstable
<F
>(name
: &'
static str, f
: F
) -> RustcOptGroup
1361 where F
: Fn(&mut getopts
::Options
) -> &mut getopts
::Options
+ '
static,
1366 stability
: OptionStability
::Unstable
,
1371 // The `opt` local module holds wrappers around the `getopts` API that
1372 // adds extra rustc-specific metadata to each option; such metadata
1373 // is exposed by . The public
1374 // functions below ending with `_u` are the functions that return
1375 // *unstable* options, i.e. options that are only enabled when the
1376 // user also passes the `-Z unstable-options` debugging flag.
1378 // The `fn opt_u` etc below are written so that we can use them
1379 // in the future; do not warn about them not being used right now.
1380 #![allow(dead_code)]
1383 use super::RustcOptGroup
;
1385 pub type R
= RustcOptGroup
;
1386 pub type S
= &'
static str;
1388 fn stable
<F
>(name
: S
, f
: F
) -> R
1389 where F
: Fn(&mut getopts
::Options
) -> &mut getopts
::Options
+ '
static
1391 RustcOptGroup
::stable(name
, f
)
1394 fn unstable
<F
>(name
: S
, f
: F
) -> R
1395 where F
: Fn(&mut getopts
::Options
) -> &mut getopts
::Options
+ '
static
1397 RustcOptGroup
::unstable(name
, f
)
1400 fn longer(a
: S
, b
: S
) -> S
{
1401 if a
.len() > b
.len() {
1408 pub fn opt_s(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
1409 stable(longer(a
, b
), move |opts
| opts
.optopt(a
, b
, c
, d
))
1411 pub fn multi_s(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
1412 stable(longer(a
, b
), move |opts
| opts
.optmulti(a
, b
, c
, d
))
1414 pub fn flag_s(a
: S
, b
: S
, c
: S
) -> R
{
1415 stable(longer(a
, b
), move |opts
| opts
.optflag(a
, b
, c
))
1417 pub fn flagopt_s(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
1418 stable(longer(a
, b
), move |opts
| opts
.optflagopt(a
, b
, c
, d
))
1420 pub fn flagmulti_s(a
: S
, b
: S
, c
: S
) -> R
{
1421 stable(longer(a
, b
), move |opts
| opts
.optflagmulti(a
, b
, c
))
1424 pub fn opt(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
1425 unstable(longer(a
, b
), move |opts
| opts
.optopt(a
, b
, c
, d
))
1427 pub fn multi(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
1428 unstable(longer(a
, b
), move |opts
| opts
.optmulti(a
, b
, c
, d
))
1430 pub fn flag(a
: S
, b
: S
, c
: S
) -> R
{
1431 unstable(longer(a
, b
), move |opts
| opts
.optflag(a
, b
, c
))
1433 pub fn flagopt(a
: S
, b
: S
, c
: S
, d
: S
) -> R
{
1434 unstable(longer(a
, b
), move |opts
| opts
.optflagopt(a
, b
, c
, d
))
1436 pub fn flagmulti(a
: S
, b
: S
, c
: S
) -> R
{
1437 unstable(longer(a
, b
), move |opts
| opts
.optflagmulti(a
, b
, c
))
1441 /// Returns the "short" subset of the rustc command line options,
1442 /// including metadata for each option, such as whether the option is
1443 /// part of the stable long-term interface for rustc.
1444 pub fn rustc_short_optgroups() -> Vec
<RustcOptGroup
> {
1446 opt
::flag_s("h", "help", "Display this message"),
1447 opt
::multi_s("", "cfg", "Configure the compilation environment", "SPEC"),
1448 opt
::multi_s("L", "", "Add a directory to the library search path. The
1449 optional KIND can be one of dependency, crate, native,
1450 framework or all (the default).", "[KIND=]PATH"),
1451 opt
::multi_s("l", "", "Link the generated crate(s) to the specified native
1452 library NAME. The optional KIND can be one of
1453 static, dylib, or framework. If omitted, dylib is
1454 assumed.", "[KIND=]NAME"),
1455 opt
::multi_s("", "crate-type", "Comma separated list of types of crates
1456 for the compiler to emit",
1457 "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]"),
1458 opt
::opt_s("", "crate-name", "Specify the name of the crate being built",
1460 opt
::multi_s("", "emit", "Comma separated list of types of output for \
1461 the compiler to emit",
1462 "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]"),
1463 opt
::multi_s("", "print", "Comma separated list of compiler information to \
1465 "[crate-name|file-names|sysroot|cfg|target-list|\
1466 target-cpus|target-features|relocation-models|\
1467 code-models|tls-models|target-spec-json|native-static-libs]"),
1468 opt
::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"),
1469 opt
::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
1470 opt
::opt_s("o", "", "Write output to <filename>", "FILENAME"),
1471 opt
::opt_s("", "out-dir", "Write output to compiler-chosen filename \
1473 opt
::opt_s("", "explain", "Provide a detailed explanation of an error \
1475 opt
::flag_s("", "test", "Build a test harness"),
1476 opt
::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"),
1477 opt
::multi_s("W", "warn", "Set lint warnings", "OPT"),
1478 opt
::multi_s("A", "allow", "Set lint allowed", "OPT"),
1479 opt
::multi_s("D", "deny", "Set lint denied", "OPT"),
1480 opt
::multi_s("F", "forbid", "Set lint forbidden", "OPT"),
1481 opt
::multi_s("", "cap-lints", "Set the most restrictive lint level. \
1482 More restrictive lints are capped at this \
1484 opt
::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
1485 opt
::flag_s("V", "version", "Print version info and exit"),
1486 opt
::flag_s("v", "verbose", "Use verbose output"),
1490 /// Returns all rustc command line options, including metadata for
1491 /// each option, such as whether the option is part of the stable
1492 /// long-term interface for rustc.
1493 pub fn rustc_optgroups() -> Vec
<RustcOptGroup
> {
1494 let mut opts
= rustc_short_optgroups();
1496 opt
::multi_s("", "extern", "Specify where an external rust library is located",
1498 opt
::opt_s("", "sysroot", "Override the system root", "PATH"),
1499 opt
::multi("Z", "", "Set internal debugging options", "FLAG"),
1500 opt
::opt_s("", "error-format",
1501 "How errors and other messages are produced",
1502 "human|json|short"),
1503 opt
::opt_s("", "color", "Configure coloring of output:
1504 auto = colorize, if output goes to a tty (default);
1505 always = always colorize output;
1506 never = never colorize output", "auto|always|never"),
1508 opt
::opt("", "pretty",
1509 "Pretty-print the input instead of compiling;
1510 valid types are: `normal` (un-annotated source),
1511 `expanded` (crates expanded), or
1512 `expanded,identified` (fully parenthesized, AST nodes with IDs).",
1514 opt
::opt("", "unpretty",
1515 "Present the input source, unstable (and less-pretty) variants;
1516 valid types are any of the types for `--pretty`, as well as:
1517 `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
1518 `everybody_loops` (all function bodies replaced with `loop {}`),
1519 `hir` (the HIR), `hir,identified`, or
1520 `hir,typed` (HIR with types for each node).",
1526 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
1527 pub fn parse_cfgspecs(cfgspecs
: Vec
<String
> ) -> ast
::CrateConfig
{
1528 cfgspecs
.into_iter().map(|s
| {
1529 let sess
= parse
::ParseSess
::new(FilePathMapping
::empty());
1531 parse
::new_parser_from_source_str(&sess
, FileName
::CfgSpec
, s
.to_string());
1533 let meta_item
= panictry
!(parser
.parse_meta_item());
1535 if parser
.token
!= token
::Eof
{
1536 early_error(ErrorOutputType
::default(), &format
!("invalid --cfg argument: {}", s
))
1537 } else if meta_item
.is_meta_item_list() {
1539 format
!("invalid predicate in --cfg command line argument: `{}`", meta_item
.name());
1540 early_error(ErrorOutputType
::default(), &msg
)
1543 (meta_item
.name(), meta_item
.value_str())
1544 }).collect
::<ast
::CrateConfig
>()
1547 pub fn build_session_options_and_crate_config(matches
: &getopts
::Matches
)
1548 -> (Options
, ast
::CrateConfig
) {
1549 let color
= match matches
.opt_str("color").as_ref().map(|s
| &s
[..]) {
1550 Some("auto") => ColorConfig
::Auto
,
1551 Some("always") => ColorConfig
::Always
,
1552 Some("never") => ColorConfig
::Never
,
1554 None
=> ColorConfig
::Auto
,
1557 early_error(ErrorOutputType
::default(), &format
!("argument for --color must be auto, \
1558 always or never (instead was `{}`)",
1563 // We need the opts_present check because the driver will send us Matches
1564 // with only stable options if no unstable options are used. Since error-format
1565 // is unstable, it will not be present. We have to use opts_present not
1566 // opt_present because the latter will panic.
1567 let error_format
= if matches
.opts_present(&["error-format".to_owned()]) {
1568 match matches
.opt_str("error-format").as_ref().map(|s
| &s
[..]) {
1569 Some("human") => ErrorOutputType
::HumanReadable(color
),
1570 Some("json") => ErrorOutputType
::Json(false),
1571 Some("pretty-json") => ErrorOutputType
::Json(true),
1573 if nightly_options
::is_unstable_enabled(matches
) {
1574 ErrorOutputType
::Short(color
)
1576 early_error(ErrorOutputType
::default(),
1577 &format
!("the `-Z unstable-options` flag must also be passed to \
1578 enable the short error message option"));
1581 None
=> ErrorOutputType
::HumanReadable(color
),
1584 early_error(ErrorOutputType
::HumanReadable(color
),
1585 &format
!("argument for --error-format must be `human`, `json` or \
1586 `short` (instead was `{}`)",
1591 ErrorOutputType
::HumanReadable(color
)
1594 let unparsed_crate_types
= matches
.opt_strs("crate-type");
1595 let crate_types
= parse_crate_types_from_list(unparsed_crate_types
)
1596 .unwrap_or_else(|e
| early_error(error_format
, &e
[..]));
1598 let mut lint_opts
= vec
![];
1599 let mut describe_lints
= false;
1601 for &level
in &[lint
::Allow
, lint
::Warn
, lint
::Deny
, lint
::Forbid
] {
1602 for lint_name
in matches
.opt_strs(level
.as_str()) {
1603 if lint_name
== "help" {
1604 describe_lints
= true;
1606 lint_opts
.push((lint_name
.replace("-", "_"), level
));
1611 let lint_cap
= matches
.opt_str("cap-lints").map(|cap
| {
1612 lint
::Level
::from_str(&cap
).unwrap_or_else(|| {
1613 early_error(error_format
, &format
!("unknown lint level: `{}`", cap
))
1617 let mut debugging_opts
= build_debugging_options(matches
, error_format
);
1619 if !debugging_opts
.unstable_options
&& error_format
== ErrorOutputType
::Json(true) {
1620 early_error(ErrorOutputType
::Json(false),
1621 "--error-format=pretty-json is unstable");
1624 let mut output_types
= BTreeMap
::new();
1625 if !debugging_opts
.parse_only
{
1626 for list
in matches
.opt_strs("emit") {
1627 for output_type
in list
.split('
,'
) {
1628 let mut parts
= output_type
.splitn(2, '
='
);
1629 let shorthand
= parts
.next().unwrap();
1630 let output_type
= match OutputType
::from_shorthand(shorthand
) {
1631 Some(output_type
) => output_type
,
1632 None
=> early_error(error_format
, &format
!(
1633 "unknown emission type: `{}` - expected one of: {}",
1634 shorthand
, OutputType
::shorthands_display(),
1637 let path
= parts
.next().map(PathBuf
::from
);
1638 output_types
.insert(output_type
, path
);
1642 if output_types
.is_empty() {
1643 output_types
.insert(OutputType
::Exe
, None
);
1646 let remap_path_prefix_sources
= debugging_opts
.remap_path_prefix_from
.len();
1647 let remap_path_prefix_targets
= debugging_opts
.remap_path_prefix_from
.len();
1649 if remap_path_prefix_targets
< remap_path_prefix_sources
{
1650 for source
in &debugging_opts
.remap_path_prefix_from
[remap_path_prefix_targets
..] {
1651 early_error(error_format
,
1652 &format
!("option `-Zremap-path-prefix-from='{}'` does not have \
1653 a corresponding `-Zremap-path-prefix-to`", source
.display()))
1655 } else if remap_path_prefix_targets
> remap_path_prefix_sources
{
1656 for target
in &debugging_opts
.remap_path_prefix_to
[remap_path_prefix_sources
..] {
1657 early_error(error_format
,
1658 &format
!("option `-Zremap-path-prefix-to='{}'` does not have \
1659 a corresponding `-Zremap-path-prefix-from`", target
.display()))
1663 let mut cg
= build_codegen_options(matches
, error_format
);
1664 let mut codegen_units
= cg
.codegen_units
;
1665 let mut thinlto
= None
;
1667 // Issue #30063: if user requests llvm-related output to one
1668 // particular path, disable codegen-units.
1669 let incompatible
: Vec
<_
> = output_types
.iter()
1670 .map(|ot_path
| ot_path
.0)
1672 !ot
.is_compatible_with_codegen_units_and_single_output_file()
1674 .map(|ot
| ot
.shorthand())
1676 if !incompatible
.is_empty() {
1677 match codegen_units
{
1678 Some(n
) if n
> 1 => {
1679 if matches
.opt_present("o") {
1680 for ot
in &incompatible
{
1681 early_warn(error_format
, &format
!("--emit={} with -o incompatible with \
1682 -C codegen-units=N for N > 1",
1685 early_warn(error_format
, "resetting to default -C codegen-units=1");
1686 codegen_units
= Some(1);
1687 thinlto
= Some(false);
1691 codegen_units
= Some(1);
1692 thinlto
= Some(false);
1697 if debugging_opts
.query_threads
== Some(0) {
1698 early_error(error_format
, "Value for query threads must be a positive nonzero integer");
1701 if codegen_units
== Some(0) {
1702 early_error(error_format
, "Value for codegen units must be a positive nonzero integer");
1705 let incremental
= match (&debugging_opts
.incremental
, &cg
.incremental
) {
1706 (&Some(ref path1
), &Some(ref path2
)) => {
1708 early_error(error_format
,
1709 &format
!("conflicting paths for `-Z incremental` and \
1710 `-C incremental` specified: {} versus {}",
1717 (&Some(ref path
), &None
) => Some(path
),
1718 (&None
, &Some(ref path
)) => Some(path
),
1719 (&None
, &None
) => None
,
1720 }.map(|m
| PathBuf
::from(m
));
1722 if cg
.lto
&& incremental
.is_some() {
1723 early_error(error_format
, "can't perform LTO when compiling incrementally");
1726 let mut prints
= Vec
::<PrintRequest
>::new();
1727 if cg
.target_cpu
.as_ref().map_or(false, |s
| s
== "help") {
1728 prints
.push(PrintRequest
::TargetCPUs
);
1729 cg
.target_cpu
= None
;
1731 if cg
.target_feature
== "help" {
1732 prints
.push(PrintRequest
::TargetFeatures
);
1733 cg
.target_feature
= "".to_string();
1735 if cg
.relocation_model
.as_ref().map_or(false, |s
| s
== "help") {
1736 prints
.push(PrintRequest
::RelocationModels
);
1737 cg
.relocation_model
= None
;
1739 if cg
.code_model
.as_ref().map_or(false, |s
| s
== "help") {
1740 prints
.push(PrintRequest
::CodeModels
);
1741 cg
.code_model
= None
;
1743 if debugging_opts
.tls_model
.as_ref().map_or(false, |s
| s
== "help") {
1744 prints
.push(PrintRequest
::TlsModels
);
1745 debugging_opts
.tls_model
= None
;
1750 let sysroot_opt
= matches
.opt_str("sysroot").map(|m
| PathBuf
::from(&m
));
1751 let target
= matches
.opt_str("target").unwrap_or(
1752 host_triple().to_string());
1754 if matches
.opt_present("O") {
1755 if cg
.opt_level
.is_some() {
1756 early_error(error_format
, "-O and -C opt-level both provided");
1760 match (cg
.opt_level
.as_ref().map(String
::as_ref
),
1761 nightly_options
::is_nightly_build()) {
1762 (None
, _
) => OptLevel
::No
,
1763 (Some("0"), _
) => OptLevel
::No
,
1764 (Some("1"), _
) => OptLevel
::Less
,
1765 (Some("2"), _
) => OptLevel
::Default
,
1766 (Some("3"), _
) => OptLevel
::Aggressive
,
1767 (Some("s"), true) => OptLevel
::Size
,
1768 (Some("z"), true) => OptLevel
::SizeMin
,
1769 (Some("s"), false) | (Some("z"), false) => {
1770 early_error(error_format
, &format
!("the optimizations s or z are only \
1771 accepted on the nightly compiler"));
1774 early_error(error_format
, &format
!("optimization level needs to be \
1775 between 0-3 (instead was `{}`)",
1781 let debug_assertions
= cg
.debug_assertions
.unwrap_or(opt_level
== OptLevel
::No
);
1782 let debuginfo
= if matches
.opt_present("g") {
1783 if cg
.debuginfo
.is_some() {
1784 early_error(error_format
, "-g and -C debuginfo both provided");
1788 match cg
.debuginfo
{
1789 None
| Some(0) => NoDebugInfo
,
1790 Some(1) => LimitedDebugInfo
,
1791 Some(2) => FullDebugInfo
,
1793 early_error(error_format
, &format
!("debug info level needs to be between \
1794 0-2 (instead was `{}`)",
1800 let mut search_paths
= SearchPaths
::new();
1801 for s
in &matches
.opt_strs("L") {
1802 search_paths
.add_path(&s
[..], error_format
);
1805 let libs
= matches
.opt_strs("l").into_iter().map(|s
| {
1806 // Parse string of the form "[KIND=]lib[:new_name]",
1807 // where KIND is one of "dylib", "framework", "static".
1808 let mut parts
= s
.splitn(2, '
='
);
1809 let kind
= parts
.next().unwrap();
1810 let (name
, kind
) = match (parts
.next(), kind
) {
1811 (None
, name
) => (name
, None
),
1812 (Some(name
), "dylib") => (name
, Some(cstore
::NativeUnknown
)),
1813 (Some(name
), "framework") => (name
, Some(cstore
::NativeFramework
)),
1814 (Some(name
), "static") => (name
, Some(cstore
::NativeStatic
)),
1815 (Some(name
), "static-nobundle") => (name
, Some(cstore
::NativeStaticNobundle
)),
1817 early_error(error_format
, &format
!("unknown library kind `{}`, expected \
1818 one of dylib, framework, or static",
1822 if kind
== Some(cstore
::NativeStaticNobundle
) && !nightly_options
::is_nightly_build() {
1823 early_error(error_format
, &format
!("the library kind 'static-nobundle' is only \
1824 accepted on the nightly compiler"));
1826 let mut name_parts
= name
.splitn(2, '
:'
);
1827 let name
= name_parts
.next().unwrap();
1828 let new_name
= name_parts
.next();
1829 (name
.to_string(), new_name
.map(|n
| n
.to_string()), kind
)
1832 let cfg
= parse_cfgspecs(matches
.opt_strs("cfg"));
1833 let test
= matches
.opt_present("test");
1835 prints
.extend(matches
.opt_strs("print").into_iter().map(|s
| {
1837 "crate-name" => PrintRequest
::CrateName
,
1838 "file-names" => PrintRequest
::FileNames
,
1839 "sysroot" => PrintRequest
::Sysroot
,
1840 "cfg" => PrintRequest
::Cfg
,
1841 "target-list" => PrintRequest
::TargetList
,
1842 "target-cpus" => PrintRequest
::TargetCPUs
,
1843 "target-features" => PrintRequest
::TargetFeatures
,
1844 "relocation-models" => PrintRequest
::RelocationModels
,
1845 "code-models" => PrintRequest
::CodeModels
,
1846 "tls-models" => PrintRequest
::TlsModels
,
1847 "native-static-libs" => PrintRequest
::NativeStaticLibs
,
1848 "target-spec-json" => {
1849 if nightly_options
::is_unstable_enabled(matches
) {
1850 PrintRequest
::TargetSpec
1852 early_error(error_format
,
1853 &format
!("the `-Z unstable-options` flag must also be passed to \
1854 enable the target-spec-json print option"));
1858 early_error(error_format
, &format
!("unknown print request `{}`", req
))
1863 let borrowck_mode
= match debugging_opts
.borrowck
.as_ref().map(|s
| &s
[..]) {
1864 None
| Some("ast") => BorrowckMode
::Ast
,
1865 Some("mir") => BorrowckMode
::Mir
,
1866 Some("compare") => BorrowckMode
::Compare
,
1868 early_error(error_format
, &format
!("unknown borrowck mode `{}`", m
))
1872 if !cg
.remark
.is_empty() && debuginfo
== NoDebugInfo
{
1873 early_warn(error_format
, "-C remark will not show source locations without \
1877 let mut externs
= BTreeMap
::new();
1878 for arg
in &matches
.opt_strs("extern") {
1879 let mut parts
= arg
.splitn(2, '
='
);
1880 let name
= match parts
.next() {
1882 None
=> early_error(error_format
, "--extern value must not be empty"),
1884 let location
= match parts
.next() {
1886 None
=> early_error(error_format
, "--extern value must be of the format `foo=bar`"),
1889 externs
.entry(name
.to_string())
1890 .or_insert_with(BTreeSet
::new
)
1891 .insert(location
.to_string());
1894 let crate_name
= matches
.opt_str("crate-name");
1898 optimize
: opt_level
,
1903 output_types
: OutputTypes(output_types
),
1905 maybe_sysroot
: sysroot_opt
,
1906 target_triple
: target
,
1914 externs
: Externs(externs
),
1918 unstable_features
: UnstableFeatures
::from_environment(),
1920 actually_rustdoc
: false,
1921 cli_forced_codegen_units
: codegen_units
,
1922 cli_forced_thinlto
: thinlto
,
1927 pub fn parse_crate_types_from_list(list_list
: Vec
<String
>)
1928 -> Result
<Vec
<CrateType
>, String
> {
1929 let mut crate_types
: Vec
<CrateType
> = Vec
::new();
1930 for unparsed_crate_type
in &list_list
{
1931 for part
in unparsed_crate_type
.split('
,'
) {
1932 let new_part
= match part
{
1933 "lib" => default_lib_output(),
1934 "rlib" => CrateTypeRlib
,
1935 "staticlib" => CrateTypeStaticlib
,
1936 "dylib" => CrateTypeDylib
,
1937 "cdylib" => CrateTypeCdylib
,
1938 "bin" => CrateTypeExecutable
,
1939 "proc-macro" => CrateTypeProcMacro
,
1941 return Err(format
!("unknown crate type: `{}`",
1945 if !crate_types
.contains(&new_part
) {
1946 crate_types
.push(new_part
)
1954 pub mod nightly_options
{
1956 use syntax
::feature_gate
::UnstableFeatures
;
1957 use super::{ErrorOutputType, OptionStability, RustcOptGroup}
;
1958 use session
::early_error
;
1960 pub fn is_unstable_enabled(matches
: &getopts
::Matches
) -> bool
{
1961 is_nightly_build() && matches
.opt_strs("Z").iter().any(|x
| *x
== "unstable-options")
1964 pub fn is_nightly_build() -> bool
{
1965 UnstableFeatures
::from_environment().is_nightly_build()
1968 pub fn check_nightly_options(matches
: &getopts
::Matches
, flags
: &[RustcOptGroup
]) {
1969 let has_z_unstable_option
= matches
.opt_strs("Z").iter().any(|x
| *x
== "unstable-options");
1970 let really_allows_unstable_options
= UnstableFeatures
::from_environment()
1971 .is_nightly_build();
1973 for opt
in flags
.iter() {
1974 if opt
.stability
== OptionStability
::Stable
{
1977 if !matches
.opt_present(opt
.name
) {
1980 if opt
.name
!= "Z" && !has_z_unstable_option
{
1981 early_error(ErrorOutputType
::default(),
1982 &format
!("the `-Z unstable-options` flag must also be passed to enable \
1986 if really_allows_unstable_options
{
1989 match opt
.stability
{
1990 OptionStability
::Unstable
=> {
1991 let msg
= format
!("the option `{}` is only accepted on the \
1992 nightly compiler", opt
.name
);
1993 early_error(ErrorOutputType
::default(), &msg
);
1995 OptionStability
::Stable
=> {}
2001 impl fmt
::Display
for CrateType
{
2002 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
2004 CrateTypeExecutable
=> "bin".fmt(f
),
2005 CrateTypeDylib
=> "dylib".fmt(f
),
2006 CrateTypeRlib
=> "rlib".fmt(f
),
2007 CrateTypeStaticlib
=> "staticlib".fmt(f
),
2008 CrateTypeCdylib
=> "cdylib".fmt(f
),
2009 CrateTypeProcMacro
=> "proc-macro".fmt(f
),
2014 /// Commandline arguments passed to the compiler have to be incorporated with
2015 /// the dependency tracking system for incremental compilation. This module
2016 /// provides some utilities to make this more convenient.
2018 /// The values of all commandline arguments that are relevant for dependency
2019 /// tracking are hashed into a single value that determines whether the
2020 /// incremental compilation cache can be re-used or not. This hashing is done
2021 /// via the DepTrackingHash trait defined below, since the standard Hash
2022 /// implementation might not be suitable (e.g. arguments are stored in a Vec,
2023 /// the hash of which is order dependent, but we might not want the order of
2024 /// arguments to make a difference for the hash).
2026 /// However, since the value provided by Hash::hash often *is* suitable,
2027 /// especially for primitive types, there is the
2028 /// impl_dep_tracking_hash_via_hash!() macro that allows to simply reuse the
2029 /// Hash implementation for DepTrackingHash. It's important though that
2030 /// we have an opt-in scheme here, so one is hopefully forced to think about
2031 /// how the hash should be calculated when adding a new commandline argument.
2035 use session
::search_paths
::{PathKind, SearchPaths}
;
2036 use std
::collections
::BTreeMap
;
2037 use std
::hash
::Hash
;
2038 use std
::path
::PathBuf
;
2039 use std
::collections
::hash_map
::DefaultHasher
;
2040 use super::{Passes
, CrateType
, OptLevel
, DebugInfoLevel
,
2041 OutputTypes
, Externs
, ErrorOutputType
, Sanitizer
};
2042 use syntax
::feature_gate
::UnstableFeatures
;
2043 use rustc_back
::{PanicStrategy, RelroLevel}
;
2045 pub trait DepTrackingHash
{
2046 fn hash(&self, hasher
: &mut DefaultHasher
, error_format
: ErrorOutputType
);
2049 macro_rules
! impl_dep_tracking_hash_via_hash
{
2051 impl DepTrackingHash
for $t
{
2052 fn hash(&self, hasher
: &mut DefaultHasher
, _
: ErrorOutputType
) {
2053 Hash
::hash(self, hasher
);
2059 macro_rules
! impl_dep_tracking_hash_for_sortable_vec_of
{
2061 impl DepTrackingHash
for Vec
<$t
> {
2062 fn hash(&self, hasher
: &mut DefaultHasher
, error_format
: ErrorOutputType
) {
2063 let mut elems
: Vec
<&$t
> = self.iter().collect();
2065 Hash
::hash(&elems
.len(), hasher
);
2066 for (index
, elem
) in elems
.iter().enumerate() {
2067 Hash
::hash(&index
, hasher
);
2068 DepTrackingHash
::hash(*elem
, hasher
, error_format
);
2075 impl_dep_tracking_hash_via_hash
!(bool
);
2076 impl_dep_tracking_hash_via_hash
!(usize);
2077 impl_dep_tracking_hash_via_hash
!(u64);
2078 impl_dep_tracking_hash_via_hash
!(String
);
2079 impl_dep_tracking_hash_via_hash
!(PathBuf
);
2080 impl_dep_tracking_hash_via_hash
!(lint
::Level
);
2081 impl_dep_tracking_hash_via_hash
!(Option
<bool
>);
2082 impl_dep_tracking_hash_via_hash
!(Option
<usize>);
2083 impl_dep_tracking_hash_via_hash
!(Option
<String
>);
2084 impl_dep_tracking_hash_via_hash
!(Option
<(String
, u64)>);
2085 impl_dep_tracking_hash_via_hash
!(Option
<PanicStrategy
>);
2086 impl_dep_tracking_hash_via_hash
!(Option
<RelroLevel
>);
2087 impl_dep_tracking_hash_via_hash
!(Option
<lint
::Level
>);
2088 impl_dep_tracking_hash_via_hash
!(Option
<PathBuf
>);
2089 impl_dep_tracking_hash_via_hash
!(Option
<cstore
::NativeLibraryKind
>);
2090 impl_dep_tracking_hash_via_hash
!(CrateType
);
2091 impl_dep_tracking_hash_via_hash
!(PanicStrategy
);
2092 impl_dep_tracking_hash_via_hash
!(RelroLevel
);
2093 impl_dep_tracking_hash_via_hash
!(Passes
);
2094 impl_dep_tracking_hash_via_hash
!(OptLevel
);
2095 impl_dep_tracking_hash_via_hash
!(DebugInfoLevel
);
2096 impl_dep_tracking_hash_via_hash
!(UnstableFeatures
);
2097 impl_dep_tracking_hash_via_hash
!(Externs
);
2098 impl_dep_tracking_hash_via_hash
!(OutputTypes
);
2099 impl_dep_tracking_hash_via_hash
!(cstore
::NativeLibraryKind
);
2100 impl_dep_tracking_hash_via_hash
!(Sanitizer
);
2101 impl_dep_tracking_hash_via_hash
!(Option
<Sanitizer
>);
2103 impl_dep_tracking_hash_for_sortable_vec_of
!(String
);
2104 impl_dep_tracking_hash_for_sortable_vec_of
!(PathBuf
);
2105 impl_dep_tracking_hash_for_sortable_vec_of
!(CrateType
);
2106 impl_dep_tracking_hash_for_sortable_vec_of
!((String
, lint
::Level
));
2107 impl_dep_tracking_hash_for_sortable_vec_of
!((String
, Option
<String
>,
2108 Option
<cstore
::NativeLibraryKind
>));
2109 impl_dep_tracking_hash_for_sortable_vec_of
!((String
, u64));
2110 impl DepTrackingHash
for SearchPaths
{
2111 fn hash(&self, hasher
: &mut DefaultHasher
, _
: ErrorOutputType
) {
2112 let mut elems
: Vec
<_
> = self
2113 .iter(PathKind
::All
)
2116 Hash
::hash(&elems
, hasher
);
2120 impl<T1
, T2
> DepTrackingHash
for (T1
, T2
)
2121 where T1
: DepTrackingHash
,
2124 fn hash(&self, hasher
: &mut DefaultHasher
, error_format
: ErrorOutputType
) {
2125 Hash
::hash(&0, hasher
);
2126 DepTrackingHash
::hash(&self.0, hasher
, error_format
);
2127 Hash
::hash(&1, hasher
);
2128 DepTrackingHash
::hash(&self.1, hasher
, error_format
);
2132 impl<T1
, T2
, T3
> DepTrackingHash
for (T1
, T2
, T3
)
2133 where T1
: DepTrackingHash
,
2134 T2
: DepTrackingHash
,
2137 fn hash(&self, hasher
: &mut DefaultHasher
, error_format
: ErrorOutputType
) {
2138 Hash
::hash(&0, hasher
);
2139 DepTrackingHash
::hash(&self.0, hasher
, error_format
);
2140 Hash
::hash(&1, hasher
);
2141 DepTrackingHash
::hash(&self.1, hasher
, error_format
);
2142 Hash
::hash(&2, hasher
);
2143 DepTrackingHash
::hash(&self.2, hasher
, error_format
);
2147 // This is a stable hash because BTreeMap is a sorted container
2148 pub fn stable_hash(sub_hashes
: BTreeMap
<&'
static str, &DepTrackingHash
>,
2149 hasher
: &mut DefaultHasher
,
2150 error_format
: ErrorOutputType
) {
2151 for (key
, sub_hash
) in sub_hashes
{
2152 // Using Hash::hash() instead of DepTrackingHash::hash() is fine for
2153 // the keys, as they are just plain strings
2154 Hash
::hash(&key
.len(), hasher
);
2155 Hash
::hash(key
, hasher
);
2156 sub_hash
.hash(hasher
, error_format
);
2167 use session
::config
::{build_configuration, build_session_options_and_crate_config}
;
2168 use session
::build_session
;
2169 use std
::collections
::{BTreeMap, BTreeSet}
;
2170 use std
::iter
::FromIterator
;
2171 use std
::path
::PathBuf
;
2172 use super::{OutputType, OutputTypes, Externs}
;
2173 use rustc_back
::{PanicStrategy, RelroLevel}
;
2174 use syntax
::symbol
::Symbol
;
2176 fn optgroups() -> getopts
::Options
{
2177 let mut opts
= getopts
::Options
::new();
2178 for group
in super::rustc_optgroups() {
2179 (group
.apply
)(&mut opts
);
2184 fn mk_map
<K
: Ord
, V
>(entries
: Vec
<(K
, V
)>) -> BTreeMap
<K
, V
> {
2185 BTreeMap
::from_iter(entries
.into_iter())
2188 fn mk_set
<V
: Ord
>(entries
: Vec
<V
>) -> BTreeSet
<V
> {
2189 BTreeSet
::from_iter(entries
.into_iter())
2192 // When the user supplies --test we should implicitly supply --cfg test
2194 fn test_switch_implies_cfg_test() {
2196 &match optgroups().parse(&["--test".to_string()]) {
2198 Err(f
) => panic
!("test_switch_implies_cfg_test: {}", f
)
2200 let registry
= errors
::registry
::Registry
::new(&[]);
2201 let (sessopts
, cfg
) = build_session_options_and_crate_config(matches
);
2202 let sess
= build_session(sessopts
, None
, registry
);
2203 let cfg
= build_configuration(&sess
, cfg
);
2204 assert
!(cfg
.contains(&(Symbol
::intern("test"), None
)));
2207 // When the user supplies --test and --cfg test, don't implicitly add
2208 // another --cfg test
2210 fn test_switch_implies_cfg_test_unless_cfg_test() {
2212 &match optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]) {
2215 panic
!("test_switch_implies_cfg_test_unless_cfg_test: {}", f
)
2218 let registry
= errors
::registry
::Registry
::new(&[]);
2219 let (sessopts
, cfg
) = build_session_options_and_crate_config(matches
);
2220 let sess
= build_session(sessopts
, None
, registry
);
2221 let cfg
= build_configuration(&sess
, cfg
);
2222 let mut test_items
= cfg
.iter().filter(|&&(name
, _
)| name
== "test");
2223 assert
!(test_items
.next().is_some());
2224 assert
!(test_items
.next().is_none());
2228 fn test_can_print_warnings() {
2230 let matches
= optgroups().parse(&[
2231 "-Awarnings".to_string()
2233 let registry
= errors
::registry
::Registry
::new(&[]);
2234 let (sessopts
, _
) = build_session_options_and_crate_config(&matches
);
2235 let sess
= build_session(sessopts
, None
, registry
);
2236 assert
!(!sess
.diagnostic().flags
.can_emit_warnings
);
2240 let matches
= optgroups().parse(&[
2241 "-Awarnings".to_string(),
2242 "-Dwarnings".to_string()
2244 let registry
= errors
::registry
::Registry
::new(&[]);
2245 let (sessopts
, _
) = build_session_options_and_crate_config(&matches
);
2246 let sess
= build_session(sessopts
, None
, registry
);
2247 assert
!(sess
.diagnostic().flags
.can_emit_warnings
);
2251 let matches
= optgroups().parse(&[
2252 "-Adead_code".to_string()
2254 let registry
= errors
::registry
::Registry
::new(&[]);
2255 let (sessopts
, _
) = build_session_options_and_crate_config(&matches
);
2256 let sess
= build_session(sessopts
, None
, registry
);
2257 assert
!(sess
.diagnostic().flags
.can_emit_warnings
);
2262 fn test_output_types_tracking_hash_different_paths() {
2263 let mut v1
= super::basic_options();
2264 let mut v2
= super::basic_options();
2265 let mut v3
= super::basic_options();
2267 v1
.output_types
= OutputTypes
::new(&[(OutputType
::Exe
,
2268 Some(PathBuf
::from("./some/thing")))]);
2269 v2
.output_types
= OutputTypes
::new(&[(OutputType
::Exe
,
2270 Some(PathBuf
::from("/some/thing")))]);
2271 v3
.output_types
= OutputTypes
::new(&[(OutputType
::Exe
, None
)]);
2273 assert
!(v1
.dep_tracking_hash() != v2
.dep_tracking_hash());
2274 assert
!(v1
.dep_tracking_hash() != v3
.dep_tracking_hash());
2275 assert
!(v2
.dep_tracking_hash() != v3
.dep_tracking_hash());
2278 assert_eq
!(v1
.dep_tracking_hash(), v1
.clone().dep_tracking_hash());
2279 assert_eq
!(v2
.dep_tracking_hash(), v2
.clone().dep_tracking_hash());
2280 assert_eq
!(v3
.dep_tracking_hash(), v3
.clone().dep_tracking_hash());
2284 fn test_output_types_tracking_hash_different_construction_order() {
2285 let mut v1
= super::basic_options();
2286 let mut v2
= super::basic_options();
2288 v1
.output_types
= OutputTypes
::new(&[
2289 (OutputType
::Exe
, Some(PathBuf
::from("./some/thing"))),
2290 (OutputType
::Bitcode
, Some(PathBuf
::from("./some/thing.bc"))),
2293 v2
.output_types
= OutputTypes
::new(&[
2294 (OutputType
::Bitcode
, Some(PathBuf
::from("./some/thing.bc"))),
2295 (OutputType
::Exe
, Some(PathBuf
::from("./some/thing"))),
2298 assert_eq
!(v1
.dep_tracking_hash(), v2
.dep_tracking_hash());
2301 assert_eq
!(v1
.dep_tracking_hash(), v1
.clone().dep_tracking_hash());
2305 fn test_externs_tracking_hash_different_values() {
2306 let mut v1
= super::basic_options();
2307 let mut v2
= super::basic_options();
2308 let mut v3
= super::basic_options();
2310 v1
.externs
= Externs
::new(mk_map(vec
![
2311 (String
::from("a"), mk_set(vec
![String
::from("b"),
2312 String
::from("c")])),
2313 (String
::from("d"), mk_set(vec
![String
::from("e"),
2314 String
::from("f")])),
2317 v2
.externs
= Externs
::new(mk_map(vec
![
2318 (String
::from("a"), mk_set(vec
![String
::from("b"),
2319 String
::from("c")])),
2320 (String
::from("X"), mk_set(vec
![String
::from("e"),
2321 String
::from("f")])),
2324 v3
.externs
= Externs
::new(mk_map(vec
![
2325 (String
::from("a"), mk_set(vec
![String
::from("b"),
2326 String
::from("c")])),
2327 (String
::from("d"), mk_set(vec
![String
::from("X"),
2328 String
::from("f")])),
2331 assert
!(v1
.dep_tracking_hash() != v2
.dep_tracking_hash());
2332 assert
!(v1
.dep_tracking_hash() != v3
.dep_tracking_hash());
2333 assert
!(v2
.dep_tracking_hash() != v3
.dep_tracking_hash());
2336 assert_eq
!(v1
.dep_tracking_hash(), v1
.clone().dep_tracking_hash());
2337 assert_eq
!(v2
.dep_tracking_hash(), v2
.clone().dep_tracking_hash());
2338 assert_eq
!(v3
.dep_tracking_hash(), v3
.clone().dep_tracking_hash());
2342 fn test_externs_tracking_hash_different_construction_order() {
2343 let mut v1
= super::basic_options();
2344 let mut v2
= super::basic_options();
2345 let mut v3
= super::basic_options();
2347 v1
.externs
= Externs
::new(mk_map(vec
![
2348 (String
::from("a"), mk_set(vec
![String
::from("b"),
2349 String
::from("c")])),
2350 (String
::from("d"), mk_set(vec
![String
::from("e"),
2351 String
::from("f")])),
2354 v2
.externs
= Externs
::new(mk_map(vec
![
2355 (String
::from("d"), mk_set(vec
![String
::from("e"),
2356 String
::from("f")])),
2357 (String
::from("a"), mk_set(vec
![String
::from("b"),
2358 String
::from("c")])),
2361 v3
.externs
= Externs
::new(mk_map(vec
![
2362 (String
::from("a"), mk_set(vec
![String
::from("b"),
2363 String
::from("c")])),
2364 (String
::from("d"), mk_set(vec
![String
::from("f"),
2365 String
::from("e")])),
2368 assert_eq
!(v1
.dep_tracking_hash(), v2
.dep_tracking_hash());
2369 assert_eq
!(v1
.dep_tracking_hash(), v3
.dep_tracking_hash());
2370 assert_eq
!(v2
.dep_tracking_hash(), v3
.dep_tracking_hash());
2373 assert_eq
!(v1
.dep_tracking_hash(), v1
.clone().dep_tracking_hash());
2374 assert_eq
!(v2
.dep_tracking_hash(), v2
.clone().dep_tracking_hash());
2375 assert_eq
!(v3
.dep_tracking_hash(), v3
.clone().dep_tracking_hash());
2379 fn test_lints_tracking_hash_different_values() {
2380 let mut v1
= super::basic_options();
2381 let mut v2
= super::basic_options();
2382 let mut v3
= super::basic_options();
2384 v1
.lint_opts
= vec
![(String
::from("a"), lint
::Allow
),
2385 (String
::from("b"), lint
::Warn
),
2386 (String
::from("c"), lint
::Deny
),
2387 (String
::from("d"), lint
::Forbid
)];
2389 v2
.lint_opts
= vec
![(String
::from("a"), lint
::Allow
),
2390 (String
::from("b"), lint
::Warn
),
2391 (String
::from("X"), lint
::Deny
),
2392 (String
::from("d"), lint
::Forbid
)];
2394 v3
.lint_opts
= vec
![(String
::from("a"), lint
::Allow
),
2395 (String
::from("b"), lint
::Warn
),
2396 (String
::from("c"), lint
::Forbid
),
2397 (String
::from("d"), lint
::Deny
)];
2399 assert
!(v1
.dep_tracking_hash() != v2
.dep_tracking_hash());
2400 assert
!(v1
.dep_tracking_hash() != v3
.dep_tracking_hash());
2401 assert
!(v2
.dep_tracking_hash() != v3
.dep_tracking_hash());
2404 assert_eq
!(v1
.dep_tracking_hash(), v1
.clone().dep_tracking_hash());
2405 assert_eq
!(v2
.dep_tracking_hash(), v2
.clone().dep_tracking_hash());
2406 assert_eq
!(v3
.dep_tracking_hash(), v3
.clone().dep_tracking_hash());
2410 fn test_lints_tracking_hash_different_construction_order() {
2411 let mut v1
= super::basic_options();
2412 let mut v2
= super::basic_options();
2414 v1
.lint_opts
= vec
![(String
::from("a"), lint
::Allow
),
2415 (String
::from("b"), lint
::Warn
),
2416 (String
::from("c"), lint
::Deny
),
2417 (String
::from("d"), lint
::Forbid
)];
2419 v2
.lint_opts
= vec
![(String
::from("a"), lint
::Allow
),
2420 (String
::from("c"), lint
::Deny
),
2421 (String
::from("b"), lint
::Warn
),
2422 (String
::from("d"), lint
::Forbid
)];
2424 assert_eq
!(v1
.dep_tracking_hash(), v2
.dep_tracking_hash());
2427 assert_eq
!(v1
.dep_tracking_hash(), v1
.clone().dep_tracking_hash());
2428 assert_eq
!(v2
.dep_tracking_hash(), v2
.clone().dep_tracking_hash());
2432 fn test_search_paths_tracking_hash_different_values() {
2433 let mut v1
= super::basic_options();
2434 let mut v2
= super::basic_options();
2435 let mut v3
= super::basic_options();
2436 let mut v4
= super::basic_options();
2437 let mut v5
= super::basic_options();
2440 v1
.search_paths
.add_path("native=abc", super::ErrorOutputType
::Json(false));
2441 v1
.search_paths
.add_path("crate=def", super::ErrorOutputType
::Json(false));
2442 v1
.search_paths
.add_path("dependency=ghi", super::ErrorOutputType
::Json(false));
2443 v1
.search_paths
.add_path("framework=jkl", super::ErrorOutputType
::Json(false));
2444 v1
.search_paths
.add_path("all=mno", super::ErrorOutputType
::Json(false));
2447 v2
.search_paths
.add_path("native=XXX", super::ErrorOutputType
::Json(false));
2448 v2
.search_paths
.add_path("crate=def", super::ErrorOutputType
::Json(false));
2449 v2
.search_paths
.add_path("dependency=ghi", super::ErrorOutputType
::Json(false));
2450 v2
.search_paths
.add_path("framework=jkl", super::ErrorOutputType
::Json(false));
2451 v2
.search_paths
.add_path("all=mno", super::ErrorOutputType
::Json(false));
2454 v2
.search_paths
.add_path("native=abc", super::ErrorOutputType
::Json(false));
2455 v2
.search_paths
.add_path("crate=XXX", super::ErrorOutputType
::Json(false));
2456 v2
.search_paths
.add_path("dependency=ghi", super::ErrorOutputType
::Json(false));
2457 v2
.search_paths
.add_path("framework=jkl", super::ErrorOutputType
::Json(false));
2458 v2
.search_paths
.add_path("all=mno", super::ErrorOutputType
::Json(false));
2460 // Dependency changed
2461 v3
.search_paths
.add_path("native=abc", super::ErrorOutputType
::Json(false));
2462 v3
.search_paths
.add_path("crate=def", super::ErrorOutputType
::Json(false));
2463 v3
.search_paths
.add_path("dependency=XXX", super::ErrorOutputType
::Json(false));
2464 v3
.search_paths
.add_path("framework=jkl", super::ErrorOutputType
::Json(false));
2465 v3
.search_paths
.add_path("all=mno", super::ErrorOutputType
::Json(false));
2467 // Framework changed
2468 v4
.search_paths
.add_path("native=abc", super::ErrorOutputType
::Json(false));
2469 v4
.search_paths
.add_path("crate=def", super::ErrorOutputType
::Json(false));
2470 v4
.search_paths
.add_path("dependency=ghi", super::ErrorOutputType
::Json(false));
2471 v4
.search_paths
.add_path("framework=XXX", super::ErrorOutputType
::Json(false));
2472 v4
.search_paths
.add_path("all=mno", super::ErrorOutputType
::Json(false));
2475 v5
.search_paths
.add_path("native=abc", super::ErrorOutputType
::Json(false));
2476 v5
.search_paths
.add_path("crate=def", super::ErrorOutputType
::Json(false));
2477 v5
.search_paths
.add_path("dependency=ghi", super::ErrorOutputType
::Json(false));
2478 v5
.search_paths
.add_path("framework=jkl", super::ErrorOutputType
::Json(false));
2479 v5
.search_paths
.add_path("all=XXX", super::ErrorOutputType
::Json(false));
2481 assert
!(v1
.dep_tracking_hash() != v2
.dep_tracking_hash());
2482 assert
!(v1
.dep_tracking_hash() != v3
.dep_tracking_hash());
2483 assert
!(v1
.dep_tracking_hash() != v4
.dep_tracking_hash());
2484 assert
!(v1
.dep_tracking_hash() != v5
.dep_tracking_hash());
2487 assert_eq
!(v1
.dep_tracking_hash(), v1
.clone().dep_tracking_hash());
2488 assert_eq
!(v2
.dep_tracking_hash(), v2
.clone().dep_tracking_hash());
2489 assert_eq
!(v3
.dep_tracking_hash(), v3
.clone().dep_tracking_hash());
2490 assert_eq
!(v4
.dep_tracking_hash(), v4
.clone().dep_tracking_hash());
2491 assert_eq
!(v5
.dep_tracking_hash(), v5
.clone().dep_tracking_hash());
2495 fn test_search_paths_tracking_hash_different_order() {
2496 let mut v1
= super::basic_options();
2497 let mut v2
= super::basic_options();
2498 let mut v3
= super::basic_options();
2499 let mut v4
= super::basic_options();
2502 v1
.search_paths
.add_path("native=abc", super::ErrorOutputType
::Json(false));
2503 v1
.search_paths
.add_path("crate=def", super::ErrorOutputType
::Json(false));
2504 v1
.search_paths
.add_path("dependency=ghi", super::ErrorOutputType
::Json(false));
2505 v1
.search_paths
.add_path("framework=jkl", super::ErrorOutputType
::Json(false));
2506 v1
.search_paths
.add_path("all=mno", super::ErrorOutputType
::Json(false));
2508 v2
.search_paths
.add_path("native=abc", super::ErrorOutputType
::Json(false));
2509 v2
.search_paths
.add_path("dependency=ghi", super::ErrorOutputType
::Json(false));
2510 v2
.search_paths
.add_path("crate=def", super::ErrorOutputType
::Json(false));
2511 v2
.search_paths
.add_path("framework=jkl", super::ErrorOutputType
::Json(false));
2512 v2
.search_paths
.add_path("all=mno", super::ErrorOutputType
::Json(false));
2514 v3
.search_paths
.add_path("crate=def", super::ErrorOutputType
::Json(false));
2515 v3
.search_paths
.add_path("framework=jkl", super::ErrorOutputType
::Json(false));
2516 v3
.search_paths
.add_path("native=abc", super::ErrorOutputType
::Json(false));
2517 v3
.search_paths
.add_path("dependency=ghi", super::ErrorOutputType
::Json(false));
2518 v3
.search_paths
.add_path("all=mno", super::ErrorOutputType
::Json(false));
2520 v4
.search_paths
.add_path("all=mno", super::ErrorOutputType
::Json(false));
2521 v4
.search_paths
.add_path("native=abc", super::ErrorOutputType
::Json(false));
2522 v4
.search_paths
.add_path("crate=def", super::ErrorOutputType
::Json(false));
2523 v4
.search_paths
.add_path("dependency=ghi", super::ErrorOutputType
::Json(false));
2524 v4
.search_paths
.add_path("framework=jkl", super::ErrorOutputType
::Json(false));
2526 assert
!(v1
.dep_tracking_hash() == v2
.dep_tracking_hash());
2527 assert
!(v1
.dep_tracking_hash() == v3
.dep_tracking_hash());
2528 assert
!(v1
.dep_tracking_hash() == v4
.dep_tracking_hash());
2531 assert_eq
!(v1
.dep_tracking_hash(), v1
.clone().dep_tracking_hash());
2532 assert_eq
!(v2
.dep_tracking_hash(), v2
.clone().dep_tracking_hash());
2533 assert_eq
!(v3
.dep_tracking_hash(), v3
.clone().dep_tracking_hash());
2534 assert_eq
!(v4
.dep_tracking_hash(), v4
.clone().dep_tracking_hash());
2538 fn test_native_libs_tracking_hash_different_values() {
2539 let mut v1
= super::basic_options();
2540 let mut v2
= super::basic_options();
2541 let mut v3
= super::basic_options();
2542 let mut v4
= super::basic_options();
2545 v1
.libs
= vec
![(String
::from("a"), None
, Some(cstore
::NativeStatic
)),
2546 (String
::from("b"), None
, Some(cstore
::NativeFramework
)),
2547 (String
::from("c"), None
, Some(cstore
::NativeUnknown
))];
2550 v2
.libs
= vec
![(String
::from("a"), None
, Some(cstore
::NativeStatic
)),
2551 (String
::from("X"), None
, Some(cstore
::NativeFramework
)),
2552 (String
::from("c"), None
, Some(cstore
::NativeUnknown
))];
2555 v3
.libs
= vec
![(String
::from("a"), None
, Some(cstore
::NativeStatic
)),
2556 (String
::from("b"), None
, Some(cstore
::NativeStatic
)),
2557 (String
::from("c"), None
, Some(cstore
::NativeUnknown
))];
2560 v4
.libs
= vec
![(String
::from("a"), None
, Some(cstore
::NativeStatic
)),
2561 (String
::from("b"), Some(String
::from("X")), Some(cstore
::NativeFramework
)),
2562 (String
::from("c"), None
, Some(cstore
::NativeUnknown
))];
2564 assert
!(v1
.dep_tracking_hash() != v2
.dep_tracking_hash());
2565 assert
!(v1
.dep_tracking_hash() != v3
.dep_tracking_hash());
2566 assert
!(v1
.dep_tracking_hash() != v4
.dep_tracking_hash());
2569 assert_eq
!(v1
.dep_tracking_hash(), v1
.clone().dep_tracking_hash());
2570 assert_eq
!(v2
.dep_tracking_hash(), v2
.clone().dep_tracking_hash());
2571 assert_eq
!(v3
.dep_tracking_hash(), v3
.clone().dep_tracking_hash());
2572 assert_eq
!(v4
.dep_tracking_hash(), v4
.clone().dep_tracking_hash());
2576 fn test_native_libs_tracking_hash_different_order() {
2577 let mut v1
= super::basic_options();
2578 let mut v2
= super::basic_options();
2579 let mut v3
= super::basic_options();
2582 v1
.libs
= vec
![(String
::from("a"), None
, Some(cstore
::NativeStatic
)),
2583 (String
::from("b"), None
, Some(cstore
::NativeFramework
)),
2584 (String
::from("c"), None
, Some(cstore
::NativeUnknown
))];
2586 v2
.libs
= vec
![(String
::from("b"), None
, Some(cstore
::NativeFramework
)),
2587 (String
::from("a"), None
, Some(cstore
::NativeStatic
)),
2588 (String
::from("c"), None
, Some(cstore
::NativeUnknown
))];
2590 v3
.libs
= vec
![(String
::from("c"), None
, Some(cstore
::NativeUnknown
)),
2591 (String
::from("a"), None
, Some(cstore
::NativeStatic
)),
2592 (String
::from("b"), None
, Some(cstore
::NativeFramework
))];
2594 assert
!(v1
.dep_tracking_hash() == v2
.dep_tracking_hash());
2595 assert
!(v1
.dep_tracking_hash() == v3
.dep_tracking_hash());
2596 assert
!(v2
.dep_tracking_hash() == v3
.dep_tracking_hash());
2599 assert_eq
!(v1
.dep_tracking_hash(), v1
.clone().dep_tracking_hash());
2600 assert_eq
!(v2
.dep_tracking_hash(), v2
.clone().dep_tracking_hash());
2601 assert_eq
!(v3
.dep_tracking_hash(), v3
.clone().dep_tracking_hash());
2605 fn test_codegen_options_tracking_hash() {
2606 let reference
= super::basic_options();
2607 let mut opts
= super::basic_options();
2609 // Make sure the changing an [UNTRACKED] option leaves the hash unchanged
2610 opts
.cg
.ar
= Some(String
::from("abc"));
2611 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2613 opts
.cg
.linker
= Some(PathBuf
::from("linker"));
2614 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2616 opts
.cg
.link_args
= Some(vec
![String
::from("abc"), String
::from("def")]);
2617 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2619 opts
.cg
.link_dead_code
= true;
2620 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2622 opts
.cg
.rpath
= true;
2623 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2625 opts
.cg
.extra_filename
= String
::from("extra-filename");
2626 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2628 opts
.cg
.codegen_units
= Some(42);
2629 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2631 opts
.cg
.remark
= super::SomePasses(vec
![String
::from("pass1"),
2632 String
::from("pass2")]);
2633 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2635 opts
.cg
.save_temps
= true;
2636 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2638 opts
.cg
.incremental
= Some(String
::from("abc"));
2639 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2642 // Make sure changing a [TRACKED] option changes the hash
2643 opts
= reference
.clone();
2645 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2647 opts
= reference
.clone();
2648 opts
.cg
.target_cpu
= Some(String
::from("abc"));
2649 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2651 opts
= reference
.clone();
2652 opts
.cg
.target_feature
= String
::from("all the features, all of them");
2653 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2655 opts
= reference
.clone();
2656 opts
.cg
.passes
= vec
![String
::from("1"), String
::from("2")];
2657 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2659 opts
= reference
.clone();
2660 opts
.cg
.llvm_args
= vec
![String
::from("1"), String
::from("2")];
2661 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2663 opts
= reference
.clone();
2664 opts
.cg
.overflow_checks
= Some(true);
2665 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2667 opts
= reference
.clone();
2668 opts
.cg
.no_prepopulate_passes
= true;
2669 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2671 opts
= reference
.clone();
2672 opts
.cg
.no_vectorize_loops
= true;
2673 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2675 opts
= reference
.clone();
2676 opts
.cg
.no_vectorize_slp
= true;
2677 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2679 opts
= reference
.clone();
2680 opts
.cg
.soft_float
= true;
2681 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2683 opts
= reference
.clone();
2684 opts
.cg
.prefer_dynamic
= true;
2685 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2687 opts
= reference
.clone();
2688 opts
.cg
.no_integrated_as
= true;
2689 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2691 opts
= reference
.clone();
2692 opts
.cg
.no_redzone
= Some(true);
2693 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2695 opts
= reference
.clone();
2696 opts
.cg
.relocation_model
= Some(String
::from("relocation model"));
2697 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2699 opts
= reference
.clone();
2700 opts
.cg
.code_model
= Some(String
::from("code model"));
2701 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2703 opts
= reference
.clone();
2704 opts
.debugging_opts
.tls_model
= Some(String
::from("tls model"));
2705 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2707 opts
= reference
.clone();
2708 opts
.cg
.metadata
= vec
![String
::from("A"), String
::from("B")];
2709 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2711 opts
= reference
.clone();
2712 opts
.cg
.debuginfo
= Some(0xdeadbeef);
2713 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2715 opts
= reference
.clone();
2716 opts
.cg
.debuginfo
= Some(0xba5eba11);
2717 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2719 opts
= reference
.clone();
2720 opts
.cg
.debug_assertions
= Some(true);
2721 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2723 opts
= reference
.clone();
2724 opts
.cg
.inline_threshold
= Some(0xf007ba11);
2725 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2727 opts
= reference
.clone();
2728 opts
.cg
.panic
= Some(PanicStrategy
::Abort
);
2729 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2733 fn test_debugging_options_tracking_hash() {
2734 let reference
= super::basic_options();
2735 let mut opts
= super::basic_options();
2737 // Make sure the changing an [UNTRACKED] option leaves the hash unchanged
2738 opts
.debugging_opts
.verbose
= true;
2739 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2740 opts
.debugging_opts
.time_passes
= true;
2741 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2742 opts
.debugging_opts
.count_llvm_insns
= true;
2743 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2744 opts
.debugging_opts
.time_llvm_passes
= true;
2745 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2746 opts
.debugging_opts
.input_stats
= true;
2747 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2748 opts
.debugging_opts
.trans_stats
= true;
2749 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2750 opts
.debugging_opts
.borrowck_stats
= true;
2751 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2752 opts
.debugging_opts
.debug_llvm
= true;
2753 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2754 opts
.debugging_opts
.meta_stats
= true;
2755 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2756 opts
.debugging_opts
.print_link_args
= true;
2757 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2758 opts
.debugging_opts
.print_llvm_passes
= true;
2759 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2760 opts
.debugging_opts
.ast_json
= true;
2761 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2762 opts
.debugging_opts
.ast_json_noexpand
= true;
2763 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2764 opts
.debugging_opts
.ls
= true;
2765 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2766 opts
.debugging_opts
.save_analysis
= true;
2767 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2768 opts
.debugging_opts
.flowgraph_print_loans
= true;
2769 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2770 opts
.debugging_opts
.flowgraph_print_moves
= true;
2771 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2772 opts
.debugging_opts
.flowgraph_print_assigns
= true;
2773 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2774 opts
.debugging_opts
.flowgraph_print_all
= true;
2775 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2776 opts
.debugging_opts
.print_region_graph
= true;
2777 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2778 opts
.debugging_opts
.parse_only
= true;
2779 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2780 opts
.debugging_opts
.incremental
= Some(String
::from("abc"));
2781 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2782 opts
.debugging_opts
.dump_dep_graph
= true;
2783 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2784 opts
.debugging_opts
.query_dep_graph
= true;
2785 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2786 opts
.debugging_opts
.no_analysis
= true;
2787 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2788 opts
.debugging_opts
.unstable_options
= true;
2789 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2790 opts
.debugging_opts
.trace_macros
= true;
2791 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2792 opts
.debugging_opts
.keep_hygiene_data
= true;
2793 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2794 opts
.debugging_opts
.keep_ast
= true;
2795 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2796 opts
.debugging_opts
.print_trans_items
= Some(String
::from("abc"));
2797 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2798 opts
.debugging_opts
.dump_mir
= Some(String
::from("abc"));
2799 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2800 opts
.debugging_opts
.dump_mir_dir
= Some(String
::from("abc"));
2801 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2802 opts
.debugging_opts
.dump_mir_graphviz
= true;
2803 assert_eq
!(reference
.dep_tracking_hash(), opts
.dep_tracking_hash());
2805 // Make sure changing a [TRACKED] option changes the hash
2806 opts
= reference
.clone();
2807 opts
.debugging_opts
.asm_comments
= true;
2808 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2810 opts
= reference
.clone();
2811 opts
.debugging_opts
.no_verify
= true;
2812 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2814 opts
= reference
.clone();
2815 opts
.debugging_opts
.no_landing_pads
= true;
2816 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2818 opts
= reference
.clone();
2819 opts
.debugging_opts
.fewer_names
= true;
2820 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2822 opts
= reference
.clone();
2823 opts
.debugging_opts
.no_trans
= true;
2824 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2826 opts
= reference
.clone();
2827 opts
.debugging_opts
.treat_err_as_bug
= true;
2828 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2830 opts
= reference
.clone();
2831 opts
.debugging_opts
.continue_parse_after_error
= true;
2832 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2834 opts
= reference
.clone();
2835 opts
.debugging_opts
.extra_plugins
= vec
![String
::from("plugin1"), String
::from("plugin2")];
2836 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2838 opts
= reference
.clone();
2839 opts
.debugging_opts
.force_overflow_checks
= Some(true);
2840 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2842 opts
= reference
.clone();
2843 opts
.debugging_opts
.enable_nonzeroing_move_hints
= true;
2844 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2846 opts
= reference
.clone();
2847 opts
.debugging_opts
.show_span
= Some(String
::from("abc"));
2848 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2850 opts
= reference
.clone();
2851 opts
.debugging_opts
.mir_opt_level
= 3;
2852 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());
2854 opts
= reference
.clone();
2855 opts
.debugging_opts
.relro_level
= Some(RelroLevel
::Full
);
2856 assert
!(reference
.dep_tracking_hash() != opts
.dep_tracking_hash());