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)]
77 /// Don't do any LTO whatsoever
80 /// Do a full crate graph LTO. The flavor is determined by the compiler
81 /// (currently the default is "fat").
84 /// Do a full crate graph LTO with ThinLTO
87 /// Do a local graph LTO with ThinLTO (only relevant for multiple codegen
91 /// Do a full crate graph LTO with "fat" LTO
95 #[derive(Clone, Copy, PartialEq, Hash)]
96 pub enum DebugInfoLevel {
102 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord,
103 RustcEncodable, RustcDecodable)]
104 pub enum OutputType {
115 /// The epoch of the compiler (RFC 2052)
116 #[derive(Clone, Copy, Hash, PartialOrd, Ord, Eq, PartialEq, Debug)]
119 // epochs must be kept in order, newest to oldest
126 // when adding new epochs, be sure to update:
128 // - the list in the `parse_epoch` static
129 // - the match in the `parse_epoch` function
130 // - add a `rust_####()` function to the session
131 // - update the enum in Cargo's sources as well
133 // When -Zepoch becomes --epoch, there will
134 // also be a check for the epoch being nightly-only
135 // somewhere. That will need to be updated
136 // whenever we're stabilizing/introducing a new epoch
137 // as well as changing the default Cargo template.
140 pub const ALL_EPOCHS: &[Epoch] = &[Epoch::Epoch2015, Epoch::Epoch2018];
142 impl ToString for Epoch {
143 fn to_string(&self) -> String {
145 Epoch::Epoch2015 => "2015".into(),
146 Epoch::Epoch2018 => "2018".into(),
152 pub fn lint_name(&self) -> &'static str {
154 Epoch::Epoch2015 => "epoch_2015",
155 Epoch::Epoch2018 => "epoch_2018",
160 impl str::FromStr for Epoch {
162 fn from_str(s: &str) -> Result<Self, ()> {
164 "2015" => Ok(Epoch::Epoch2015),
165 "2018" => Ok(Epoch::Epoch2018),
171 impl_stable_hash_for!(enum self::OutputType {
182 impl<'tcx> ToStableHashKey<StableHashingContext<'tcx>> for OutputType {
183 type KeyType = OutputType;
185 fn to_stable_hash_key(&self, _: &StableHashingContext<'tcx>) -> Self::KeyType {
191 fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
194 OutputType::DepInfo => true,
195 OutputType::Bitcode |
196 OutputType::Assembly |
197 OutputType::LlvmAssembly |
200 OutputType::Metadata => false,
204 fn shorthand(&self) -> &'static str {
206 OutputType::Bitcode => "llvm-bc",
207 OutputType::Assembly => "asm",
208 OutputType::LlvmAssembly => "llvm-ir",
209 OutputType::Mir => "mir",
210 OutputType::Object => "obj",
211 OutputType::Metadata => "metadata",
212 OutputType::Exe => "link",
213 OutputType::DepInfo => "dep-info",
217 fn from_shorthand(shorthand: &str) -> Option<Self> {
218 Some(match shorthand {
219 "asm" => OutputType::Assembly,
220 "llvm-ir" => OutputType::LlvmAssembly,
221 "mir" => OutputType::Mir,
222 "llvm-bc" => OutputType::Bitcode,
223 "obj" => OutputType::Object,
224 "metadata" => OutputType::Metadata,
225 "link" => OutputType::Exe,
226 "dep-info" => OutputType::DepInfo,
231 fn shorthands_display() -> String {
233 "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`",
234 OutputType::Bitcode.shorthand(),
235 OutputType::Assembly.shorthand(),
236 OutputType::LlvmAssembly.shorthand(),
237 OutputType::Mir.shorthand(),
238 OutputType::Object.shorthand(),
239 OutputType::Metadata.shorthand(),
240 OutputType::Exe.shorthand(),
241 OutputType::DepInfo.shorthand(),
245 pub fn extension(&self) -> &'static str {
247 OutputType::Bitcode => "bc",
248 OutputType::Assembly => "s",
249 OutputType::LlvmAssembly => "ll",
250 OutputType::Mir => "mir",
251 OutputType::Object => "o",
252 OutputType::Metadata => "rmeta",
253 OutputType::DepInfo => "d",
254 OutputType::Exe => "",
259 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
260 pub enum ErrorOutputType {
261 HumanReadable(ColorConfig),
266 impl Default for ErrorOutputType {
267 fn default() -> ErrorOutputType {
268 ErrorOutputType::HumanReadable(ColorConfig::Auto)
272 // Use tree-based collections to cheaply get a deterministic Hash implementation.
273 // DO NOT switch BTreeMap out for an unsorted container type! That would break
274 // dependency tracking for commandline arguments.
275 #[derive(Clone, Hash)]
276 pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
278 impl_stable_hash_for!(tuple_struct self::OutputTypes {
283 pub fn new(entries: &[(OutputType, Option<PathBuf>)]) -> OutputTypes {
284 OutputTypes(BTreeMap::from_iter(entries.iter()
285 .map(|&(k, ref v)| (k, v.clone()))))
288 pub fn get(&self, key: &OutputType) -> Option<&Option<PathBuf>> {
292 pub fn contains_key(&self, key: &OutputType) -> bool {
293 self.0.contains_key(key)
296 pub fn keys<'a>(&'a self) -> BTreeMapKeysIter<'a, OutputType, Option<PathBuf>> {
300 pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option<PathBuf>> {
304 // True if any of the output types require codegen or linking.
305 pub fn should_trans(&self) -> bool {
306 self.0.keys().any(|k| match *k {
307 OutputType::Bitcode |
308 OutputType::Assembly |
309 OutputType::LlvmAssembly |
312 OutputType::Exe => true,
313 OutputType::Metadata |
314 OutputType::DepInfo => false,
320 // Use tree-based collections to cheaply get a deterministic Hash implementation.
321 // DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That
322 // would break dependency tracking for commandline arguments.
323 #[derive(Clone, Hash)]
324 pub struct Externs(BTreeMap<String, BTreeSet<String>>);
327 pub fn new(data: BTreeMap<String, BTreeSet<String>>) -> Externs {
331 pub fn get(&self, key: &str) -> Option<&BTreeSet<String>> {
335 pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<String>> {
340 macro_rules! hash_option {
341 ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => ({});
342 ($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({
343 if $sub_hashes.insert(stringify!($opt_name),
344 $opt_expr as &dyn dep_tracking::DepTrackingHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHashHash).is_some() {
345 bug!("Duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
351 [UNTRACKED_WITH_WARNING $warn_val:expr, $warn_text:expr, $error_format:expr]) => ({
352 if *$opt_expr == $warn_val {
353 early_warn($error_format, $warn_text)
358 macro_rules! top_level_options {
359 (pub struct Options { $(
360 $opt:ident : $t:ty [$dep_tracking_marker:ident $($warn_val:expr, $warn_text:expr)*],
368 pub fn dep_tracking_hash(&self) -> u64 {
369 let mut sub_hashes = BTreeMap::new();
374 [$dep_tracking_marker $($warn_val,
376 self.error_format)*]);
378 let mut hasher = DefaultHasher::new();
379 dep_tracking::stable_hash(sub_hashes,
388 // The top-level commandline options struct
390 // For each option, one has to specify how it behaves with regard to the
391 // dependency tracking system of incremental compilation. This is done via the
392 // square-bracketed directive after the field type. The options are:
395 // A change in the given field will cause the compiler to completely clear the
396 // incremental compilation cache before proceeding.
399 // Incremental compilation is not influenced by this option.
401 // [UNTRACKED_WITH_WARNING(val, warning)]
402 // The option is incompatible with incremental compilation in some way. If it
403 // has the value `val`, the string `warning` is emitted as a warning.
405 // If you add a new option to this struct or one of the sub-structs like
406 // CodegenOptions, think about how it influences incremental compilation. If in
407 // doubt, specify [TRACKED], which is always "correct" but might lead to
408 // unnecessary re-compilation.
411 // The crate config requested for the session, which may be combined
412 // with additional crate configurations during the compile process
413 crate_types: Vec<CrateType> [TRACKED],
414 optimize: OptLevel [TRACKED],
415 // Include the debug_assertions flag into dependency tracking, since it
416 // can influence whether overflow checks are done or not.
417 debug_assertions: bool [TRACKED],
418 debuginfo: DebugInfoLevel [TRACKED],
419 lint_opts: Vec<(String, lint::Level)> [TRACKED],
420 lint_cap: Option<lint::Level> [TRACKED],
421 describe_lints: bool [UNTRACKED],
422 output_types: OutputTypes [TRACKED],
423 // FIXME(mw): We track this for now but it actually doesn't make too
424 // much sense: The search path can stay the same while the
425 // things discovered there might have changed on disk.
426 search_paths: SearchPaths [TRACKED],
427 libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED],
428 maybe_sysroot: Option<PathBuf> [TRACKED],
430 target_triple: String [TRACKED],
432 test: bool [TRACKED],
433 error_format: ErrorOutputType [UNTRACKED],
435 // if Some, enable incremental compilation, using the given
436 // directory to store intermediate results
437 incremental: Option<PathBuf> [UNTRACKED],
439 debugging_opts: DebuggingOptions [TRACKED],
440 prints: Vec<PrintRequest> [UNTRACKED],
441 // Determines which borrow checker(s) to run. This is the parsed, sanitized
442 // version of `debugging_opts.borrowck`, which is just a plain string.
443 borrowck_mode: BorrowckMode [UNTRACKED],
444 cg: CodegenOptions [TRACKED],
445 // FIXME(mw): We track this for now but it actually doesn't make too
446 // much sense: The value of this option can stay the same
447 // while the files they refer to might have changed on disk.
448 externs: Externs [TRACKED],
449 crate_name: Option<String> [TRACKED],
450 // An optional name to use as the crate for std during std injection,
451 // written `extern crate std = "name"`. Default to "std". Used by
452 // out-of-tree drivers.
453 alt_std_name: Option<String> [TRACKED],
454 // Indicates how the compiler should treat unstable features
455 unstable_features: UnstableFeatures [TRACKED],
457 // Indicates whether this run of the compiler is actually rustdoc. This
458 // is currently just a hack and will be removed eventually, so please
459 // try to not rely on this too much.
460 actually_rustdoc: bool [TRACKED],
462 // Specifications of codegen units / ThinLTO which are forced as a
463 // result of parsing command line options. These are not necessarily
464 // what rustc was invoked with, but massaged a bit to agree with
465 // commands like `--emit llvm-ir` which they're often incompatible with
466 // if we otherwise use the defaults of rustc.
467 cli_forced_codegen_units: Option<usize> [UNTRACKED],
468 cli_forced_thinlto_off: bool [UNTRACKED],
470 // Remap source path prefixes in all output (messages, object files, debug, etc)
471 remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
475 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
476 pub enum PrintRequest {
491 #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
492 pub enum BorrowckMode {
499 /// Should we emit the AST-based borrow checker errors?
500 pub fn use_ast(self) -> bool {
502 BorrowckMode::Ast => true,
503 BorrowckMode::Compare => true,
504 BorrowckMode::Mir => false,
507 /// Should we emit the MIR-based borrow checker errors?
508 pub fn use_mir(self) -> bool {
510 BorrowckMode::Ast => false,
511 BorrowckMode::Compare => true,
512 BorrowckMode::Mir => true,
518 /// Load source from file
521 /// String that is shown in place of a filename
523 /// Anonymous source string
529 pub fn filestem(&self) -> String {
531 Input::File(ref ifile) => ifile.file_stem().unwrap()
532 .to_str().unwrap().to_string(),
533 Input::Str { .. } => "rust_out".to_string(),
539 pub struct OutputFilenames {
540 pub out_directory: PathBuf,
541 pub out_filestem: String,
542 pub single_output_file: Option<PathBuf>,
544 pub outputs: OutputTypes,
547 impl_stable_hash_for!(struct self::OutputFilenames {
555 pub const RUST_CGU_EXT: &str = "rcgu";
557 impl OutputFilenames {
558 pub fn path(&self, flavor: OutputType) -> PathBuf {
559 self.outputs.get(&flavor).and_then(|p| p.to_owned())
560 .or_else(|| self.single_output_file.clone())
561 .unwrap_or_else(|| self.temp_path(flavor, None))
564 /// Get the path where a compilation artifact of the given type for the
565 /// given codegen unit should be placed on disk. If codegen_unit_name is
566 /// None, a path distinct from those of any codegen unit will be generated.
567 pub fn temp_path(&self,
569 codegen_unit_name: Option<&str>)
571 let extension = flavor.extension();
572 self.temp_path_ext(extension, codegen_unit_name)
575 /// Like temp_path, but also supports things where there is no corresponding
576 /// OutputType, like no-opt-bitcode or lto-bitcode.
577 pub fn temp_path_ext(&self,
579 codegen_unit_name: Option<&str>)
581 let base = self.out_directory.join(&self.filestem());
583 let mut extension = String::new();
585 if let Some(codegen_unit_name) = codegen_unit_name {
586 extension.push_str(codegen_unit_name);
590 if !extension.is_empty() {
591 extension.push_str(".");
592 extension.push_str(RUST_CGU_EXT);
593 extension.push_str(".");
596 extension.push_str(ext);
599 let path = base.with_extension(&extension[..]);
603 pub fn with_extension(&self, extension: &str) -> PathBuf {
604 self.out_directory.join(&self.filestem()).with_extension(extension)
607 pub fn filestem(&self) -> String {
608 format!("{}{}", self.out_filestem, self.extra)
612 pub fn host_triple() -> &'static str {
613 // Get the host triple out of the build environment. This ensures that our
614 // idea of the host triple is the same as for the set of libraries we've
615 // actually built. We can't just take LLVM's host triple because they
616 // normalize all ix86 architectures to i386.
618 // Instead of grabbing the host triple (for the current host), we grab (at
619 // compile time) the target triple that this rustc is built with and
620 // calling that (at runtime) the host triple.
621 (option_env!("CFG_COMPILER_HOST_TRIPLE")).
622 expect("CFG_COMPILER_HOST_TRIPLE")
625 /// Some reasonable defaults
626 pub fn basic_options() -> Options {
628 crate_types: Vec::new(),
629 optimize: OptLevel::No,
630 debuginfo: NoDebugInfo,
631 lint_opts: Vec::new(),
633 describe_lints: false,
634 output_types: OutputTypes(BTreeMap::new()),
635 search_paths: SearchPaths::new(),
637 target_triple: host_triple().to_string(),
640 debugging_opts: basic_debugging_options(),
642 borrowck_mode: BorrowckMode::Ast,
643 cg: basic_codegen_options(),
644 error_format: ErrorOutputType::default(),
645 externs: Externs(BTreeMap::new()),
649 unstable_features: UnstableFeatures::Disallow,
650 debug_assertions: true,
651 actually_rustdoc: false,
652 cli_forced_codegen_units: None,
653 cli_forced_thinlto_off: false,
654 remap_path_prefix: Vec::new(),
659 /// True if there is a reason to build the dep graph.
660 pub fn build_dep_graph(&self) -> bool {
661 self.incremental.is_some() ||
662 self.debugging_opts.dump_dep_graph ||
663 self.debugging_opts.query_dep_graph
667 pub fn enable_dep_node_debug_strs(&self) -> bool {
668 cfg!(debug_assertions) &&
669 (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info)
672 pub fn file_path_mapping(&self) -> FilePathMapping {
673 FilePathMapping::new(self.remap_path_prefix.clone())
676 /// True if there will be an output file generated
677 pub fn will_create_output_file(&self) -> bool {
678 !self.debugging_opts.parse_only && // The file is just being parsed
679 !self.debugging_opts.ls // The file is just being queried
683 // The type of entry function, so
684 // users can have their own entry
685 // functions that don't start a
687 #[derive(Copy, Clone, PartialEq)]
688 pub enum EntryFnType {
694 #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
704 #[derive(Clone, Hash)]
706 SomePasses(Vec<String>),
711 pub fn is_empty(&self) -> bool {
713 SomePasses(ref v) => v.is_empty(),
719 /// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all
720 /// at once. The goal of this macro is to define an interface that can be
721 /// programmatically used by the option parser in order to initialize the struct
722 /// without hardcoding field names all over the place.
724 /// The goal is to invoke this macro once with the correct fields, and then this
725 /// macro generates all necessary code. The main gotcha of this macro is the
726 /// cgsetters module which is a bunch of generated code to parse an option into
727 /// its respective field in the struct. There are a few hand-written parsers for
728 /// parsing specific types of values in this module.
729 macro_rules! options {
730 ($struct_name:ident, $setter_name:ident, $defaultfn:ident,
731 $buildfn:ident, $prefix:expr, $outputname:expr,
732 $stat:ident, $mod_desc:ident, $mod_set:ident,
733 $($opt:ident : $t:ty = (
736 [$dep_tracking_marker:ident $(($dep_warn_val:expr, $dep_warn_text:expr))*],
741 pub struct $struct_name { $(pub $opt: $t),* }
743 pub fn $defaultfn() -> $struct_name {
744 $struct_name { $($opt: $init),* }
747 pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $struct_name
749 let mut op = $defaultfn();
750 for option in matches.opt_strs($prefix) {
751 let mut iter = option.splitn(2, '=');
752 let key = iter.next().unwrap();
753 let value = iter.next();
754 let option_to_lookup = key.replace("-", "_");
755 let mut found = false;
756 for &(candidate, setter, opt_type_desc, _) in $stat {
757 if option_to_lookup != candidate { continue }
758 if !setter(&mut op, value) {
759 match (value, opt_type_desc) {
760 (Some(..), None) => {
761 early_error(error_format, &format!("{} option `{}` takes no \
762 value", $outputname, key))
764 (None, Some(type_desc)) => {
765 early_error(error_format, &format!("{0} option `{1}` requires \
766 {2} ({3} {1}=<value>)",
770 (Some(value), Some(type_desc)) => {
771 early_error(error_format, &format!("incorrect value `{}` for {} \
772 option `{}` - {} was expected",
776 (None, None) => bug!()
783 early_error(error_format, &format!("unknown {} option: `{}`",
790 impl<'a> dep_tracking::DepTrackingHash for $struct_name {
792 fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
793 let mut sub_hashes = BTreeMap::new();
798 [$dep_tracking_marker $($dep_warn_val,
802 dep_tracking::stable_hash(sub_hashes, hasher, error_format);
806 pub type $setter_name = fn(&mut $struct_name, v: Option<&str>) -> bool;
807 pub const $stat: &'static [(&'static str, $setter_name,
808 Option<&'static str>, &'static str)] =
809 &[ $( (stringify!($opt), $mod_set::$opt, $mod_desc::$parse, $desc) ),* ];
811 #[allow(non_upper_case_globals, dead_code)]
813 pub const parse_bool: Option<&'static str> = None;
814 pub const parse_opt_bool: Option<&'static str> =
815 Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`");
816 pub const parse_string: Option<&'static str> = Some("a string");
817 pub const parse_string_push: Option<&'static str> = Some("a string");
818 pub const parse_pathbuf_push: Option<&'static str> = Some("a path");
819 pub const parse_opt_string: Option<&'static str> = Some("a string");
820 pub const parse_opt_pathbuf: Option<&'static str> = Some("a path");
821 pub const parse_list: Option<&'static str> = Some("a space-separated list of strings");
822 pub const parse_opt_list: Option<&'static str> = Some("a space-separated list of strings");
823 pub const parse_uint: Option<&'static str> = Some("a number");
824 pub const parse_passes: Option<&'static str> =
825 Some("a space-separated list of passes, or `all`");
826 pub const parse_opt_uint: Option<&'static str> =
828 pub const parse_panic_strategy: Option<&'static str> =
829 Some("either `panic` or `abort`");
830 pub const parse_relro_level: Option<&'static str> =
831 Some("one of: `full`, `partial`, or `off`");
832 pub const parse_sanitizer: Option<&'static str> =
833 Some("one of: `address`, `leak`, `memory` or `thread`");
834 pub const parse_linker_flavor: Option<&'static str> =
835 Some(::rustc_back::LinkerFlavor::one_of());
836 pub const parse_optimization_fuel: Option<&'static str> =
837 Some("crate=integer");
838 pub const parse_unpretty: Option<&'static str> =
839 Some("`string` or `string=string`");
840 pub const parse_lto: Option<&'static str> =
841 Some("one of `thin`, `fat`, or omitted");
842 pub const parse_epoch: Option<&'static str> =
843 Some("one of: `2015`, `2018`");
848 use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto, Epoch};
849 use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
850 use std::path::PathBuf;
853 pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
854 $parse(&mut cg.$opt, v)
858 fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
861 None => { *slot = true; true }
865 fn parse_opt_bool(slot: &mut Option<bool>, v: Option<&str>) -> bool {
869 "n" | "no" | "off" => {
872 "y" | "yes" | "on" => {
875 _ => { return false; }
880 None => { *slot = Some(true); true }
884 fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool {
886 Some(s) => { *slot = Some(s.to_string()); true },
891 fn parse_opt_pathbuf(slot: &mut Option<PathBuf>, v: Option<&str>) -> bool {
893 Some(s) => { *slot = Some(PathBuf::from(s)); true },
898 fn parse_string(slot: &mut String, v: Option<&str>) -> bool {
900 Some(s) => { *slot = s.to_string(); true },
905 fn parse_string_push(slot: &mut Vec<String>, v: Option<&str>) -> bool {
907 Some(s) => { slot.push(s.to_string()); true },
912 fn parse_pathbuf_push(slot: &mut Vec<PathBuf>, v: Option<&str>) -> bool {
914 Some(s) => { slot.push(PathBuf::from(s)); true },
919 fn parse_list(slot: &mut Vec<String>, v: Option<&str>)
923 for s in s.split_whitespace() {
924 slot.push(s.to_string());
932 fn parse_opt_list(slot: &mut Option<Vec<String>>, v: Option<&str>)
936 let v = s.split_whitespace().map(|s| s.to_string()).collect();
944 fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool {
945 match v.and_then(|s| s.parse().ok()) {
946 Some(i) => { *slot = i; true },
951 fn parse_opt_uint(slot: &mut Option<usize>, v: Option<&str>) -> bool {
953 Some(s) => { *slot = s.parse().ok(); slot.is_some() }
954 None => { *slot = None; false }
958 fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
965 let mut passes = vec![];
966 if parse_list(&mut passes, v) {
967 *slot = SomePasses(passes);
976 fn parse_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bool {
978 Some("unwind") => *slot = Some(PanicStrategy::Unwind),
979 Some("abort") => *slot = Some(PanicStrategy::Abort),
985 fn parse_relro_level(slot: &mut Option<RelroLevel>, v: Option<&str>) -> bool {
988 match s.parse::<RelroLevel>() {
989 Ok(level) => *slot = Some(level),
998 fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
1000 Some("address") => *slote = Some(Sanitizer::Address),
1001 Some("leak") => *slote = Some(Sanitizer::Leak),
1002 Some("memory") => *slote = Some(Sanitizer::Memory),
1003 Some("thread") => *slote = Some(Sanitizer::Thread),
1009 fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
1010 match v.and_then(LinkerFlavor::from_str) {
1011 Some(lf) => *slote = Some(lf),
1017 fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) -> bool {
1021 let parts = s.split('=').collect::<Vec<_>>();
1022 if parts.len() != 2 { return false; }
1023 let crate_name = parts[0].to_string();
1024 let fuel = parts[1].parse::<u64>();
1025 if fuel.is_err() { return false; }
1026 *slot = Some((crate_name, fuel.unwrap()));
1032 fn parse_unpretty(slot: &mut Option<String>, v: Option<&str>) -> bool {
1035 Some(s) if s.split('=').count() <= 2 => {
1036 *slot = Some(s.to_string());
1043 fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
1046 Some("thin") => Lto::Thin,
1047 Some("fat") => Lto::Fat,
1048 Some(_) => return false,
1053 fn parse_epoch(slot: &mut Epoch, v: Option<&str>) -> bool {
1056 let epoch = s.parse();
1057 if let Ok(parsed) = epoch {
1070 options! {CodegenOptions, CodegenSetter, basic_codegen_options,
1071 build_codegen_options, "C", "codegen",
1072 CG_OPTIONS, cg_type_desc, cgsetters,
1073 ar: Option<String> = (None, parse_opt_string, [UNTRACKED],
1074 "this option is deprecated and does nothing"),
1075 linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
1076 "system linker to link outputs with"),
1077 link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
1078 "a single extra argument to append to the linker invocation (can be used several times)"),
1079 link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
1080 "extra arguments to append to the linker invocation (space separated)"),
1081 link_dead_code: bool = (false, parse_bool, [UNTRACKED],
1082 "don't let linker strip dead code (turning it on can be used for code coverage)"),
1083 lto: Lto = (Lto::No, parse_lto, [TRACKED],
1084 "perform LLVM link-time optimizations"),
1085 target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
1086 "select target processor (rustc --print target-cpus for details)"),
1087 target_feature: String = ("".to_string(), parse_string, [TRACKED],
1088 "target specific attributes (rustc --print target-features for details)"),
1089 passes: Vec<String> = (Vec::new(), parse_list, [TRACKED],
1090 "a list of extra LLVM passes to run (space separated)"),
1091 llvm_args: Vec<String> = (Vec::new(), parse_list, [TRACKED],
1092 "a list of arguments to pass to llvm (space separated)"),
1093 save_temps: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
1094 "`-C save-temps` might not produce all requested temporary products \
1095 when incremental compilation is enabled.")],
1096 "save all temporary output files during compilation"),
1097 rpath: bool = (false, parse_bool, [UNTRACKED],
1098 "set rpath values in libs/exes"),
1099 overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
1100 "use overflow checks for integer arithmetic"),
1101 no_prepopulate_passes: bool = (false, parse_bool, [TRACKED],
1102 "don't pre-populate the pass manager with a list of passes"),
1103 no_vectorize_loops: bool = (false, parse_bool, [TRACKED],
1104 "don't run the loop vectorization optimization passes"),
1105 no_vectorize_slp: bool = (false, parse_bool, [TRACKED],
1106 "don't run LLVM's SLP vectorization pass"),
1107 soft_float: bool = (false, parse_bool, [TRACKED],
1108 "use soft float ABI (*eabihf targets only)"),
1109 prefer_dynamic: bool = (false, parse_bool, [TRACKED],
1110 "prefer dynamic linking to static linking"),
1111 no_integrated_as: bool = (false, parse_bool, [TRACKED],
1112 "use an external assembler rather than LLVM's integrated one"),
1113 no_redzone: Option<bool> = (None, parse_opt_bool, [TRACKED],
1114 "disable the use of the redzone"),
1115 relocation_model: Option<String> = (None, parse_opt_string, [TRACKED],
1116 "choose the relocation model to use (rustc --print relocation-models for details)"),
1117 code_model: Option<String> = (None, parse_opt_string, [TRACKED],
1118 "choose the code model to use (rustc --print code-models for details)"),
1119 metadata: Vec<String> = (Vec::new(), parse_list, [TRACKED],
1120 "metadata to mangle symbol names with"),
1121 extra_filename: String = ("".to_string(), parse_string, [UNTRACKED],
1122 "extra data to put in each output filename"),
1123 codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
1124 "divide crate into N units to optimize in parallel"),
1125 remark: Passes = (SomePasses(Vec::new()), parse_passes, [UNTRACKED],
1126 "print remarks for these optimization passes (space separated, or \"all\")"),
1127 no_stack_check: bool = (false, parse_bool, [UNTRACKED],
1128 "the --no-stack-check flag is deprecated and does nothing"),
1129 debuginfo: Option<usize> = (None, parse_opt_uint, [TRACKED],
1130 "debug info emission level, 0 = no debug info, 1 = line tables only, \
1131 2 = full debug info with variable and type information"),
1132 opt_level: Option<String> = (None, parse_opt_string, [TRACKED],
1133 "optimize with possible levels 0-3, s, or z"),
1134 debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
1135 "explicitly enable the cfg(debug_assertions) directive"),
1136 inline_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
1137 "set the threshold for inlining a function (default: 225)"),
1138 panic: Option<PanicStrategy> = (None, parse_panic_strategy,
1139 [TRACKED], "panic strategy to compile crate with"),
1140 incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
1141 "enable incremental compilation"),
1144 options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
1145 build_debugging_options, "Z", "debugging",
1146 DB_OPTIONS, db_type_desc, dbsetters,
1147 codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
1148 "the backend to use"),
1149 verbose: bool = (false, parse_bool, [UNTRACKED],
1150 "in general, enable more debug printouts"),
1151 span_free_formats: bool = (false, parse_bool, [UNTRACKED],
1152 "when debug-printing compiler state, do not include spans"), // o/w tests have closure@path
1153 identify_regions: bool = (false, parse_bool, [UNTRACKED],
1154 "make unnamed regions display as '# (where # is some non-ident unique id)"),
1155 emit_end_regions: bool = (false, parse_bool, [UNTRACKED],
1156 "emit EndRegion as part of MIR; enable transforms that solely process EndRegion"),
1157 borrowck: Option<String> = (None, parse_opt_string, [UNTRACKED],
1158 "select which borrowck is used (`ast`, `mir`, or `compare`)"),
1159 two_phase_borrows: bool = (false, parse_bool, [UNTRACKED],
1160 "use two-phase reserved/active distinction for `&mut` borrows in MIR borrowck"),
1161 two_phase_beyond_autoref: bool = (false, parse_bool, [UNTRACKED],
1162 "when using two-phase-borrows, allow two phases even for non-autoref `&mut` borrows"),
1163 time_passes: bool = (false, parse_bool, [UNTRACKED],
1164 "measure time of each rustc pass"),
1165 count_llvm_insns: bool = (false, parse_bool,
1166 [UNTRACKED_WITH_WARNING(true,
1167 "The output generated by `-Z count_llvm_insns` might not be reliable \
1168 when used with incremental compilation")],
1169 "count where LLVM instrs originate"),
1170 time_llvm_passes: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
1171 "The output of `-Z time-llvm-passes` will only reflect timings of \
1172 re-translated modules when used with incremental compilation" )],
1173 "measure time of each LLVM pass"),
1174 input_stats: bool = (false, parse_bool, [UNTRACKED],
1175 "gather statistics about the input"),
1176 trans_stats: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
1177 "The output of `-Z trans-stats` might not be accurate when incremental \
1178 compilation is enabled")],
1179 "gather trans statistics"),
1180 asm_comments: bool = (false, parse_bool, [TRACKED],
1181 "generate comments into the assembly (may change behavior)"),
1182 no_verify: bool = (false, parse_bool, [TRACKED],
1183 "skip LLVM verification"),
1184 borrowck_stats: bool = (false, parse_bool, [UNTRACKED],
1185 "gather borrowck statistics"),
1186 no_landing_pads: bool = (false, parse_bool, [TRACKED],
1187 "omit landing pads for unwinding"),
1188 fewer_names: bool = (false, parse_bool, [TRACKED],
1189 "reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR)"),
1190 meta_stats: bool = (false, parse_bool, [UNTRACKED],
1191 "gather metadata statistics"),
1192 print_link_args: bool = (false, parse_bool, [UNTRACKED],
1193 "print the arguments passed to the linker"),
1194 print_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
1195 "prints the llvm optimization passes being run"),
1196 ast_json: bool = (false, parse_bool, [UNTRACKED],
1197 "print the AST as JSON and halt"),
1198 query_threads: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
1199 "execute queries on a thread pool with N threads"),
1200 ast_json_noexpand: bool = (false, parse_bool, [UNTRACKED],
1201 "print the pre-expansion AST as JSON and halt"),
1202 ls: bool = (false, parse_bool, [UNTRACKED],
1203 "list the symbols defined by a library crate"),
1204 save_analysis: bool = (false, parse_bool, [UNTRACKED],
1205 "write syntax and type analysis (in JSON format) information, in \
1206 addition to normal output"),
1207 flowgraph_print_loans: bool = (false, parse_bool, [UNTRACKED],
1208 "include loan analysis data in -Z unpretty flowgraph output"),
1209 flowgraph_print_moves: bool = (false, parse_bool, [UNTRACKED],
1210 "include move analysis data in -Z unpretty flowgraph output"),
1211 flowgraph_print_assigns: bool = (false, parse_bool, [UNTRACKED],
1212 "include assignment analysis data in -Z unpretty flowgraph output"),
1213 flowgraph_print_all: bool = (false, parse_bool, [UNTRACKED],
1214 "include all dataflow analysis data in -Z unpretty flowgraph output"),
1215 print_region_graph: bool = (false, parse_bool, [UNTRACKED],
1216 "prints region inference graph. \
1217 Use with RUST_REGION_GRAPH=help for more info"),
1218 parse_only: bool = (false, parse_bool, [UNTRACKED],
1219 "parse only; do not compile, assemble, or link"),
1220 no_trans: bool = (false, parse_bool, [TRACKED],
1221 "run all passes except translation; no output"),
1222 treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
1223 "treat all errors that occur as bugs"),
1224 external_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
1225 "show macro backtraces even for non-local macros"),
1226 teach: bool = (false, parse_bool, [TRACKED],
1227 "show extended diagnostic help"),
1228 continue_parse_after_error: bool = (false, parse_bool, [TRACKED],
1229 "attempt to recover from parse errors (experimental)"),
1230 incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
1231 "enable incremental compilation (experimental)"),
1232 incremental_queries: bool = (true, parse_bool, [UNTRACKED],
1233 "enable incremental compilation support for queries (experimental)"),
1234 incremental_info: bool = (false, parse_bool, [UNTRACKED],
1235 "print high-level information about incremental reuse (or the lack thereof)"),
1236 incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED],
1237 "dump hash information in textual format to stdout"),
1238 incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
1239 "verify incr. comp. hashes of green query instances"),
1240 incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED],
1241 "ignore spans during ICH computation -- used for testing"),
1242 dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
1243 "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
1244 query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
1245 "enable queries of the dependency graph for regression testing"),
1246 profile_queries: bool = (false, parse_bool, [UNTRACKED],
1247 "trace and profile the queries of the incremental compilation framework"),
1248 profile_queries_and_keys: bool = (false, parse_bool, [UNTRACKED],
1249 "trace and profile the queries and keys of the incremental compilation framework"),
1250 no_analysis: bool = (false, parse_bool, [UNTRACKED],
1251 "parse and expand the source, but run no analysis"),
1252 extra_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
1253 "load extra plugins"),
1254 unstable_options: bool = (false, parse_bool, [UNTRACKED],
1255 "adds unstable command line options to rustc interface"),
1256 force_overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
1257 "force overflow checks on or off"),
1258 trace_macros: bool = (false, parse_bool, [UNTRACKED],
1259 "for every macro invocation, print its name and arguments"),
1260 debug_macros: bool = (false, parse_bool, [TRACKED],
1261 "emit line numbers debug info inside macros"),
1262 enable_nonzeroing_move_hints: bool = (false, parse_bool, [TRACKED],
1263 "force nonzeroing move optimization on"),
1264 keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],
1265 "don't clear the hygiene data after analysis"),
1266 keep_ast: bool = (false, parse_bool, [UNTRACKED],
1267 "keep the AST after lowering it to HIR"),
1268 show_span: Option<String> = (None, parse_opt_string, [TRACKED],
1269 "show spans for compiler debugging (expr|pat|ty)"),
1270 print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
1271 "print layout information for each type encountered"),
1272 print_trans_items: Option<String> = (None, parse_opt_string, [UNTRACKED],
1273 "print the result of the translation item collection pass"),
1274 mir_opt_level: usize = (1, parse_uint, [TRACKED],
1275 "set the MIR optimization level (0-3, default: 1)"),
1276 mutable_noalias: bool = (false, parse_bool, [UNTRACKED],
1277 "emit noalias metadata for mutable references"),
1278 dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
1279 "dump MIR state at various points in translation"),
1280 dump_mir_dir: String = (String::from("mir_dump"), parse_string, [UNTRACKED],
1281 "the directory the MIR is dumped into"),
1282 dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
1283 "in addition to `.mir` files, create graphviz `.dot` files"),
1284 dump_mir_exclude_pass_number: bool = (false, parse_bool, [UNTRACKED],
1285 "if set, exclude the pass number when dumping MIR (used in tests)"),
1286 mir_emit_validate: usize = (0, parse_uint, [TRACKED],
1287 "emit Validate MIR statements, interpreted e.g. by miri (0: do not emit; 1: if function \
1288 contains unsafe block, only validate arguments; 2: always emit full validation)"),
1289 perf_stats: bool = (false, parse_bool, [UNTRACKED],
1290 "print some performance-related statistics"),
1291 hir_stats: bool = (false, parse_bool, [UNTRACKED],
1292 "print some statistics about AST and HIR"),
1293 mir_stats: bool = (false, parse_bool, [UNTRACKED],
1294 "print some statistics about MIR"),
1295 always_encode_mir: bool = (false, parse_bool, [TRACKED],
1296 "encode MIR of all functions into the crate metadata"),
1297 miri: bool = (false, parse_bool, [TRACKED],
1298 "check the miri const evaluator against the old ctfe"),
1299 osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
1300 "pass `-install_name @rpath/...` to the macOS linker"),
1301 sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED],
1303 linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
1305 fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
1306 "set the optimization fuel quota for a crate"),
1307 print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
1308 "make Rustc print the total optimization fuel used by a crate"),
1309 force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
1310 "force all crates to be `rustc_private` unstable"),
1311 pre_link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
1312 "a single extra argument to prepend the linker invocation (can be used several times)"),
1313 pre_link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
1314 "extra arguments to prepend to the linker invocation (space separated)"),
1315 profile: bool = (false, parse_bool, [TRACKED],
1316 "insert profiling code"),
1317 relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
1318 "choose which RELRO level to use"),
1319 nll: bool = (false, parse_bool, [UNTRACKED],
1320 "run the non-lexical lifetimes MIR pass"),
1321 nll_dump_cause: bool = (false, parse_bool, [UNTRACKED],
1322 "dump cause information when reporting errors from NLL"),
1323 trans_time_graph: bool = (false, parse_bool, [UNTRACKED],
1324 "generate a graphical HTML report of time spent in trans and LLVM"),
1325 thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
1326 "enable ThinLTO when possible"),
1327 inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
1328 "control whether #[inline] functions are in all cgus"),
1329 tls_model: Option<String> = (None, parse_opt_string, [TRACKED],
1330 "choose the TLS model to use (rustc --print tls-models for details)"),
1331 saturating_float_casts: bool = (false, parse_bool, [TRACKED],
1332 "make float->int casts UB-free: numbers outside the integer type's range are clipped to \
1333 the max/min integer respectively, and NaN is mapped to 0"),
1334 lower_128bit_ops: Option<bool> = (None, parse_opt_bool, [TRACKED],
1335 "rewrite operators on i128 and u128 into lang item calls (typically provided \
1336 by compiler-builtins) so translation doesn't need to support them,
1337 overriding the default for the current target"),
1338 human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
1339 "generate human-readable, predictable names for codegen units"),
1340 dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
1341 "in dep-info output, omit targets for tracking dependencies of the dep-info files \
1343 approximate_suggestions: bool = (false, parse_bool, [UNTRACKED],
1344 "include machine-applicability of suggestions in JSON output"),
1345 unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
1346 "Present the input source, unstable (and less-pretty) variants;
1347 valid types are any of the types for `--pretty`, as well as:
1348 `flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
1349 `everybody_loops` (all function bodies replaced with `loop {}`),
1350 `hir` (the HIR), `hir,identified`, or
1351 `hir,typed` (HIR with types for each node)."),
1352 epoch: Epoch = (Epoch::Epoch2015, parse_epoch, [TRACKED],
1353 "The epoch to build Rust with. Newer epochs may include features
1354 that require breaking changes. The default epoch is 2015 (the first
1355 epoch). Crates compiled with different epochs can be linked together."),
1356 run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
1357 "run `dsymutil` and delete intermediate object files"),
1358 ui_testing: bool = (false, parse_bool, [UNTRACKED],
1359 "format compiler diagnostics in a way that's better suitable for UI testing"),
1362 pub fn default_lib_output() -> CrateType {
1366 pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
1367 let end = &sess.target.target.target_endian;
1368 let arch = &sess.target.target.arch;
1369 let wordsz = &sess.target.target.target_pointer_width;
1370 let os = &sess.target.target.target_os;
1371 let env = &sess.target.target.target_env;
1372 let vendor = &sess.target.target.target_vendor;
1373 let min_atomic_width = sess.target.target.min_atomic_width();
1374 let max_atomic_width = sess.target.target.max_atomic_width();
1376 let mut ret = HashSet::new();
1378 ret.insert((Symbol::intern("target_os"), Some(Symbol::intern(os))));
1379 if let Some(ref fam) = sess.target.target.options.target_family {
1380 ret.insert((Symbol::intern("target_family"), Some(Symbol::intern(fam))));
1381 if fam == "windows" || fam == "unix" {
1382 ret.insert((Symbol::intern(fam), None));
1385 ret.insert((Symbol::intern("target_arch"), Some(Symbol::intern(arch))));
1386 ret.insert((Symbol::intern("target_endian"), Some(Symbol::intern(end))));
1387 ret.insert((Symbol::intern("target_pointer_width"), Some(Symbol::intern(wordsz))));
1388 ret.insert((Symbol::intern("target_env"), Some(Symbol::intern(env))));
1389 ret.insert((Symbol::intern("target_vendor"), Some(Symbol::intern(vendor))));
1390 if sess.target.target.options.has_elf_tls {
1391 ret.insert((Symbol::intern("target_thread_local"), None));
1393 for &i in &[8, 16, 32, 64, 128] {
1394 if i >= min_atomic_width && i <= max_atomic_width {
1395 let s = i.to_string();
1396 ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern(&s))));
1398 ret.insert((Symbol::intern("target_has_atomic"), Some(Symbol::intern("ptr"))));
1402 if sess.opts.debug_assertions {
1403 ret.insert((Symbol::intern("debug_assertions"), None));
1405 if sess.opts.crate_types.contains(&CrateTypeProcMacro) {
1406 ret.insert((Symbol::intern("proc_macro"), None));
1411 pub fn build_configuration(sess: &Session,
1412 mut user_cfg: ast::CrateConfig)
1413 -> ast::CrateConfig {
1414 // Combine the configuration requested by the session (command line) with
1415 // some default and generated configuration items
1416 let default_cfg = default_configuration(sess);
1417 // If the user wants a test runner, then add the test cfg
1419 user_cfg.insert((Symbol::intern("test"), None));
1421 user_cfg.extend(default_cfg.iter().cloned());
1425 pub fn build_target_config(opts: &Options, sp: &Handler) -> Config {
1426 let target = match Target::search(&opts.target_triple) {
1429 sp.struct_fatal(&format!("Error loading target specification: {}", e))
1430 .help("Use `--print target-list` for a list of built-in targets")
1436 let (isize_ty, usize_ty) = match &target.target_pointer_width[..] {
1437 "16" => (ast::IntTy::I16, ast::UintTy::U16),
1438 "32" => (ast::IntTy::I32, ast::UintTy::U32),
1439 "64" => (ast::IntTy::I64, ast::UintTy::U64),
1440 w => sp.fatal(&format!("target specification was invalid: \
1441 unrecognized target-pointer-width {}", w)).raise(),
1451 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
1452 pub enum OptionStability {
1458 pub struct RustcOptGroup {
1459 pub apply: Box<dyn Fn(&mut getopts::Options) -> &mut getopts::Options>,
1460 pub name: &'static str,
1461 pub stability: OptionStability,
1464 impl RustcOptGroup {
1465 pub fn is_stable(&self) -> bool {
1466 self.stability == OptionStability::Stable
1469 pub fn stable<F>(name: &'static str, f: F) -> RustcOptGroup
1470 where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
1475 stability: OptionStability::Stable,
1479 pub fn unstable<F>(name: &'static str, f: F) -> RustcOptGroup
1480 where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
1485 stability: OptionStability::Unstable,
1490 // The `opt` local module holds wrappers around the `getopts` API that
1491 // adds extra rustc-specific metadata to each option; such metadata
1492 // is exposed by . The public
1493 // functions below ending with `_u` are the functions that return
1494 // *unstable* options, i.e. options that are only enabled when the
1495 // user also passes the `-Z unstable-options` debugging flag.
1497 // The `fn opt_u` etc below are written so that we can use them
1498 // in the future; do not warn about them not being used right now.
1499 #![allow(dead_code)]
1502 use super::RustcOptGroup;
1504 pub type R = RustcOptGroup;
1505 pub type S = &'static str;
1507 fn stable<F>(name: S, f: F) -> R
1508 where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static
1510 RustcOptGroup::stable(name, f)
1513 fn unstable<F>(name: S, f: F) -> R
1514 where F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static
1516 RustcOptGroup::unstable(name, f)
1519 fn longer(a: S, b: S) -> S {
1520 if a.len() > b.len() {
1527 pub fn opt_s(a: S, b: S, c: S, d: S) -> R {
1528 stable(longer(a, b), move |opts| opts.optopt(a, b, c, d))
1530 pub fn multi_s(a: S, b: S, c: S, d: S) -> R {
1531 stable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
1533 pub fn flag_s(a: S, b: S, c: S) -> R {
1534 stable(longer(a, b), move |opts| opts.optflag(a, b, c))
1536 pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R {
1537 stable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d))
1539 pub fn flagmulti_s(a: S, b: S, c: S) -> R {
1540 stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
1543 pub fn opt(a: S, b: S, c: S, d: S) -> R {
1544 unstable(longer(a, b), move |opts| opts.optopt(a, b, c, d))
1546 pub fn multi(a: S, b: S, c: S, d: S) -> R {
1547 unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
1549 pub fn flag(a: S, b: S, c: S) -> R {
1550 unstable(longer(a, b), move |opts| opts.optflag(a, b, c))
1552 pub fn flagopt(a: S, b: S, c: S, d: S) -> R {
1553 unstable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d))
1555 pub fn flagmulti(a: S, b: S, c: S) -> R {
1556 unstable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
1560 /// Returns the "short" subset of the rustc command line options,
1561 /// including metadata for each option, such as whether the option is
1562 /// part of the stable long-term interface for rustc.
1563 pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
1565 opt::flag_s("h", "help", "Display this message"),
1566 opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"),
1567 opt::multi_s("L", "", "Add a directory to the library search path. The
1568 optional KIND can be one of dependency, crate, native,
1569 framework or all (the default).", "[KIND=]PATH"),
1570 opt::multi_s("l", "", "Link the generated crate(s) to the specified native
1571 library NAME. The optional KIND can be one of
1572 static, dylib, or framework. If omitted, dylib is
1573 assumed.", "[KIND=]NAME"),
1574 opt::multi_s("", "crate-type", "Comma separated list of types of crates
1575 for the compiler to emit",
1576 "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]"),
1577 opt::opt_s("", "crate-name", "Specify the name of the crate being built",
1579 opt::multi_s("", "emit", "Comma separated list of types of output for \
1580 the compiler to emit",
1581 "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]"),
1582 opt::multi_s("", "print", "Comma separated list of compiler information to \
1584 "[crate-name|file-names|sysroot|cfg|target-list|\
1585 target-cpus|target-features|relocation-models|\
1586 code-models|tls-models|target-spec-json|native-static-libs]"),
1587 opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"),
1588 opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
1589 opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
1590 opt::opt_s("", "out-dir", "Write output to compiler-chosen filename \
1592 opt::opt_s("", "explain", "Provide a detailed explanation of an error \
1594 opt::flag_s("", "test", "Build a test harness"),
1595 opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"),
1596 opt::multi_s("W", "warn", "Set lint warnings", "OPT"),
1597 opt::multi_s("A", "allow", "Set lint allowed", "OPT"),
1598 opt::multi_s("D", "deny", "Set lint denied", "OPT"),
1599 opt::multi_s("F", "forbid", "Set lint forbidden", "OPT"),
1600 opt::multi_s("", "cap-lints", "Set the most restrictive lint level. \
1601 More restrictive lints are capped at this \
1603 opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
1604 opt::flag_s("V", "version", "Print version info and exit"),
1605 opt::flag_s("v", "verbose", "Use verbose output"),
1609 /// Returns all rustc command line options, including metadata for
1610 /// each option, such as whether the option is part of the stable
1611 /// long-term interface for rustc.
1612 pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
1613 let mut opts = rustc_short_optgroups();
1615 opt::multi_s("", "extern", "Specify where an external rust library is located",
1617 opt::opt_s("", "sysroot", "Override the system root", "PATH"),
1618 opt::multi("Z", "", "Set internal debugging options", "FLAG"),
1619 opt::opt_s("", "error-format",
1620 "How errors and other messages are produced",
1621 "human|json|short"),
1622 opt::opt_s("", "color", "Configure coloring of output:
1623 auto = colorize, if output goes to a tty (default);
1624 always = always colorize output;
1625 never = never colorize output", "auto|always|never"),
1627 opt::opt("", "pretty",
1628 "Pretty-print the input instead of compiling;
1629 valid types are: `normal` (un-annotated source),
1630 `expanded` (crates expanded), or
1631 `expanded,identified` (fully parenthesized, AST nodes with IDs).",
1633 opt::multi_s("", "remap-path-prefix", "remap source names in output", "FROM=TO"),
1638 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
1639 pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig {
1640 cfgspecs.into_iter().map(|s| {
1641 let sess = parse::ParseSess::new(FilePathMapping::empty());
1643 parse::new_parser_from_source_str(&sess, FileName::CfgSpec, s.to_string());
1645 let meta_item = panictry!(parser.parse_meta_item());
1647 if parser.token != token::Eof {
1648 early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}", s))
1649 } else if meta_item.is_meta_item_list() {
1651 format!("invalid predicate in --cfg command line argument: `{}`", meta_item.name());
1652 early_error(ErrorOutputType::default(), &msg)
1655 (meta_item.name(), meta_item.value_str())
1656 }).collect::<ast::CrateConfig>()
1659 pub fn build_session_options_and_crate_config(matches: &getopts::Matches)
1660 -> (Options, ast::CrateConfig) {
1661 let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
1662 Some("auto") => ColorConfig::Auto,
1663 Some("always") => ColorConfig::Always,
1664 Some("never") => ColorConfig::Never,
1666 None => ColorConfig::Auto,
1669 early_error(ErrorOutputType::default(), &format!("argument for --color must be auto, \
1670 always or never (instead was `{}`)",
1675 // We need the opts_present check because the driver will send us Matches
1676 // with only stable options if no unstable options are used. Since error-format
1677 // is unstable, it will not be present. We have to use opts_present not
1678 // opt_present because the latter will panic.
1679 let error_format = if matches.opts_present(&["error-format".to_owned()]) {
1680 match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
1681 Some("human") => ErrorOutputType::HumanReadable(color),
1682 Some("json") => ErrorOutputType::Json(false),
1683 Some("pretty-json") => ErrorOutputType::Json(true),
1685 if nightly_options::is_unstable_enabled(matches) {
1686 ErrorOutputType::Short(color)
1688 early_error(ErrorOutputType::default(),
1689 &format!("the `-Z unstable-options` flag must also be passed to \
1690 enable the short error message option"));
1693 None => ErrorOutputType::HumanReadable(color),
1696 early_error(ErrorOutputType::HumanReadable(color),
1697 &format!("argument for --error-format must be `human`, `json` or \
1698 `short` (instead was `{}`)",
1703 ErrorOutputType::HumanReadable(color)
1706 let unparsed_crate_types = matches.opt_strs("crate-type");
1707 let crate_types = parse_crate_types_from_list(unparsed_crate_types)
1708 .unwrap_or_else(|e| early_error(error_format, &e[..]));
1710 let mut lint_opts = vec![];
1711 let mut describe_lints = false;
1713 for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] {
1714 for lint_name in matches.opt_strs(level.as_str()) {
1715 if lint_name == "help" {
1716 describe_lints = true;
1718 lint_opts.push((lint_name.replace("-", "_"), level));
1723 let lint_cap = matches.opt_str("cap-lints").map(|cap| {
1724 lint::Level::from_str(&cap).unwrap_or_else(|| {
1725 early_error(error_format, &format!("unknown lint level: `{}`", cap))
1729 let mut debugging_opts = build_debugging_options(matches, error_format);
1731 if !debugging_opts.unstable_options && error_format == ErrorOutputType::Json(true) {
1732 early_error(ErrorOutputType::Json(false), "--error-format=pretty-json is unstable");
1735 let mut output_types = BTreeMap::new();
1736 if !debugging_opts.parse_only {
1737 for list in matches.opt_strs("emit") {
1738 for output_type in list.split(',') {
1739 let mut parts = output_type.splitn(2, '=');
1740 let shorthand = parts.next().unwrap();
1741 let output_type = match OutputType::from_shorthand(shorthand) {
1742 Some(output_type) => output_type,
1743 None => early_error(error_format, &format!(
1744 "unknown emission type: `{}` - expected one of: {}",
1745 shorthand, OutputType::shorthands_display(),
1748 let path = parts.next().map(PathBuf::from);
1749 output_types.insert(output_type, path);
1753 if output_types.is_empty() {
1754 output_types.insert(OutputType::Exe, None);
1757 let mut cg = build_codegen_options(matches, error_format);
1758 let mut codegen_units = cg.codegen_units;
1759 let mut disable_thinlto = false;
1761 // Issue #30063: if user requests llvm-related output to one
1762 // particular path, disable codegen-units.
1763 let incompatible: Vec<_> = output_types.iter()
1764 .map(|ot_path| ot_path.0)
1766 !ot.is_compatible_with_codegen_units_and_single_output_file()
1768 .map(|ot| ot.shorthand())
1770 if !incompatible.is_empty() {
1771 match codegen_units {
1772 Some(n) if n > 1 => {
1773 if matches.opt_present("o") {
1774 for ot in &incompatible {
1775 early_warn(error_format, &format!("--emit={} with -o incompatible with \
1776 -C codegen-units=N for N > 1",
1779 early_warn(error_format, "resetting to default -C codegen-units=1");
1780 codegen_units = Some(1);
1781 disable_thinlto = true;
1785 codegen_units = Some(1);
1786 disable_thinlto = true;
1791 if debugging_opts.query_threads == Some(0) {
1792 early_error(error_format, "Value for query threads must be a positive nonzero integer");
1795 if codegen_units == Some(0) {
1796 early_error(error_format, "Value for codegen units must be a positive nonzero integer");
1799 let incremental = match (&debugging_opts.incremental, &cg.incremental) {
1800 (&Some(ref path1), &Some(ref path2)) => {
1802 early_error(error_format,
1803 &format!("conflicting paths for `-Z incremental` and \
1804 `-C incremental` specified: {} versus {}",
1811 (&Some(ref path), &None) => Some(path),
1812 (&None, &Some(ref path)) => Some(path),
1813 (&None, &None) => None,
1814 }.map(|m| PathBuf::from(m));
1816 if cg.lto != Lto::No && incremental.is_some() {
1817 early_error(error_format, "can't perform LTO when compiling incrementally");
1820 let mut prints = Vec::<PrintRequest>::new();
1821 if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
1822 prints.push(PrintRequest::TargetCPUs);
1823 cg.target_cpu = None;
1825 if cg.target_feature == "help" {
1826 prints.push(PrintRequest::TargetFeatures);
1827 cg.target_feature = "".to_string();
1829 if cg.relocation_model.as_ref().map_or(false, |s| s == "help") {
1830 prints.push(PrintRequest::RelocationModels);
1831 cg.relocation_model = None;
1833 if cg.code_model.as_ref().map_or(false, |s| s == "help") {
1834 prints.push(PrintRequest::CodeModels);
1835 cg.code_model = None;
1837 if debugging_opts.tls_model.as_ref().map_or(false, |s| s == "help") {
1838 prints.push(PrintRequest::TlsModels);
1839 debugging_opts.tls_model = None;
1844 let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
1845 let target = matches.opt_str("target").unwrap_or(
1846 host_triple().to_string());
1848 if matches.opt_present("O") {
1849 if cg.opt_level.is_some() {
1850 early_error(error_format, "-O and -C opt-level both provided");
1854 match (cg.opt_level.as_ref().map(String::as_ref),
1855 nightly_options::is_nightly_build()) {
1856 (None, _) => OptLevel::No,
1857 (Some("0"), _) => OptLevel::No,
1858 (Some("1"), _) => OptLevel::Less,
1859 (Some("2"), _) => OptLevel::Default,
1860 (Some("3"), _) => OptLevel::Aggressive,
1861 (Some("s"), true) => OptLevel::Size,
1862 (Some("z"), true) => OptLevel::SizeMin,
1863 (Some("s"), false) | (Some("z"), false) => {
1864 early_error(error_format, &format!("the optimizations s or z are only \
1865 accepted on the nightly compiler"));
1868 early_error(error_format, &format!("optimization level needs to be \
1869 between 0-3 (instead was `{}`)",
1875 let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
1876 let debuginfo = if matches.opt_present("g") {
1877 if cg.debuginfo.is_some() {
1878 early_error(error_format, "-g and -C debuginfo both provided");
1882 match cg.debuginfo {
1883 None | Some(0) => NoDebugInfo,
1884 Some(1) => LimitedDebugInfo,
1885 Some(2) => FullDebugInfo,
1887 early_error(error_format, &format!("debug info level needs to be between \
1888 0-2 (instead was `{}`)",
1894 let mut search_paths = SearchPaths::new();
1895 for s in &matches.opt_strs("L") {
1896 search_paths.add_path(&s[..], error_format);
1899 let libs = matches.opt_strs("l").into_iter().map(|s| {
1900 // Parse string of the form "[KIND=]lib[:new_name]",
1901 // where KIND is one of "dylib", "framework", "static".
1902 let mut parts = s.splitn(2, '=');
1903 let kind = parts.next().unwrap();
1904 let (name, kind) = match (parts.next(), kind) {
1905 (None, name) => (name, None),
1906 (Some(name), "dylib") => (name, Some(cstore::NativeUnknown)),
1907 (Some(name), "framework") => (name, Some(cstore::NativeFramework)),
1908 (Some(name), "static") => (name, Some(cstore::NativeStatic)),
1909 (Some(name), "static-nobundle") => (name, Some(cstore::NativeStaticNobundle)),
1911 early_error(error_format, &format!("unknown library kind `{}`, expected \
1912 one of dylib, framework, or static",
1916 if kind == Some(cstore::NativeStaticNobundle) && !nightly_options::is_nightly_build() {
1917 early_error(error_format, &format!("the library kind 'static-nobundle' is only \
1918 accepted on the nightly compiler"));
1920 let mut name_parts = name.splitn(2, ':');
1921 let name = name_parts.next().unwrap();
1922 let new_name = name_parts.next();
1923 (name.to_string(), new_name.map(|n| n.to_string()), kind)
1926 let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
1927 let test = matches.opt_present("test");
1929 prints.extend(matches.opt_strs("print").into_iter().map(|s| {
1931 "crate-name" => PrintRequest::CrateName,
1932 "file-names" => PrintRequest::FileNames,
1933 "sysroot" => PrintRequest::Sysroot,
1934 "cfg" => PrintRequest::Cfg,
1935 "target-list" => PrintRequest::TargetList,
1936 "target-cpus" => PrintRequest::TargetCPUs,
1937 "target-features" => PrintRequest::TargetFeatures,
1938 "relocation-models" => PrintRequest::RelocationModels,
1939 "code-models" => PrintRequest::CodeModels,
1940 "tls-models" => PrintRequest::TlsModels,
1941 "native-static-libs" => PrintRequest::NativeStaticLibs,
1942 "target-spec-json" => {
1943 if nightly_options::is_unstable_enabled(matches) {
1944 PrintRequest::TargetSpec
1946 early_error(error_format,
1947 &format!("the `-Z unstable-options` flag must also be passed to \
1948 enable the target-spec-json print option"));
1952 early_error(error_format, &format!("unknown print request `{}`", req))
1957 let borrowck_mode = match debugging_opts.borrowck.as_ref().map(|s| &s[..]) {
1958 None | Some("ast") => BorrowckMode::Ast,
1959 Some("mir") => BorrowckMode::Mir,
1960 Some("compare") => BorrowckMode::Compare,
1962 early_error(error_format, &format!("unknown borrowck mode `{}`", m))
1966 if !cg.remark.is_empty() && debuginfo == NoDebugInfo {
1967 early_warn(error_format, "-C remark will not show source locations without \
1971 let mut externs = BTreeMap::new();
1972 for arg in &matches.opt_strs("extern") {
1973 let mut parts = arg.splitn(2, '=');
1974 let name = match parts.next() {
1976 None => early_error(error_format, "--extern value must not be empty"),
1978 let location = match parts.next() {
1980 None => early_error(error_format, "--extern value must be of the format `foo=bar`"),
1983 externs.entry(name.to_string())
1984 .or_insert_with(BTreeSet::new)
1985 .insert(location.to_string());
1988 let crate_name = matches.opt_str("crate-name");
1990 let remap_path_prefix = matches.opt_strs("remap-path-prefix")
1993 let mut parts = remap.rsplitn(2, '='); // reverse iterator
1994 let to = parts.next();
1995 let from = parts.next();
1997 (Some(from), Some(to)) => (PathBuf::from(from), PathBuf::from(to)),
1998 _ => early_error(error_format,
1999 "--remap-path-prefix must contain '=' between FROM and TO"),
2006 optimize: opt_level,
2011 output_types: OutputTypes(output_types),
2013 maybe_sysroot: sysroot_opt,
2014 target_triple: target,
2022 externs: Externs(externs),
2026 unstable_features: UnstableFeatures::from_environment(),
2028 actually_rustdoc: false,
2029 cli_forced_codegen_units: codegen_units,
2030 cli_forced_thinlto_off: disable_thinlto,
2036 pub fn parse_crate_types_from_list(list_list: Vec<String>)
2037 -> Result<Vec<CrateType>, String> {
2038 let mut crate_types: Vec<CrateType> = Vec::new();
2039 for unparsed_crate_type in &list_list {
2040 for part in unparsed_crate_type.split(',') {
2041 let new_part = match part {
2042 "lib" => default_lib_output(),
2043 "rlib" => CrateTypeRlib,
2044 "staticlib" => CrateTypeStaticlib,
2045 "dylib" => CrateTypeDylib,
2046 "cdylib" => CrateTypeCdylib,
2047 "bin" => CrateTypeExecutable,
2048 "proc-macro" => CrateTypeProcMacro,
2050 return Err(format!("unknown crate type: `{}`",
2054 if !crate_types.contains(&new_part) {
2055 crate_types.push(new_part)
2063 pub mod nightly_options {
2065 use syntax::feature_gate::UnstableFeatures;
2066 use super::{ErrorOutputType, OptionStability, RustcOptGroup};
2067 use session::early_error;
2069 pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
2070 is_nightly_build() && matches.opt_strs("Z").iter().any(|x| *x == "unstable-options")
2073 pub fn is_nightly_build() -> bool {
2074 UnstableFeatures::from_environment().is_nightly_build()
2077 pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) {
2078 let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options");
2079 let really_allows_unstable_options = UnstableFeatures::from_environment()
2080 .is_nightly_build();
2082 for opt in flags.iter() {
2083 if opt.stability == OptionStability::Stable {
2086 if !matches.opt_present(opt.name) {
2089 if opt.name != "Z" && !has_z_unstable_option {
2090 early_error(ErrorOutputType::default(),
2091 &format!("the `-Z unstable-options` flag must also be passed to enable \
2095 if really_allows_unstable_options {
2098 match opt.stability {
2099 OptionStability::Unstable => {
2100 let msg = format!("the option `{}` is only accepted on the \
2101 nightly compiler", opt.name);
2102 early_error(ErrorOutputType::default(), &msg);
2104 OptionStability::Stable => {}
2110 impl fmt::Display for CrateType {
2111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2113 CrateTypeExecutable => "bin".fmt(f),
2114 CrateTypeDylib => "dylib".fmt(f),
2115 CrateTypeRlib => "rlib".fmt(f),
2116 CrateTypeStaticlib => "staticlib".fmt(f),
2117 CrateTypeCdylib => "cdylib".fmt(f),
2118 CrateTypeProcMacro => "proc-macro".fmt(f),
2123 /// Commandline arguments passed to the compiler have to be incorporated with
2124 /// the dependency tracking system for incremental compilation. This module
2125 /// provides some utilities to make this more convenient.
2127 /// The values of all commandline arguments that are relevant for dependency
2128 /// tracking are hashed into a single value that determines whether the
2129 /// incremental compilation cache can be re-used or not. This hashing is done
2130 /// via the DepTrackingHash trait defined below, since the standard Hash
2131 /// implementation might not be suitable (e.g. arguments are stored in a Vec,
2132 /// the hash of which is order dependent, but we might not want the order of
2133 /// arguments to make a difference for the hash).
2135 /// However, since the value provided by Hash::hash often *is* suitable,
2136 /// especially for primitive types, there is the
2137 /// impl_dep_tracking_hash_via_hash!() macro that allows to simply reuse the
2138 /// Hash implementation for DepTrackingHash. It's important though that
2139 /// we have an opt-in scheme here, so one is hopefully forced to think about
2140 /// how the hash should be calculated when adding a new commandline argument.
2144 use session::search_paths::{PathKind, SearchPaths};
2145 use std::collections::BTreeMap;
2146 use std::hash::Hash;
2147 use std::path::PathBuf;
2148 use std::collections::hash_map::DefaultHasher;
2149 use super::{Passes, CrateType, OptLevel, DebugInfoLevel, Lto,
2150 OutputTypes, Externs, ErrorOutputType, Sanitizer, Epoch};
2151 use syntax::feature_gate::UnstableFeatures;
2152 use rustc_back::{PanicStrategy, RelroLevel};
2154 pub trait DepTrackingHash {
2155 fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
2158 macro_rules! impl_dep_tracking_hash_via_hash {
2160 impl DepTrackingHash for $t {
2161 fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
2162 Hash::hash(self, hasher);
2168 macro_rules! impl_dep_tracking_hash_for_sortable_vec_of {
2170 impl DepTrackingHash for Vec<$t> {
2171 fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
2172 let mut elems: Vec<&$t> = self.iter().collect();
2174 Hash::hash(&elems.len(), hasher);
2175 for (index, elem) in elems.iter().enumerate() {
2176 Hash::hash(&index, hasher);
2177 DepTrackingHash::hash(*elem, hasher, error_format);
2184 impl_dep_tracking_hash_via_hash!(bool);
2185 impl_dep_tracking_hash_via_hash!(usize);
2186 impl_dep_tracking_hash_via_hash!(u64);
2187 impl_dep_tracking_hash_via_hash!(String);
2188 impl_dep_tracking_hash_via_hash!(PathBuf);
2189 impl_dep_tracking_hash_via_hash!(lint::Level);
2190 impl_dep_tracking_hash_via_hash!(Option<bool>);
2191 impl_dep_tracking_hash_via_hash!(Option<usize>);
2192 impl_dep_tracking_hash_via_hash!(Option<String>);
2193 impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
2194 impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
2195 impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
2196 impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
2197 impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
2198 impl_dep_tracking_hash_via_hash!(Option<cstore::NativeLibraryKind>);
2199 impl_dep_tracking_hash_via_hash!(CrateType);
2200 impl_dep_tracking_hash_via_hash!(PanicStrategy);
2201 impl_dep_tracking_hash_via_hash!(RelroLevel);
2202 impl_dep_tracking_hash_via_hash!(Passes);
2203 impl_dep_tracking_hash_via_hash!(OptLevel);
2204 impl_dep_tracking_hash_via_hash!(Lto);
2205 impl_dep_tracking_hash_via_hash!(DebugInfoLevel);
2206 impl_dep_tracking_hash_via_hash!(UnstableFeatures);
2207 impl_dep_tracking_hash_via_hash!(Externs);
2208 impl_dep_tracking_hash_via_hash!(OutputTypes);
2209 impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
2210 impl_dep_tracking_hash_via_hash!(Sanitizer);
2211 impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
2212 impl_dep_tracking_hash_via_hash!(Epoch);
2214 impl_dep_tracking_hash_for_sortable_vec_of!(String);
2215 impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
2216 impl_dep_tracking_hash_for_sortable_vec_of!(CrateType);
2217 impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
2218 impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>,
2219 Option<cstore::NativeLibraryKind>));
2220 impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
2221 impl DepTrackingHash for SearchPaths {
2222 fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
2223 let mut elems: Vec<_> = self
2224 .iter(PathKind::All)
2227 Hash::hash(&elems, hasher);
2231 impl<T1, T2> DepTrackingHash for (T1, T2)
2232 where T1: DepTrackingHash,
2235 fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
2236 Hash::hash(&0, hasher);
2237 DepTrackingHash::hash(&self.0, hasher, error_format);
2238 Hash::hash(&1, hasher);
2239 DepTrackingHash::hash(&self.1, hasher, error_format);
2243 impl<T1, T2, T3> DepTrackingHash for (T1, T2, T3)
2244 where T1: DepTrackingHash,
2245 T2: DepTrackingHash,
2248 fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
2249 Hash::hash(&0, hasher);
2250 DepTrackingHash::hash(&self.0, hasher, error_format);
2251 Hash::hash(&1, hasher);
2252 DepTrackingHash::hash(&self.1, hasher, error_format);
2253 Hash::hash(&2, hasher);
2254 DepTrackingHash::hash(&self.2, hasher, error_format);
2258 // This is a stable hash because BTreeMap is a sorted container
2259 pub fn stable_hash(sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
2260 hasher: &mut DefaultHasher,
2261 error_format: ErrorOutputType) {
2262 for (key, sub_hash) in sub_hashes {
2263 // Using Hash::hash() instead of DepTrackingHash::hash() is fine for
2264 // the keys, as they are just plain strings
2265 Hash::hash(&key.len(), hasher);
2266 Hash::hash(key, hasher);
2267 sub_hash.hash(hasher, error_format);
2278 use session::config::{build_configuration, build_session_options_and_crate_config};
2279 use session::config::Lto;
2280 use session::build_session;
2281 use std::collections::{BTreeMap, BTreeSet};
2282 use std::iter::FromIterator;
2283 use std::path::PathBuf;
2284 use super::{OutputType, OutputTypes, Externs};
2285 use rustc_back::{PanicStrategy, RelroLevel};
2286 use syntax::symbol::Symbol;
2288 fn optgroups() -> getopts::Options {
2289 let mut opts = getopts::Options::new();
2290 for group in super::rustc_optgroups() {
2291 (group.apply)(&mut opts);
2296 fn mk_map<K: Ord, V>(entries: Vec<(K, V)>) -> BTreeMap<K, V> {
2297 BTreeMap::from_iter(entries.into_iter())
2300 fn mk_set<V: Ord>(entries: Vec<V>) -> BTreeSet<V> {
2301 BTreeSet::from_iter(entries.into_iter())
2304 // When the user supplies --test we should implicitly supply --cfg test
2306 fn test_switch_implies_cfg_test() {
2308 &match optgroups().parse(&["--test".to_string()]) {
2310 Err(f) => panic!("test_switch_implies_cfg_test: {}", f)
2312 let registry = errors::registry::Registry::new(&[]);
2313 let (sessopts, cfg) = build_session_options_and_crate_config(matches);
2314 let sess = build_session(sessopts, None, registry);
2315 let cfg = build_configuration(&sess, cfg);
2316 assert!(cfg.contains(&(Symbol::intern("test"), None)));
2319 // When the user supplies --test and --cfg test, don't implicitly add
2320 // another --cfg test
2322 fn test_switch_implies_cfg_test_unless_cfg_test() {
2324 &match optgroups().parse(&["--test".to_string(), "--cfg=test".to_string()]) {
2327 panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f)
2330 let registry = errors::registry::Registry::new(&[]);
2331 let (sessopts, cfg) = build_session_options_and_crate_config(matches);
2332 let sess = build_session(sessopts, None, registry);
2333 let cfg = build_configuration(&sess, cfg);
2334 let mut test_items = cfg.iter().filter(|&&(name, _)| name == "test");
2335 assert!(test_items.next().is_some());
2336 assert!(test_items.next().is_none());
2340 fn test_can_print_warnings() {
2342 let matches = optgroups().parse(&[
2343 "-Awarnings".to_string()
2345 let registry = errors::registry::Registry::new(&[]);
2346 let (sessopts, _) = build_session_options_and_crate_config(&matches);
2347 let sess = build_session(sessopts, None, registry);
2348 assert!(!sess.diagnostic().flags.can_emit_warnings);
2352 let matches = optgroups().parse(&[
2353 "-Awarnings".to_string(),
2354 "-Dwarnings".to_string()
2356 let registry = errors::registry::Registry::new(&[]);
2357 let (sessopts, _) = build_session_options_and_crate_config(&matches);
2358 let sess = build_session(sessopts, None, registry);
2359 assert!(sess.diagnostic().flags.can_emit_warnings);
2363 let matches = optgroups().parse(&[
2364 "-Adead_code".to_string()
2366 let registry = errors::registry::Registry::new(&[]);
2367 let (sessopts, _) = build_session_options_and_crate_config(&matches);
2368 let sess = build_session(sessopts, None, registry);
2369 assert!(sess.diagnostic().flags.can_emit_warnings);
2374 fn test_output_types_tracking_hash_different_paths() {
2375 let mut v1 = super::basic_options();
2376 let mut v2 = super::basic_options();
2377 let mut v3 = super::basic_options();
2379 v1.output_types = OutputTypes::new(&[(OutputType::Exe,
2380 Some(PathBuf::from("./some/thing")))]);
2381 v2.output_types = OutputTypes::new(&[(OutputType::Exe,
2382 Some(PathBuf::from("/some/thing")))]);
2383 v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
2385 assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
2386 assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
2387 assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
2390 assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
2391 assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
2392 assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
2396 fn test_output_types_tracking_hash_different_construction_order() {
2397 let mut v1 = super::basic_options();
2398 let mut v2 = super::basic_options();
2400 v1.output_types = OutputTypes::new(&[
2401 (OutputType::Exe, Some(PathBuf::from("./some/thing"))),
2402 (OutputType::Bitcode, Some(PathBuf::from("./some/thing.bc"))),
2405 v2.output_types = OutputTypes::new(&[
2406 (OutputType::Bitcode, Some(PathBuf::from("./some/thing.bc"))),
2407 (OutputType::Exe, Some(PathBuf::from("./some/thing"))),
2410 assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
2413 assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
2417 fn test_externs_tracking_hash_different_values() {
2418 let mut v1 = super::basic_options();
2419 let mut v2 = super::basic_options();
2420 let mut v3 = super::basic_options();
2422 v1.externs = Externs::new(mk_map(vec![
2423 (String::from("a"), mk_set(vec![String::from("b"),
2424 String::from("c")])),
2425 (String::from("d"), mk_set(vec![String::from("e"),
2426 String::from("f")])),
2429 v2.externs = Externs::new(mk_map(vec![
2430 (String::from("a"), mk_set(vec![String::from("b"),
2431 String::from("c")])),
2432 (String::from("X"), mk_set(vec![String::from("e"),
2433 String::from("f")])),
2436 v3.externs = Externs::new(mk_map(vec![
2437 (String::from("a"), mk_set(vec![String::from("b"),
2438 String::from("c")])),
2439 (String::from("d"), mk_set(vec![String::from("X"),
2440 String::from("f")])),
2443 assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
2444 assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
2445 assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
2448 assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
2449 assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
2450 assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
2454 fn test_externs_tracking_hash_different_construction_order() {
2455 let mut v1 = super::basic_options();
2456 let mut v2 = super::basic_options();
2457 let mut v3 = super::basic_options();
2459 v1.externs = Externs::new(mk_map(vec![
2460 (String::from("a"), mk_set(vec![String::from("b"),
2461 String::from("c")])),
2462 (String::from("d"), mk_set(vec![String::from("e"),
2463 String::from("f")])),
2466 v2.externs = Externs::new(mk_map(vec![
2467 (String::from("d"), mk_set(vec![String::from("e"),
2468 String::from("f")])),
2469 (String::from("a"), mk_set(vec![String::from("b"),
2470 String::from("c")])),
2473 v3.externs = Externs::new(mk_map(vec![
2474 (String::from("a"), mk_set(vec![String::from("b"),
2475 String::from("c")])),
2476 (String::from("d"), mk_set(vec![String::from("f"),
2477 String::from("e")])),
2480 assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
2481 assert_eq!(v1.dep_tracking_hash(), v3.dep_tracking_hash());
2482 assert_eq!(v2.dep_tracking_hash(), v3.dep_tracking_hash());
2485 assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
2486 assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
2487 assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
2491 fn test_lints_tracking_hash_different_values() {
2492 let mut v1 = super::basic_options();
2493 let mut v2 = super::basic_options();
2494 let mut v3 = super::basic_options();
2496 v1.lint_opts = vec![(String::from("a"), lint::Allow),
2497 (String::from("b"), lint::Warn),
2498 (String::from("c"), lint::Deny),
2499 (String::from("d"), lint::Forbid)];
2501 v2.lint_opts = vec![(String::from("a"), lint::Allow),
2502 (String::from("b"), lint::Warn),
2503 (String::from("X"), lint::Deny),
2504 (String::from("d"), lint::Forbid)];
2506 v3.lint_opts = vec![(String::from("a"), lint::Allow),
2507 (String::from("b"), lint::Warn),
2508 (String::from("c"), lint::Forbid),
2509 (String::from("d"), lint::Deny)];
2511 assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
2512 assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
2513 assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
2516 assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
2517 assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
2518 assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
2522 fn test_lints_tracking_hash_different_construction_order() {
2523 let mut v1 = super::basic_options();
2524 let mut v2 = super::basic_options();
2526 v1.lint_opts = vec![(String::from("a"), lint::Allow),
2527 (String::from("b"), lint::Warn),
2528 (String::from("c"), lint::Deny),
2529 (String::from("d"), lint::Forbid)];
2531 v2.lint_opts = vec![(String::from("a"), lint::Allow),
2532 (String::from("c"), lint::Deny),
2533 (String::from("b"), lint::Warn),
2534 (String::from("d"), lint::Forbid)];
2536 assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
2539 assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
2540 assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
2544 fn test_search_paths_tracking_hash_different_values() {
2545 let mut v1 = super::basic_options();
2546 let mut v2 = super::basic_options();
2547 let mut v3 = super::basic_options();
2548 let mut v4 = super::basic_options();
2549 let mut v5 = super::basic_options();
2552 v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
2553 v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
2554 v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
2555 v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
2556 v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
2559 v2.search_paths.add_path("native=XXX", super::ErrorOutputType::Json(false));
2560 v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
2561 v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
2562 v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
2563 v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
2566 v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
2567 v2.search_paths.add_path("crate=XXX", super::ErrorOutputType::Json(false));
2568 v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
2569 v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
2570 v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
2572 // Dependency changed
2573 v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
2574 v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
2575 v3.search_paths.add_path("dependency=XXX", super::ErrorOutputType::Json(false));
2576 v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
2577 v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
2579 // Framework changed
2580 v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
2581 v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
2582 v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
2583 v4.search_paths.add_path("framework=XXX", super::ErrorOutputType::Json(false));
2584 v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
2587 v5.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
2588 v5.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
2589 v5.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
2590 v5.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
2591 v5.search_paths.add_path("all=XXX", super::ErrorOutputType::Json(false));
2593 assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
2594 assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
2595 assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash());
2596 assert!(v1.dep_tracking_hash() != v5.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());
2602 assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
2603 assert_eq!(v5.dep_tracking_hash(), v5.clone().dep_tracking_hash());
2607 fn test_search_paths_tracking_hash_different_order() {
2608 let mut v1 = super::basic_options();
2609 let mut v2 = super::basic_options();
2610 let mut v3 = super::basic_options();
2611 let mut v4 = super::basic_options();
2614 v1.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
2615 v1.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
2616 v1.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
2617 v1.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
2618 v1.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
2620 v2.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
2621 v2.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
2622 v2.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
2623 v2.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
2624 v2.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
2626 v3.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
2627 v3.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
2628 v3.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
2629 v3.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
2630 v3.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
2632 v4.search_paths.add_path("all=mno", super::ErrorOutputType::Json(false));
2633 v4.search_paths.add_path("native=abc", super::ErrorOutputType::Json(false));
2634 v4.search_paths.add_path("crate=def", super::ErrorOutputType::Json(false));
2635 v4.search_paths.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
2636 v4.search_paths.add_path("framework=jkl", super::ErrorOutputType::Json(false));
2638 assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
2639 assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
2640 assert!(v1.dep_tracking_hash() == v4.dep_tracking_hash());
2643 assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
2644 assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
2645 assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
2646 assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
2650 fn test_native_libs_tracking_hash_different_values() {
2651 let mut v1 = super::basic_options();
2652 let mut v2 = super::basic_options();
2653 let mut v3 = super::basic_options();
2654 let mut v4 = super::basic_options();
2657 v1.libs = vec![(String::from("a"), None, Some(cstore::NativeStatic)),
2658 (String::from("b"), None, Some(cstore::NativeFramework)),
2659 (String::from("c"), None, Some(cstore::NativeUnknown))];
2662 v2.libs = vec![(String::from("a"), None, Some(cstore::NativeStatic)),
2663 (String::from("X"), None, Some(cstore::NativeFramework)),
2664 (String::from("c"), None, Some(cstore::NativeUnknown))];
2667 v3.libs = vec![(String::from("a"), None, Some(cstore::NativeStatic)),
2668 (String::from("b"), None, Some(cstore::NativeStatic)),
2669 (String::from("c"), None, Some(cstore::NativeUnknown))];
2672 v4.libs = vec![(String::from("a"), None, Some(cstore::NativeStatic)),
2673 (String::from("b"), Some(String::from("X")), Some(cstore::NativeFramework)),
2674 (String::from("c"), None, Some(cstore::NativeUnknown))];
2676 assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
2677 assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
2678 assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash());
2681 assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
2682 assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
2683 assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
2684 assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
2688 fn test_native_libs_tracking_hash_different_order() {
2689 let mut v1 = super::basic_options();
2690 let mut v2 = super::basic_options();
2691 let mut v3 = super::basic_options();
2694 v1.libs = vec![(String::from("a"), None, Some(cstore::NativeStatic)),
2695 (String::from("b"), None, Some(cstore::NativeFramework)),
2696 (String::from("c"), None, Some(cstore::NativeUnknown))];
2698 v2.libs = vec![(String::from("b"), None, Some(cstore::NativeFramework)),
2699 (String::from("a"), None, Some(cstore::NativeStatic)),
2700 (String::from("c"), None, Some(cstore::NativeUnknown))];
2702 v3.libs = vec![(String::from("c"), None, Some(cstore::NativeUnknown)),
2703 (String::from("a"), None, Some(cstore::NativeStatic)),
2704 (String::from("b"), None, Some(cstore::NativeFramework))];
2706 assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
2707 assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
2708 assert!(v2.dep_tracking_hash() == v3.dep_tracking_hash());
2711 assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
2712 assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
2713 assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
2717 fn test_codegen_options_tracking_hash() {
2718 let reference = super::basic_options();
2719 let mut opts = super::basic_options();
2721 // Make sure the changing an [UNTRACKED] option leaves the hash unchanged
2722 opts.cg.ar = Some(String::from("abc"));
2723 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2725 opts.cg.linker = Some(PathBuf::from("linker"));
2726 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2728 opts.cg.link_args = Some(vec![String::from("abc"), String::from("def")]);
2729 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2731 opts.cg.link_dead_code = true;
2732 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2734 opts.cg.rpath = true;
2735 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2737 opts.cg.extra_filename = String::from("extra-filename");
2738 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2740 opts.cg.codegen_units = Some(42);
2741 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2743 opts.cg.remark = super::SomePasses(vec![String::from("pass1"),
2744 String::from("pass2")]);
2745 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2747 opts.cg.save_temps = true;
2748 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2750 opts.cg.incremental = Some(String::from("abc"));
2751 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2754 // Make sure changing a [TRACKED] option changes the hash
2755 opts = reference.clone();
2756 opts.cg.lto = Lto::Fat;
2757 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2759 opts = reference.clone();
2760 opts.cg.target_cpu = Some(String::from("abc"));
2761 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2763 opts = reference.clone();
2764 opts.cg.target_feature = String::from("all the features, all of them");
2765 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2767 opts = reference.clone();
2768 opts.cg.passes = vec![String::from("1"), String::from("2")];
2769 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2771 opts = reference.clone();
2772 opts.cg.llvm_args = vec![String::from("1"), String::from("2")];
2773 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2775 opts = reference.clone();
2776 opts.cg.overflow_checks = Some(true);
2777 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2779 opts = reference.clone();
2780 opts.cg.no_prepopulate_passes = true;
2781 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2783 opts = reference.clone();
2784 opts.cg.no_vectorize_loops = true;
2785 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2787 opts = reference.clone();
2788 opts.cg.no_vectorize_slp = true;
2789 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2791 opts = reference.clone();
2792 opts.cg.soft_float = true;
2793 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2795 opts = reference.clone();
2796 opts.cg.prefer_dynamic = true;
2797 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2799 opts = reference.clone();
2800 opts.cg.no_integrated_as = true;
2801 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2803 opts = reference.clone();
2804 opts.cg.no_redzone = Some(true);
2805 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2807 opts = reference.clone();
2808 opts.cg.relocation_model = Some(String::from("relocation model"));
2809 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2811 opts = reference.clone();
2812 opts.cg.code_model = Some(String::from("code model"));
2813 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2815 opts = reference.clone();
2816 opts.debugging_opts.tls_model = Some(String::from("tls model"));
2817 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2819 opts = reference.clone();
2820 opts.cg.metadata = vec![String::from("A"), String::from("B")];
2821 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2823 opts = reference.clone();
2824 opts.cg.debuginfo = Some(0xdeadbeef);
2825 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2827 opts = reference.clone();
2828 opts.cg.debuginfo = Some(0xba5eba11);
2829 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2831 opts = reference.clone();
2832 opts.cg.debug_assertions = Some(true);
2833 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2835 opts = reference.clone();
2836 opts.cg.inline_threshold = Some(0xf007ba11);
2837 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2839 opts = reference.clone();
2840 opts.cg.panic = Some(PanicStrategy::Abort);
2841 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2845 fn test_debugging_options_tracking_hash() {
2846 let reference = super::basic_options();
2847 let mut opts = super::basic_options();
2849 // Make sure the changing an [UNTRACKED] option leaves the hash unchanged
2850 opts.debugging_opts.verbose = true;
2851 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2852 opts.debugging_opts.time_passes = true;
2853 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2854 opts.debugging_opts.count_llvm_insns = true;
2855 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2856 opts.debugging_opts.time_llvm_passes = true;
2857 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2858 opts.debugging_opts.input_stats = true;
2859 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2860 opts.debugging_opts.trans_stats = true;
2861 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2862 opts.debugging_opts.borrowck_stats = true;
2863 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2864 opts.debugging_opts.meta_stats = true;
2865 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2866 opts.debugging_opts.print_link_args = true;
2867 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2868 opts.debugging_opts.print_llvm_passes = true;
2869 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2870 opts.debugging_opts.ast_json = true;
2871 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2872 opts.debugging_opts.ast_json_noexpand = true;
2873 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2874 opts.debugging_opts.ls = true;
2875 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2876 opts.debugging_opts.save_analysis = true;
2877 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2878 opts.debugging_opts.flowgraph_print_loans = true;
2879 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2880 opts.debugging_opts.flowgraph_print_moves = true;
2881 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2882 opts.debugging_opts.flowgraph_print_assigns = true;
2883 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2884 opts.debugging_opts.flowgraph_print_all = true;
2885 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2886 opts.debugging_opts.print_region_graph = true;
2887 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2888 opts.debugging_opts.parse_only = true;
2889 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2890 opts.debugging_opts.incremental = Some(String::from("abc"));
2891 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2892 opts.debugging_opts.dump_dep_graph = true;
2893 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2894 opts.debugging_opts.query_dep_graph = true;
2895 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2896 opts.debugging_opts.no_analysis = true;
2897 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2898 opts.debugging_opts.unstable_options = true;
2899 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2900 opts.debugging_opts.trace_macros = true;
2901 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2902 opts.debugging_opts.keep_hygiene_data = true;
2903 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2904 opts.debugging_opts.keep_ast = true;
2905 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2906 opts.debugging_opts.print_trans_items = Some(String::from("abc"));
2907 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2908 opts.debugging_opts.dump_mir = Some(String::from("abc"));
2909 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2910 opts.debugging_opts.dump_mir_dir = String::from("abc");
2911 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2912 opts.debugging_opts.dump_mir_graphviz = true;
2913 assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2915 // Make sure changing a [TRACKED] option changes the hash
2916 opts = reference.clone();
2917 opts.debugging_opts.asm_comments = true;
2918 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2920 opts = reference.clone();
2921 opts.debugging_opts.no_verify = true;
2922 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2924 opts = reference.clone();
2925 opts.debugging_opts.no_landing_pads = true;
2926 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2928 opts = reference.clone();
2929 opts.debugging_opts.fewer_names = true;
2930 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2932 opts = reference.clone();
2933 opts.debugging_opts.no_trans = true;
2934 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2936 opts = reference.clone();
2937 opts.debugging_opts.treat_err_as_bug = true;
2938 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2940 opts = reference.clone();
2941 opts.debugging_opts.continue_parse_after_error = true;
2942 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2944 opts = reference.clone();
2945 opts.debugging_opts.extra_plugins = vec![String::from("plugin1"), String::from("plugin2")];
2946 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2948 opts = reference.clone();
2949 opts.debugging_opts.force_overflow_checks = Some(true);
2950 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2952 opts = reference.clone();
2953 opts.debugging_opts.enable_nonzeroing_move_hints = true;
2954 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2956 opts = reference.clone();
2957 opts.debugging_opts.show_span = Some(String::from("abc"));
2958 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2960 opts = reference.clone();
2961 opts.debugging_opts.mir_opt_level = 3;
2962 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
2964 opts = reference.clone();
2965 opts.debugging_opts.relro_level = Some(RelroLevel::Full);
2966 assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());