2014-05-06 23:38:01 +12:00
|
|
|
//! Contains infrastructure for configuring the compiler, including parsing
|
2019-09-06 03:57:44 +01:00
|
|
|
//! command-line options.
|
2018-04-19 13:56:26 -07:00
|
|
|
|
2019-12-17 23:22:55 +11:00
|
|
|
pub use crate::options::*;
|
|
|
|
|
2019-11-29 16:05:28 -05:00
|
|
|
use crate::lint;
|
2019-12-22 17:42:04 -05:00
|
|
|
use crate::search_paths::SearchPath;
|
2020-05-18 00:18:50 +03:00
|
|
|
use crate::utils::NativeLibKind;
|
2019-11-29 16:05:28 -05:00
|
|
|
use crate::{early_error, early_warn, Session};
|
2014-05-06 23:38:01 +12:00
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
use rustc_data_structures::fx::FxHashSet;
|
2019-11-29 16:05:28 -05:00
|
|
|
use rustc_data_structures::impl_stable_hash_via_hash;
|
2020-06-14 00:00:00 +00:00
|
|
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
2019-09-06 03:57:44 +01:00
|
|
|
|
2020-09-20 12:09:22 +02:00
|
|
|
use rustc_target::abi::{Align, TargetDataLayout};
|
2017-12-08 21:18:21 +02:00
|
|
|
use rustc_target::spec::{Target, TargetTriple};
|
2014-05-06 23:38:01 +12:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
use crate::parse::CrateConfig;
|
|
|
|
use rustc_feature::UnstableFeatures;
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST};
|
|
|
|
use rustc_span::source_map::{FileName, FilePathMapping};
|
|
|
|
use rustc_span::symbol::{sym, Symbol};
|
2020-03-30 22:17:15 -07:00
|
|
|
use rustc_span::SourceFileHashAlgorithm;
|
2014-05-06 23:38:01 +12:00
|
|
|
|
2019-11-29 16:05:28 -05:00
|
|
|
use rustc_errors::emitter::HumanReadableErrorType;
|
2020-03-30 22:17:15 -07:00
|
|
|
use rustc_errors::{ColorConfig, HandlerFlags};
|
2016-06-21 18:08:13 -04:00
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
use std::collections::btree_map::{
|
|
|
|
Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter,
|
|
|
|
};
|
2019-12-22 17:42:04 -05:00
|
|
|
use std::collections::{BTreeMap, BTreeSet};
|
2019-09-06 03:57:44 +01:00
|
|
|
use std::fmt;
|
2019-12-05 14:43:53 -08:00
|
|
|
use std::iter::{self, FromIterator};
|
2018-03-24 20:14:59 +01:00
|
|
|
use std::path::{Path, PathBuf};
|
2019-12-22 17:42:04 -05:00
|
|
|
use std::str::{self, FromStr};
|
2014-05-06 23:38:01 +12:00
|
|
|
|
2020-06-14 00:00:00 +00:00
|
|
|
bitflags! {
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Default, Encodable, Decodable)]
|
2020-06-14 00:00:00 +00:00
|
|
|
pub struct SanitizerSet: u8 {
|
|
|
|
const ADDRESS = 1 << 0;
|
|
|
|
const LEAK = 1 << 1;
|
|
|
|
const MEMORY = 1 << 2;
|
|
|
|
const THREAD = 1 << 3;
|
|
|
|
}
|
2016-12-29 23:28:11 -05:00
|
|
|
}
|
|
|
|
|
2020-06-14 00:00:00 +00:00
|
|
|
/// Formats a sanitizer set as a comma separated list of sanitizers' names.
|
|
|
|
impl fmt::Display for SanitizerSet {
|
2019-10-22 00:00:00 +00:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2020-06-14 00:00:00 +00:00
|
|
|
let mut first = true;
|
|
|
|
for s in *self {
|
|
|
|
let name = match s {
|
|
|
|
SanitizerSet::ADDRESS => "address",
|
|
|
|
SanitizerSet::LEAK => "leak",
|
|
|
|
SanitizerSet::MEMORY => "memory",
|
|
|
|
SanitizerSet::THREAD => "thread",
|
|
|
|
_ => panic!("unrecognized sanitizer {:?}", s),
|
|
|
|
};
|
|
|
|
if !first {
|
|
|
|
f.write_str(",")?;
|
|
|
|
}
|
|
|
|
f.write_str(name)?;
|
|
|
|
first = false;
|
2019-10-22 00:00:00 +00:00
|
|
|
}
|
2020-06-14 00:00:00 +00:00
|
|
|
Ok(())
|
2019-10-22 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-14 00:00:00 +00:00
|
|
|
impl IntoIterator for SanitizerSet {
|
|
|
|
type Item = SanitizerSet;
|
|
|
|
type IntoIter = std::vec::IntoIter<SanitizerSet>;
|
|
|
|
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
|
|
[SanitizerSet::ADDRESS, SanitizerSet::LEAK, SanitizerSet::MEMORY, SanitizerSet::THREAD]
|
|
|
|
.iter()
|
|
|
|
.copied()
|
|
|
|
.filter(|&s| self.contains(s))
|
|
|
|
.collect::<Vec<_>>()
|
|
|
|
.into_iter()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<CTX> HashStable<CTX> for SanitizerSet {
|
|
|
|
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
|
|
|
|
self.bits().hash_stable(ctx, hasher);
|
2019-11-15 00:00:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-03 12:36:12 +08:00
|
|
|
/// The different settings that the `-Z strip` flag can have.
|
|
|
|
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
|
|
|
pub enum Strip {
|
|
|
|
/// Do not strip at all.
|
|
|
|
None,
|
|
|
|
|
|
|
|
/// Strip debuginfo.
|
|
|
|
Debuginfo,
|
|
|
|
|
|
|
|
/// Strip all symbols.
|
|
|
|
Symbols,
|
|
|
|
}
|
|
|
|
|
2020-07-14 15:27:42 +01:00
|
|
|
/// The different settings that the `-C control-flow-guard` flag can have.
|
2020-01-13 13:25:39 +00:00
|
|
|
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
|
|
|
pub enum CFGuard {
|
|
|
|
/// Do not emit Control Flow Guard metadata or checks.
|
|
|
|
Disabled,
|
|
|
|
|
|
|
|
/// Emit Control Flow Guard metadata but no checks.
|
|
|
|
NoChecks,
|
|
|
|
|
|
|
|
/// Emit Control Flow Guard metadata and checks.
|
|
|
|
Checks,
|
|
|
|
}
|
|
|
|
|
2018-05-19 13:50:58 -04:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Hash)]
|
2014-05-06 23:38:01 +12:00
|
|
|
pub enum OptLevel {
|
2018-03-06 02:29:03 -03:00
|
|
|
No, // -O0
|
|
|
|
Less, // -O1
|
|
|
|
Default, // -O2
|
2016-03-27 12:42:47 -07:00
|
|
|
Aggressive, // -O3
|
2018-03-06 02:29:03 -03:00
|
|
|
Size, // -Os
|
|
|
|
SizeMin, // -Oz
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
|
2018-10-27 15:29:06 +03:00
|
|
|
impl_stable_hash_via_hash!(OptLevel);
|
|
|
|
|
2018-09-04 17:57:17 +02:00
|
|
|
/// This is what the `LtoCli` values get mapped to after resolving defaults and
|
|
|
|
/// and taking other command line options into account.
|
2019-10-20 15:54:53 +11:00
|
|
|
#[derive(Clone, PartialEq)]
|
2018-01-16 15:02:31 -08:00
|
|
|
pub enum Lto {
|
|
|
|
/// Don't do any LTO whatsoever
|
|
|
|
No,
|
|
|
|
|
|
|
|
/// Do a full crate graph LTO with ThinLTO
|
|
|
|
Thin,
|
|
|
|
|
|
|
|
/// Do a local graph LTO with ThinLTO (only relevant for multiple codegen
|
|
|
|
/// units).
|
|
|
|
ThinLocal,
|
|
|
|
|
|
|
|
/// Do a full crate graph LTO with "fat" LTO
|
|
|
|
Fat,
|
|
|
|
}
|
|
|
|
|
2018-09-04 17:57:17 +02:00
|
|
|
/// The different settings that the `-C lto` flag can have.
|
|
|
|
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
|
|
|
pub enum LtoCli {
|
|
|
|
/// `-C lto=no`
|
|
|
|
No,
|
|
|
|
/// `-C lto=yes`
|
|
|
|
Yes,
|
|
|
|
/// `-C lto`
|
|
|
|
NoParam,
|
|
|
|
/// `-C lto=thin`
|
|
|
|
Thin,
|
|
|
|
/// `-C lto=fat`
|
|
|
|
Fat,
|
|
|
|
/// No `-C lto` flag passed
|
|
|
|
Unspecified,
|
|
|
|
}
|
|
|
|
|
2020-08-29 10:55:46 -07:00
|
|
|
/// The different settings that the `-Z dump_mir_spanview` flag can have. `Statement` generates a
|
|
|
|
/// document highlighting each span of every statement (including terminators). `Terminator` and
|
|
|
|
/// `Block` highlight a single span per `BasicBlock`: the span of the block's `Terminator`, or a
|
|
|
|
/// computed span for the block, representing the entire range, covering the block's terminator and
|
|
|
|
/// all of its statements.
|
|
|
|
#[derive(Clone, Copy, PartialEq, Hash, Debug)]
|
|
|
|
pub enum MirSpanview {
|
|
|
|
/// Default `-Z dump_mir_spanview` or `-Z dump_mir_spanview=statement`
|
|
|
|
Statement,
|
|
|
|
/// `-Z dump_mir_spanview=terminator`
|
|
|
|
Terminator,
|
|
|
|
/// `-Z dump_mir_spanview=block`
|
|
|
|
Block,
|
|
|
|
}
|
|
|
|
|
2018-04-25 15:45:04 +02:00
|
|
|
#[derive(Clone, PartialEq, Hash)]
|
2019-02-01 15:15:43 +01:00
|
|
|
pub enum LinkerPluginLto {
|
2018-04-25 15:45:04 +02:00
|
|
|
LinkerPlugin(PathBuf),
|
2018-07-03 16:33:11 +02:00
|
|
|
LinkerPluginAuto,
|
2019-12-22 17:42:04 -05:00
|
|
|
Disabled,
|
2018-04-25 15:45:04 +02:00
|
|
|
}
|
|
|
|
|
2019-02-01 15:15:43 +01:00
|
|
|
impl LinkerPluginLto {
|
2018-07-06 13:58:25 +02:00
|
|
|
pub fn enabled(&self) -> bool {
|
2018-04-25 15:45:04 +02:00
|
|
|
match *self {
|
2019-12-22 17:42:04 -05:00
|
|
|
LinkerPluginLto::LinkerPlugin(_) | LinkerPluginLto::LinkerPluginAuto => true,
|
2019-02-01 15:15:43 +01:00
|
|
|
LinkerPluginLto::Disabled => false,
|
2018-04-25 15:45:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-04-10 13:46:37 +02:00
|
|
|
#[derive(Clone, PartialEq, Hash)]
|
2019-05-28 16:13:59 +02:00
|
|
|
pub enum SwitchWithOptPath {
|
2019-04-10 13:46:37 +02:00
|
|
|
Enabled(Option<PathBuf>),
|
|
|
|
Disabled,
|
|
|
|
}
|
|
|
|
|
2019-05-28 16:13:59 +02:00
|
|
|
impl SwitchWithOptPath {
|
2019-04-10 13:46:37 +02:00
|
|
|
pub fn enabled(&self) -> bool {
|
|
|
|
match *self {
|
2019-05-28 16:13:59 +02:00
|
|
|
SwitchWithOptPath::Enabled(_) => true,
|
|
|
|
SwitchWithOptPath::Disabled => false,
|
2019-04-10 13:46:37 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
|
|
#[derive(Encodable, Decodable)]
|
2019-01-29 07:24:32 +02:00
|
|
|
pub enum SymbolManglingVersion {
|
|
|
|
Legacy,
|
|
|
|
V0,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl_stable_hash_via_hash!(SymbolManglingVersion);
|
|
|
|
|
2016-08-02 16:53:58 -04:00
|
|
|
#[derive(Clone, Copy, PartialEq, Hash)]
|
2018-07-26 11:41:10 -06:00
|
|
|
pub enum DebugInfo {
|
|
|
|
None,
|
|
|
|
Limited,
|
|
|
|
Full,
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
|
|
|
|
#[derive(Encodable, Decodable)]
|
2014-11-15 20:30:33 -05:00
|
|
|
pub enum OutputType {
|
2015-09-30 10:08:37 -07:00
|
|
|
Bitcode,
|
|
|
|
Assembly,
|
|
|
|
LlvmAssembly,
|
2017-02-16 16:59:09 -05:00
|
|
|
Mir,
|
2016-12-23 19:39:20 +13:00
|
|
|
Metadata,
|
2015-09-30 10:08:37 -07:00
|
|
|
Object,
|
|
|
|
Exe,
|
|
|
|
DepInfo,
|
2014-11-15 20:30:33 -05:00
|
|
|
}
|
|
|
|
|
2018-08-03 16:41:30 -06:00
|
|
|
impl_stable_hash_via_hash!(OutputType);
|
2017-09-18 12:14:52 +02:00
|
|
|
|
2015-12-04 19:35:16 +01:00
|
|
|
impl OutputType {
|
|
|
|
fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
|
|
|
|
match *self {
|
2019-04-25 09:06:38 -07:00
|
|
|
OutputType::Exe | OutputType::DepInfo | OutputType::Metadata => true,
|
2018-03-06 02:29:03 -03:00
|
|
|
OutputType::Bitcode
|
|
|
|
| OutputType::Assembly
|
|
|
|
| OutputType::LlvmAssembly
|
|
|
|
| OutputType::Mir
|
2019-04-25 09:06:38 -07:00
|
|
|
| OutputType::Object => false,
|
2015-12-04 19:35:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn shorthand(&self) -> &'static str {
|
|
|
|
match *self {
|
|
|
|
OutputType::Bitcode => "llvm-bc",
|
|
|
|
OutputType::Assembly => "asm",
|
|
|
|
OutputType::LlvmAssembly => "llvm-ir",
|
2017-02-16 16:59:09 -05:00
|
|
|
OutputType::Mir => "mir",
|
2015-12-04 19:35:16 +01:00
|
|
|
OutputType::Object => "obj",
|
2016-12-23 19:39:20 +13:00
|
|
|
OutputType::Metadata => "metadata",
|
2015-12-04 19:35:16 +01:00
|
|
|
OutputType::Exe => "link",
|
|
|
|
OutputType::DepInfo => "dep-info",
|
|
|
|
}
|
|
|
|
}
|
2016-07-25 10:51:14 -04:00
|
|
|
|
2017-11-05 09:20:59 -05:00
|
|
|
fn from_shorthand(shorthand: &str) -> Option<Self> {
|
|
|
|
Some(match shorthand {
|
2018-03-06 02:29:03 -03:00
|
|
|
"asm" => OutputType::Assembly,
|
|
|
|
"llvm-ir" => OutputType::LlvmAssembly,
|
|
|
|
"mir" => OutputType::Mir,
|
|
|
|
"llvm-bc" => OutputType::Bitcode,
|
|
|
|
"obj" => OutputType::Object,
|
|
|
|
"metadata" => OutputType::Metadata,
|
|
|
|
"link" => OutputType::Exe,
|
|
|
|
"dep-info" => OutputType::DepInfo,
|
2017-11-05 09:20:59 -05:00
|
|
|
_ => return None,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn shorthands_display() -> String {
|
|
|
|
format!(
|
|
|
|
"`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`",
|
|
|
|
OutputType::Bitcode.shorthand(),
|
|
|
|
OutputType::Assembly.shorthand(),
|
|
|
|
OutputType::LlvmAssembly.shorthand(),
|
|
|
|
OutputType::Mir.shorthand(),
|
|
|
|
OutputType::Object.shorthand(),
|
|
|
|
OutputType::Metadata.shorthand(),
|
|
|
|
OutputType::Exe.shorthand(),
|
|
|
|
OutputType::DepInfo.shorthand(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2016-07-25 10:51:14 -04:00
|
|
|
pub fn extension(&self) -> &'static str {
|
|
|
|
match *self {
|
|
|
|
OutputType::Bitcode => "bc",
|
|
|
|
OutputType::Assembly => "s",
|
|
|
|
OutputType::LlvmAssembly => "ll",
|
2017-02-16 16:59:09 -05:00
|
|
|
OutputType::Mir => "mir",
|
2016-07-25 10:51:14 -04:00
|
|
|
OutputType::Object => "o",
|
2016-12-23 19:39:20 +13:00
|
|
|
OutputType::Metadata => "rmeta",
|
2016-07-25 10:51:14 -04:00
|
|
|
OutputType::DepInfo => "d",
|
|
|
|
OutputType::Exe => "",
|
|
|
|
}
|
|
|
|
}
|
2015-12-04 19:35:16 +01:00
|
|
|
}
|
|
|
|
|
2019-06-10 10:59:03 +02:00
|
|
|
/// The type of diagnostics output to generate.
|
2016-10-26 11:14:02 +13:00
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
|
|
|
pub enum ErrorOutputType {
|
2019-06-09 12:04:40 +02:00
|
|
|
/// Output meant for the consumption of humans.
|
2019-03-25 11:16:58 +01:00
|
|
|
HumanReadable(HumanReadableErrorType),
|
2019-06-09 12:04:40 +02:00
|
|
|
/// Output that's consumed by other tools such as `rustfix` or the `RLS`.
|
2019-03-12 13:06:43 +01:00
|
|
|
Json {
|
2019-06-10 10:59:03 +02:00
|
|
|
/// Render the JSON in a human readable way (with indents and newlines).
|
2019-03-12 13:06:43 +01:00
|
|
|
pretty: bool,
|
2019-06-09 12:04:40 +02:00
|
|
|
/// The JSON output includes a `rendered` field that includes the rendered
|
|
|
|
/// human output.
|
2019-03-25 11:16:58 +01:00
|
|
|
json_rendered: HumanReadableErrorType,
|
2019-03-12 13:06:43 +01:00
|
|
|
},
|
2016-10-26 11:14:02 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for ErrorOutputType {
|
2019-09-06 03:57:44 +01:00
|
|
|
fn default() -> Self {
|
|
|
|
Self::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto))
|
2016-10-26 11:14:02 +13:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-02 10:40:56 +03:00
|
|
|
/// Parameter to control path trimming.
|
|
|
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub enum TrimmedDefPaths {
|
|
|
|
/// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive query
|
|
|
|
Never,
|
|
|
|
/// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call `delay_good_path_bug`
|
|
|
|
Always,
|
|
|
|
/// `try_print_trimmed_def_path` calls the expensive query, the query calls `delay_good_path_bug`
|
|
|
|
GoodPath,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for TrimmedDefPaths {
|
|
|
|
fn default() -> Self {
|
|
|
|
Self::Never
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
|
|
|
|
/// *Do not* switch `BTreeMap` out for an unsorted container type! That would break
|
|
|
|
/// dependency tracking for command-line arguments.
|
2016-08-02 16:53:58 -04:00
|
|
|
#[derive(Clone, Hash)]
|
|
|
|
pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
|
|
|
|
|
2018-08-03 16:41:30 -06:00
|
|
|
impl_stable_hash_via_hash!(OutputTypes);
|
2017-09-18 12:14:52 +02:00
|
|
|
|
2016-08-02 16:53:58 -04:00
|
|
|
impl OutputTypes {
|
|
|
|
pub fn new(entries: &[(OutputType, Option<PathBuf>)]) -> OutputTypes {
|
2019-12-22 17:42:04 -05:00
|
|
|
OutputTypes(BTreeMap::from_iter(entries.iter().map(|&(k, ref v)| (k, v.clone()))))
|
2016-08-02 16:53:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get(&self, key: &OutputType) -> Option<&Option<PathBuf>> {
|
|
|
|
self.0.get(key)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn contains_key(&self, key: &OutputType) -> bool {
|
|
|
|
self.0.contains_key(key)
|
|
|
|
}
|
|
|
|
|
2019-06-21 23:49:03 +02:00
|
|
|
pub fn keys(&self) -> BTreeMapKeysIter<'_, OutputType, Option<PathBuf>> {
|
2016-08-02 16:53:58 -04:00
|
|
|
self.0.keys()
|
|
|
|
}
|
|
|
|
|
2019-06-21 23:49:03 +02:00
|
|
|
pub fn values(&self) -> BTreeMapValuesIter<'_, OutputType, Option<PathBuf>> {
|
2016-08-02 16:53:58 -04:00
|
|
|
self.0.values()
|
|
|
|
}
|
2016-12-29 13:23:38 +13:00
|
|
|
|
2018-03-28 00:13:34 +01:00
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
self.0.len()
|
|
|
|
}
|
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
// Returns `true` if any of the output types require codegen or linking.
|
2018-05-08 16:10:16 +03:00
|
|
|
pub fn should_codegen(&self) -> bool {
|
2016-12-29 13:23:38 +13:00
|
|
|
self.0.keys().any(|k| match *k {
|
2018-03-06 02:29:03 -03:00
|
|
|
OutputType::Bitcode
|
|
|
|
| OutputType::Assembly
|
|
|
|
| OutputType::LlvmAssembly
|
|
|
|
| OutputType::Mir
|
|
|
|
| OutputType::Object
|
|
|
|
| OutputType::Exe => true,
|
|
|
|
OutputType::Metadata | OutputType::DepInfo => false,
|
2016-12-29 13:23:38 +13:00
|
|
|
})
|
|
|
|
}
|
2016-08-02 16:53:58 -04:00
|
|
|
}
|
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Use tree-based collections to cheaply get a deterministic `Hash` implementation.
|
|
|
|
/// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That
|
|
|
|
/// would break dependency tracking for command-line arguments.
|
2019-10-20 15:54:53 +11:00
|
|
|
#[derive(Clone)]
|
2019-04-07 18:48:40 -04:00
|
|
|
pub struct Externs(BTreeMap<String, ExternEntry>);
|
2016-08-02 16:53:58 -04:00
|
|
|
|
2019-12-05 14:43:53 -08:00
|
|
|
#[derive(Clone, Debug)]
|
2019-03-24 23:06:32 -04:00
|
|
|
pub struct ExternEntry {
|
2019-12-05 14:43:53 -08:00
|
|
|
pub location: ExternLocation,
|
|
|
|
/// Indicates this is a "private" dependency for the
|
|
|
|
/// `exported_private_dependencies` lint.
|
|
|
|
///
|
|
|
|
/// This can be set with the `priv` option like
|
|
|
|
/// `--extern priv:name=foo.rlib`.
|
|
|
|
pub is_private_dep: bool,
|
|
|
|
/// Add the extern entry to the extern prelude.
|
|
|
|
///
|
|
|
|
/// This can be disabled with the `noprelude` option like
|
|
|
|
/// `--extern noprelude:name`.
|
|
|
|
pub add_prelude: bool,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
pub enum ExternLocation {
|
|
|
|
/// Indicates to look for the library in the search paths.
|
|
|
|
///
|
|
|
|
/// Added via `--extern name`.
|
|
|
|
FoundInLibrarySearchDirectories,
|
|
|
|
/// The locations where this extern entry must be found.
|
|
|
|
///
|
|
|
|
/// The `CrateLoader` is responsible for loading these and figuring out
|
|
|
|
/// which one to use.
|
|
|
|
///
|
|
|
|
/// Added via `--extern prelude_name=some_file.rlib`
|
|
|
|
ExactPaths(BTreeSet<String>),
|
2019-03-24 23:06:32 -04:00
|
|
|
}
|
2019-03-20 23:27:08 -04:00
|
|
|
|
2016-08-02 16:53:58 -04:00
|
|
|
impl Externs {
|
2019-04-07 18:48:40 -04:00
|
|
|
pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs {
|
2016-08-02 16:53:58 -04:00
|
|
|
Externs(data)
|
|
|
|
}
|
|
|
|
|
2019-04-07 18:48:40 -04:00
|
|
|
pub fn get(&self, key: &str) -> Option<&ExternEntry> {
|
2019-03-20 23:27:08 -04:00
|
|
|
self.0.get(key)
|
|
|
|
}
|
|
|
|
|
2019-06-21 23:49:03 +02:00
|
|
|
pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> {
|
2019-03-20 23:27:08 -04:00
|
|
|
self.0.iter()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-05 14:43:53 -08:00
|
|
|
impl ExternEntry {
|
|
|
|
fn new(location: ExternLocation) -> ExternEntry {
|
|
|
|
ExternEntry { location, is_private_dep: false, add_prelude: false }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn files(&self) -> Option<impl Iterator<Item = &String>> {
|
|
|
|
match &self.location {
|
|
|
|
ExternLocation::ExactPaths(set) => Some(set.iter()),
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-03-20 23:27:08 -04:00
|
|
|
|
2017-04-30 20:33:25 +02:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
2014-12-15 16:03:39 -08:00
|
|
|
pub enum PrintRequest {
|
|
|
|
FileNames,
|
|
|
|
Sysroot,
|
2020-03-01 14:33:52 +03:00
|
|
|
TargetLibdir,
|
2014-12-15 16:03:39 -08:00
|
|
|
CrateName,
|
2016-01-25 11:36:18 -08:00
|
|
|
Cfg,
|
2016-02-12 10:11:58 -05:00
|
|
|
TargetList,
|
2016-07-11 00:22:13 +10:00
|
|
|
TargetCPUs,
|
|
|
|
TargetFeatures,
|
|
|
|
RelocationModels,
|
|
|
|
CodeModels,
|
2017-10-31 18:24:04 +00:00
|
|
|
TlsModels,
|
2016-04-07 16:36:35 -05:00
|
|
|
TargetSpec,
|
2017-08-22 21:20:42 +01:00
|
|
|
NativeStaticLibs,
|
2014-12-15 16:03:39 -08:00
|
|
|
}
|
|
|
|
|
2019-10-20 15:54:53 +11:00
|
|
|
#[derive(Copy, Clone)]
|
2017-11-19 23:35:53 +01:00
|
|
|
pub enum BorrowckMode {
|
|
|
|
Mir,
|
2018-07-20 17:29:29 +02:00
|
|
|
Migrate,
|
2017-11-19 23:35:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl BorrowckMode {
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Returns whether we should run the MIR-based borrow check, but also fall back
|
2018-07-20 17:29:29 +02:00
|
|
|
/// on the AST borrow check if the MIR-based one errors.
|
|
|
|
pub fn migrate(self) -> bool {
|
|
|
|
match self {
|
|
|
|
BorrowckMode::Mir => false,
|
|
|
|
BorrowckMode::Migrate => true,
|
|
|
|
}
|
|
|
|
}
|
2017-11-19 23:35:53 +01:00
|
|
|
}
|
|
|
|
|
2014-11-27 07:21:26 -05:00
|
|
|
pub enum Input {
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Load source code from a file.
|
2015-02-26 21:00:43 -08:00
|
|
|
File(PathBuf),
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Load source code from a string.
|
2016-03-10 04:49:40 +01:00
|
|
|
Str {
|
2019-09-06 03:57:44 +01:00
|
|
|
/// A string that is shown in place of a filename.
|
2017-12-14 08:09:19 +01:00
|
|
|
name: FileName,
|
2019-09-06 03:57:44 +01:00
|
|
|
/// An anonymous string containing the source code.
|
2016-03-10 04:49:40 +01:00
|
|
|
input: String,
|
|
|
|
},
|
2014-11-27 07:21:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Input {
|
2018-10-10 15:30:53 +02:00
|
|
|
pub fn filestem(&self) -> &str {
|
2014-11-27 07:21:26 -05:00
|
|
|
match *self {
|
2018-10-10 15:30:53 +02:00
|
|
|
Input::File(ref ifile) => ifile.file_stem().unwrap().to_str().unwrap(),
|
|
|
|
Input::Str { .. } => "rust_out",
|
2014-11-27 07:21:26 -05:00
|
|
|
}
|
|
|
|
}
|
2018-05-10 20:13:25 +02:00
|
|
|
|
|
|
|
pub fn get_input(&mut self) -> Option<&mut String> {
|
|
|
|
match *self {
|
|
|
|
Input::File(_) => None,
|
|
|
|
Input::Str { ref mut input, .. } => Some(input),
|
|
|
|
}
|
|
|
|
}
|
2018-12-08 20:30:23 +01:00
|
|
|
|
|
|
|
pub fn source_name(&self) -> FileName {
|
|
|
|
match *self {
|
|
|
|
Input::File(ref ifile) => ifile.clone().into(),
|
|
|
|
Input::Str { ref name, .. } => name.clone(),
|
|
|
|
}
|
|
|
|
}
|
2014-11-27 07:21:26 -05:00
|
|
|
}
|
|
|
|
|
2018-08-03 16:41:30 -06:00
|
|
|
#[derive(Clone, Hash)]
|
2014-11-27 07:21:26 -05:00
|
|
|
pub struct OutputFilenames {
|
2015-02-26 21:00:43 -08:00
|
|
|
pub out_directory: PathBuf,
|
2020-01-21 09:54:58 -05:00
|
|
|
filestem: String,
|
2015-02-26 21:00:43 -08:00
|
|
|
pub single_output_file: Option<PathBuf>,
|
2016-08-02 16:53:58 -04:00
|
|
|
pub outputs: OutputTypes,
|
2014-11-27 07:21:26 -05:00
|
|
|
}
|
|
|
|
|
2018-08-03 16:41:30 -06:00
|
|
|
impl_stable_hash_via_hash!(OutputFilenames);
|
2017-09-18 12:14:52 +02:00
|
|
|
|
2020-01-23 21:48:48 +11:00
|
|
|
pub const RLINK_EXT: &str = "rlink";
|
2017-11-03 22:41:15 +03:00
|
|
|
pub const RUST_CGU_EXT: &str = "rcgu";
|
2016-05-13 20:48:32 -04:00
|
|
|
|
2014-11-27 07:21:26 -05:00
|
|
|
impl OutputFilenames {
|
2020-01-21 09:50:22 -05:00
|
|
|
pub fn new(
|
|
|
|
out_directory: PathBuf,
|
|
|
|
out_filestem: String,
|
|
|
|
single_output_file: Option<PathBuf>,
|
|
|
|
extra: String,
|
|
|
|
outputs: OutputTypes,
|
|
|
|
) -> Self {
|
2020-01-21 09:54:58 -05:00
|
|
|
OutputFilenames {
|
|
|
|
out_directory,
|
|
|
|
single_output_file,
|
|
|
|
outputs,
|
|
|
|
filestem: format!("{}{}", out_filestem, extra),
|
|
|
|
}
|
2020-01-21 09:50:22 -05:00
|
|
|
}
|
|
|
|
|
2015-02-26 21:00:43 -08:00
|
|
|
pub fn path(&self, flavor: OutputType) -> PathBuf {
|
2018-03-06 02:29:03 -03:00
|
|
|
self.outputs
|
|
|
|
.get(&flavor)
|
|
|
|
.and_then(|p| p.to_owned())
|
2015-09-30 10:08:37 -07:00
|
|
|
.or_else(|| self.single_output_file.clone())
|
2016-05-13 20:48:32 -04:00
|
|
|
.unwrap_or_else(|| self.temp_path(flavor, None))
|
2014-11-27 07:21:26 -05:00
|
|
|
}
|
|
|
|
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Gets the path where a compilation artifact of the given type for the
|
2016-05-13 20:48:32 -04:00
|
|
|
/// given codegen unit should be placed on disk. If codegen_unit_name is
|
|
|
|
/// None, a path distinct from those of any codegen unit will be generated.
|
2018-03-06 02:29:03 -03:00
|
|
|
pub fn temp_path(&self, flavor: OutputType, codegen_unit_name: Option<&str>) -> PathBuf {
|
2016-07-25 10:51:14 -04:00
|
|
|
let extension = flavor.extension();
|
2016-05-13 20:48:32 -04:00
|
|
|
self.temp_path_ext(extension, codegen_unit_name)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Like temp_path, but also supports things where there is no corresponding
|
2019-02-08 14:53:55 +01:00
|
|
|
/// OutputType, like noopt-bitcode or lto-bitcode.
|
2018-03-06 02:29:03 -03:00
|
|
|
pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf {
|
2016-05-13 20:48:32 -04:00
|
|
|
let mut extension = String::new();
|
|
|
|
|
|
|
|
if let Some(codegen_unit_name) = codegen_unit_name {
|
rustc: Implement ThinLTO
This commit is an implementation of LLVM's ThinLTO for consumption in rustc
itself. Currently today LTO works by merging all relevant LLVM modules into one
and then running optimization passes. "Thin" LTO operates differently by having
more sharded work and allowing parallelism opportunities between optimizing
codegen units. Further down the road Thin LTO also allows *incremental* LTO
which should enable even faster release builds without compromising on the
performance we have today.
This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then
also implements two forms of ThinLTO:
* In one mode we'll *only* perform ThinLTO over the codegen units produced in a
single compilation. That is, we won't load upstream rlibs, but we'll instead
just perform ThinLTO amongst all codegen units produced by the compiler for
the local crate. This is intended to emulate a desired end point where we have
codegen units turned on by default for all crates and ThinLTO allows us to do
this without performance loss.
* In anther mode, like full LTO today, we'll optimize all upstream dependencies
in "thin" mode. Unlike today, however, this LTO step is fully parallelized so
should finish much more quickly.
There's a good bit of comments about what the implementation is doing and where
it came from, but the tl;dr; is that currently most of the support here is
copied from upstream LLVM. This code duplication is done for a number of
reasons:
* Controlling parallelism means we can use the existing jobserver support to
avoid overloading machines.
* We will likely want a slightly different form of incremental caching which
integrates with our own incremental strategy, but this is yet to be
determined.
* This buys us some flexibility about when/where we run ThinLTO, as well as
having it tailored to fit our needs for the time being.
* Finally this allows us to reuse some artifacts such as our `TargetMachine`
creation, where all our options we used today aren't necessarily supported by
upstream LLVM yet.
My hope is that we can get some experience with this copy/paste in tree and then
eventually upstream some work to LLVM itself to avoid the duplication while
still ensuring our needs are met. Otherwise I fear that maintaining these
bindings may be quite costly over the years with LLVM updates!
2017-07-23 08:14:38 -07:00
|
|
|
extension.push_str(codegen_unit_name);
|
2014-11-27 07:21:26 -05:00
|
|
|
}
|
2016-05-13 20:48:32 -04:00
|
|
|
|
|
|
|
if !ext.is_empty() {
|
|
|
|
if !extension.is_empty() {
|
2020-09-10 13:57:40 +02:00
|
|
|
extension.push('.');
|
rustc: Implement ThinLTO
This commit is an implementation of LLVM's ThinLTO for consumption in rustc
itself. Currently today LTO works by merging all relevant LLVM modules into one
and then running optimization passes. "Thin" LTO operates differently by having
more sharded work and allowing parallelism opportunities between optimizing
codegen units. Further down the road Thin LTO also allows *incremental* LTO
which should enable even faster release builds without compromising on the
performance we have today.
This commit uses a `-Z thinlto` flag to gate whether ThinLTO is enabled. It then
also implements two forms of ThinLTO:
* In one mode we'll *only* perform ThinLTO over the codegen units produced in a
single compilation. That is, we won't load upstream rlibs, but we'll instead
just perform ThinLTO amongst all codegen units produced by the compiler for
the local crate. This is intended to emulate a desired end point where we have
codegen units turned on by default for all crates and ThinLTO allows us to do
this without performance loss.
* In anther mode, like full LTO today, we'll optimize all upstream dependencies
in "thin" mode. Unlike today, however, this LTO step is fully parallelized so
should finish much more quickly.
There's a good bit of comments about what the implementation is doing and where
it came from, but the tl;dr; is that currently most of the support here is
copied from upstream LLVM. This code duplication is done for a number of
reasons:
* Controlling parallelism means we can use the existing jobserver support to
avoid overloading machines.
* We will likely want a slightly different form of incremental caching which
integrates with our own incremental strategy, but this is yet to be
determined.
* This buys us some flexibility about when/where we run ThinLTO, as well as
having it tailored to fit our needs for the time being.
* Finally this allows us to reuse some artifacts such as our `TargetMachine`
creation, where all our options we used today aren't necessarily supported by
upstream LLVM yet.
My hope is that we can get some experience with this copy/paste in tree and then
eventually upstream some work to LLVM itself to avoid the duplication while
still ensuring our needs are met. Otherwise I fear that maintaining these
bindings may be quite costly over the years with LLVM updates!
2017-07-23 08:14:38 -07:00
|
|
|
extension.push_str(RUST_CGU_EXT);
|
2020-09-10 13:57:40 +02:00
|
|
|
extension.push('.');
|
2016-05-13 20:48:32 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
extension.push_str(ext);
|
|
|
|
}
|
|
|
|
|
2020-01-21 09:57:50 -05:00
|
|
|
self.with_extension(&extension)
|
2014-11-27 07:21:26 -05:00
|
|
|
}
|
|
|
|
|
2015-02-26 21:00:43 -08:00
|
|
|
pub fn with_extension(&self, extension: &str) -> PathBuf {
|
2020-01-21 09:57:50 -05:00
|
|
|
let mut path = self.out_directory.join(&self.filestem);
|
|
|
|
path.set_extension(extension);
|
|
|
|
path
|
2014-11-27 07:21:26 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-11-15 20:30:33 -05:00
|
|
|
pub fn host_triple() -> &'static str {
|
|
|
|
// Get the host triple out of the build environment. This ensures that our
|
|
|
|
// idea of the host triple is the same as for the set of libraries we've
|
|
|
|
// actually built. We can't just take LLVM's host triple because they
|
|
|
|
// normalize all ix86 architectures to i386.
|
|
|
|
//
|
|
|
|
// Instead of grabbing the host triple (for the current host), we grab (at
|
|
|
|
// compile time) the target triple that this rustc is built with and
|
|
|
|
// calling that (at runtime) the host triple.
|
2018-03-06 02:29:03 -03:00
|
|
|
(option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE")
|
2014-11-15 20:30:33 -05:00
|
|
|
}
|
|
|
|
|
2018-07-26 12:36:11 -06:00
|
|
|
impl Default for Options {
|
|
|
|
fn default() -> Options {
|
|
|
|
Options {
|
|
|
|
crate_types: Vec::new(),
|
|
|
|
optimize: OptLevel::No,
|
|
|
|
debuginfo: DebugInfo::None,
|
|
|
|
lint_opts: Vec::new(),
|
|
|
|
lint_cap: None,
|
|
|
|
describe_lints: false,
|
|
|
|
output_types: OutputTypes(BTreeMap::new()),
|
2018-11-22 16:33:07 +11:00
|
|
|
search_paths: vec![],
|
2018-07-26 12:36:11 -06:00
|
|
|
maybe_sysroot: None,
|
|
|
|
target_triple: TargetTriple::from_triple(host_triple()),
|
|
|
|
test: false,
|
|
|
|
incremental: None,
|
|
|
|
debugging_opts: basic_debugging_options(),
|
|
|
|
prints: Vec::new(),
|
2019-01-26 17:25:37 +00:00
|
|
|
borrowck_mode: BorrowckMode::Migrate,
|
2018-07-26 12:36:11 -06:00
|
|
|
cg: basic_codegen_options(),
|
|
|
|
error_format: ErrorOutputType::default(),
|
|
|
|
externs: Externs(BTreeMap::new()),
|
|
|
|
crate_name: None,
|
|
|
|
alt_std_name: None,
|
|
|
|
libs: Vec::new(),
|
|
|
|
unstable_features: UnstableFeatures::Disallow,
|
|
|
|
debug_assertions: true,
|
|
|
|
actually_rustdoc: false,
|
2020-09-02 10:40:56 +03:00
|
|
|
trimmed_def_paths: TrimmedDefPaths::default(),
|
2018-07-26 12:36:11 -06:00
|
|
|
cli_forced_codegen_units: None,
|
|
|
|
cli_forced_thinlto_off: false,
|
|
|
|
remap_path_prefix: Vec::new(),
|
|
|
|
edition: DEFAULT_EDITION,
|
2019-07-17 12:52:56 -07:00
|
|
|
json_artifact_notifications: false,
|
2019-11-03 21:42:03 -05:00
|
|
|
pretty: None,
|
2018-07-26 12:36:11 -06:00
|
|
|
}
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-28 17:43:36 -04:00
|
|
|
impl Options {
|
2019-02-08 14:53:55 +01:00
|
|
|
/// Returns `true` if there is a reason to build the dep graph.
|
2016-03-28 17:43:36 -04:00
|
|
|
pub fn build_dep_graph(&self) -> bool {
|
2019-12-22 17:42:04 -05:00
|
|
|
self.incremental.is_some()
|
|
|
|
|| self.debugging_opts.dump_dep_graph
|
2018-03-06 02:29:03 -03:00
|
|
|
|| self.debugging_opts.query_dep_graph
|
2016-03-28 17:43:36 -04:00
|
|
|
}
|
2016-07-13 17:03:02 -04:00
|
|
|
|
2017-06-23 16:37:12 +02:00
|
|
|
#[inline(always)]
|
|
|
|
pub fn enable_dep_node_debug_strs(&self) -> bool {
|
2018-03-06 02:29:03 -03:00
|
|
|
cfg!(debug_assertions)
|
|
|
|
&& (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info)
|
2017-06-23 16:37:12 +02:00
|
|
|
}
|
|
|
|
|
2017-04-24 19:01:19 +02:00
|
|
|
pub fn file_path_mapping(&self) -> FilePathMapping {
|
2018-02-18 15:05:24 -08:00
|
|
|
FilePathMapping::new(self.remap_path_prefix.clone())
|
2017-04-24 19:01:19 +02:00
|
|
|
}
|
2017-12-18 15:35:45 +00:00
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Returns `true` if there will be an output file generated.
|
2017-12-18 15:35:45 +00:00
|
|
|
pub fn will_create_output_file(&self) -> bool {
|
|
|
|
!self.debugging_opts.parse_only && // The file is just being parsed
|
|
|
|
!self.debugging_opts.ls // The file is just being queried
|
|
|
|
}
|
2018-07-26 13:20:47 -06:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn share_generics(&self) -> bool {
|
|
|
|
match self.debugging_opts.share_generics {
|
|
|
|
Some(setting) => setting,
|
2019-12-22 17:42:04 -05:00
|
|
|
None => match self.optimize {
|
|
|
|
OptLevel::No | OptLevel::Less | OptLevel::Size | OptLevel::SizeMin => true,
|
|
|
|
OptLevel::Default | OptLevel::Aggressive => false,
|
|
|
|
},
|
2018-07-26 13:20:47 -06:00
|
|
|
}
|
|
|
|
}
|
2016-03-28 17:43:36 -04:00
|
|
|
}
|
|
|
|
|
2019-12-30 00:23:19 +03:00
|
|
|
impl DebuggingOptions {
|
2019-12-29 23:07:23 +03:00
|
|
|
pub fn diagnostic_handler_flags(&self, can_emit_warnings: bool) -> HandlerFlags {
|
|
|
|
HandlerFlags {
|
|
|
|
can_emit_warnings,
|
|
|
|
treat_err_as_bug: self.treat_err_as_bug,
|
|
|
|
dont_buffer_diagnostics: self.dont_buffer_diagnostics,
|
|
|
|
report_delayed_bugs: self.report_delayed_bugs,
|
2019-12-15 17:12:30 +02:00
|
|
|
macro_backtrace: self.macro_backtrace,
|
2020-04-02 16:44:47 +11:00
|
|
|
deduplicate_diagnostics: self.deduplicate_diagnostics,
|
2019-12-29 23:07:23 +03:00
|
|
|
}
|
|
|
|
}
|
2019-12-30 00:23:19 +03:00
|
|
|
}
|
|
|
|
|
2019-01-13 13:06:26 +01:00
|
|
|
// The type of entry function, so users can have their own entry functions
|
|
|
|
#[derive(Copy, Clone, PartialEq, Hash, Debug)]
|
2014-05-06 23:38:01 +12:00
|
|
|
pub enum EntryFnType {
|
2018-07-26 11:29:45 -06:00
|
|
|
Main,
|
|
|
|
Start,
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
|
2019-01-13 13:06:26 +01:00
|
|
|
impl_stable_hash_via_hash!(EntryFnType);
|
|
|
|
|
2020-06-11 15:49:57 +01:00
|
|
|
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)]
|
2014-05-06 23:38:01 +12:00
|
|
|
pub enum CrateType {
|
2018-07-26 11:13:11 -06:00
|
|
|
Executable,
|
|
|
|
Dylib,
|
|
|
|
Rlib,
|
|
|
|
Staticlib,
|
|
|
|
Cdylib,
|
|
|
|
ProcMacro,
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
|
2019-11-29 16:05:28 -05:00
|
|
|
impl_stable_hash_via_hash!(CrateType);
|
|
|
|
|
2016-08-02 16:53:58 -04:00
|
|
|
#[derive(Clone, Hash)]
|
2014-09-12 08:17:58 -07:00
|
|
|
pub enum Passes {
|
2018-07-26 11:22:14 -06:00
|
|
|
Some(Vec<String>),
|
|
|
|
All,
|
2014-09-12 08:17:58 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Passes {
|
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
match *self {
|
2018-07-26 11:22:14 -06:00
|
|
|
Passes::Some(ref v) => v.is_empty(),
|
|
|
|
Passes::All => false,
|
2014-09-12 08:17:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-25 13:23:18 -04:00
|
|
|
pub const fn default_lib_output() -> CrateType {
|
2018-07-26 11:13:11 -06:00
|
|
|
CrateType::Rlib
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
|
2019-11-19 20:02:16 -05:00
|
|
|
pub fn default_configuration(sess: &Session) -> CrateConfig {
|
2020-11-08 14:57:55 +03:00
|
|
|
let end = &sess.target.endian;
|
2020-10-15 11:44:00 +02:00
|
|
|
let arch = &sess.target.arch;
|
|
|
|
let wordsz = sess.target.pointer_width.to_string();
|
2020-11-08 14:57:55 +03:00
|
|
|
let os = &sess.target.os;
|
|
|
|
let env = &sess.target.env;
|
|
|
|
let vendor = &sess.target.vendor;
|
2020-10-15 11:44:00 +02:00
|
|
|
let min_atomic_width = sess.target.min_atomic_width();
|
|
|
|
let max_atomic_width = sess.target.max_atomic_width();
|
2020-11-08 14:27:51 +03:00
|
|
|
let atomic_cas = sess.target.atomic_cas;
|
2020-10-15 11:44:00 +02:00
|
|
|
let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| {
|
2020-09-20 12:39:07 +02:00
|
|
|
sess.fatal(&err);
|
|
|
|
});
|
2014-05-06 23:38:01 +12:00
|
|
|
|
2018-08-18 13:55:43 +03:00
|
|
|
let mut ret = FxHashSet::default();
|
2018-10-10 15:30:53 +02:00
|
|
|
ret.reserve(6); // the minimum number of insertions
|
2016-11-15 08:54:27 +00:00
|
|
|
// Target bindings.
|
2020-07-08 11:04:10 +10:00
|
|
|
ret.insert((sym::target_os, Some(Symbol::intern(os))));
|
2020-11-08 14:57:55 +03:00
|
|
|
if let Some(ref fam) = sess.target.os_family {
|
2020-07-08 11:04:10 +10:00
|
|
|
ret.insert((sym::target_family, Some(Symbol::intern(fam))));
|
|
|
|
if fam == "windows" {
|
|
|
|
ret.insert((sym::windows, None));
|
|
|
|
} else if fam == "unix" {
|
|
|
|
ret.insert((sym::unix, None));
|
2016-12-22 22:20:47 -07:00
|
|
|
}
|
|
|
|
}
|
2020-07-08 11:04:10 +10:00
|
|
|
ret.insert((sym::target_arch, Some(Symbol::intern(arch))));
|
|
|
|
ret.insert((sym::target_endian, Some(Symbol::intern(end))));
|
2020-10-14 18:22:10 +02:00
|
|
|
ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz))));
|
2020-07-08 11:04:10 +10:00
|
|
|
ret.insert((sym::target_env, Some(Symbol::intern(env))));
|
|
|
|
ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
|
2020-11-08 14:27:51 +03:00
|
|
|
if sess.target.has_elf_tls {
|
2019-05-22 12:42:23 +10:00
|
|
|
ret.insert((sym::target_thread_local, None));
|
2015-12-10 12:21:55 -08:00
|
|
|
}
|
2020-09-20 12:09:22 +02:00
|
|
|
for &(i, align) in &[
|
|
|
|
(8, layout.i8_align.abi),
|
|
|
|
(16, layout.i16_align.abi),
|
|
|
|
(32, layout.i32_align.abi),
|
|
|
|
(64, layout.i64_align.abi),
|
|
|
|
(128, layout.i128_align.abi),
|
|
|
|
] {
|
2016-08-15 09:46:44 +00:00
|
|
|
if i >= min_atomic_width && i <= max_atomic_width {
|
2020-09-20 12:09:22 +02:00
|
|
|
let mut insert_atomic = |s, align: Align| {
|
2019-12-22 17:42:04 -05:00
|
|
|
ret.insert((sym::target_has_atomic_load_store, Some(Symbol::intern(s))));
|
2019-10-08 17:09:23 +01:00
|
|
|
if atomic_cas {
|
2019-12-22 17:42:04 -05:00
|
|
|
ret.insert((sym::target_has_atomic, Some(Symbol::intern(s))));
|
2019-10-08 17:09:23 +01:00
|
|
|
}
|
2020-09-20 12:09:22 +02:00
|
|
|
if align.bits() == i {
|
|
|
|
ret.insert((sym::target_has_atomic_equal_alignment, Some(Symbol::intern(s))));
|
|
|
|
}
|
2019-10-08 17:09:23 +01:00
|
|
|
};
|
|
|
|
let s = i.to_string();
|
2020-09-20 12:09:22 +02:00
|
|
|
insert_atomic(&s, align);
|
2020-10-14 18:22:10 +02:00
|
|
|
if s == wordsz {
|
2020-09-20 12:09:22 +02:00
|
|
|
insert_atomic("ptr", layout.pointer_align.abi);
|
2016-04-15 20:16:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-06-14 00:00:00 +00:00
|
|
|
|
2020-07-25 19:02:49 +01:00
|
|
|
let panic_strategy = sess.panic_strategy();
|
|
|
|
ret.insert((sym::panic, Some(panic_strategy.desc_symbol())));
|
|
|
|
|
2020-06-14 00:00:00 +00:00
|
|
|
for s in sess.opts.debugging_opts.sanitizer {
|
2019-10-22 00:00:00 +00:00
|
|
|
let symbol = Symbol::intern(&s.to_string());
|
|
|
|
ret.insert((sym::sanitize, Some(symbol)));
|
|
|
|
}
|
2020-06-14 00:00:00 +00:00
|
|
|
|
2015-03-02 14:51:24 -08:00
|
|
|
if sess.opts.debug_assertions {
|
2020-07-08 11:04:10 +10:00
|
|
|
ret.insert((sym::debug_assertions, None));
|
2015-03-02 14:51:24 -08:00
|
|
|
}
|
2018-07-26 11:13:11 -06:00
|
|
|
if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
|
2019-05-22 12:42:23 +10:00
|
|
|
ret.insert((sym::proc_macro, None));
|
rustc: Implement custom derive (macros 1.1)
This commit is an implementation of [RFC 1681] which adds support to the
compiler for first-class user-define custom `#[derive]` modes with a far more
stable API than plugins have today.
[RFC 1681]: https://github.com/rust-lang/rfcs/blob/master/text/1681-macros-1.1.md
The main features added by this commit are:
* A new `rustc-macro` crate-type. This crate type represents one which will
provide custom `derive` implementations and perhaps eventually flower into the
implementation of macros 2.0 as well.
* A new `rustc_macro` crate in the standard distribution. This crate will
provide the runtime interface between macro crates and the compiler. The API
here is particularly conservative right now but has quite a bit of room to
expand into any manner of APIs required by macro authors.
* The ability to load new derive modes through the `#[macro_use]` annotations on
other crates.
All support added here is gated behind the `rustc_macro` feature gate, both for
the library support (the `rustc_macro` crate) as well as the language features.
There are a few minor differences from the implementation outlined in the RFC,
such as the `rustc_macro` crate being available as a dylib and all symbols are
`dlsym`'d directly instead of having a shim compiled. These should only affect
the implementation, however, not the public interface.
This commit also ended up touching a lot of code related to `#[derive]`, making
a few notable changes:
* Recognized derive attributes are no longer desugared to `derive_Foo`. Wasn't
sure how to keep this behavior and *not* expose it to custom derive.
* Derive attributes no longer have access to unstable features by default, they
have to opt in on a granular level.
* The `derive(Copy,Clone)` optimization is now done through another "obscure
attribute" which is just intended to ferry along in the compiler that such an
optimization is possible. The `derive(PartialEq,Eq)` optimization was also
updated to do something similar.
---
One part of this PR which needs to be improved before stabilizing are the errors
and exact interfaces here. The error messages are relatively poor quality and
there are surprising spects of this such as `#[derive(PartialEq, Eq, MyTrait)]`
not working by default. The custom attributes added by the compiler end up
becoming unstable again when going through a custom impl.
Hopefully though this is enough to start allowing experimentation on crates.io!
syntax-[breaking-change]
2016-08-22 17:07:11 -07:00
|
|
|
}
|
2018-10-10 15:33:10 +02:00
|
|
|
ret
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Converts the crate `cfg!` configuration from `String` to `Symbol`.
|
2018-12-08 20:30:23 +01:00
|
|
|
/// `rustc_interface::interface::Config` accepts this in the compiler configuration,
|
|
|
|
/// but the symbol interner is not yet set up then, so we must convert it later.
|
2019-11-19 20:02:16 -05:00
|
|
|
pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig {
|
2019-12-22 17:42:04 -05:00
|
|
|
cfg.into_iter().map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b)))).collect()
|
2018-12-08 20:30:23 +01:00
|
|
|
}
|
|
|
|
|
2019-11-19 20:02:16 -05:00
|
|
|
pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig {
|
2014-05-06 23:38:01 +12:00
|
|
|
// Combine the configuration requested by the session (command line) with
|
2019-09-06 03:57:44 +01:00
|
|
|
// some default and generated configuration items.
|
2014-05-06 23:38:01 +12:00
|
|
|
let default_cfg = default_configuration(sess);
|
2019-09-06 03:57:44 +01:00
|
|
|
// If the user wants a test runner, then add the test cfg.
|
2014-05-06 23:38:01 +12:00
|
|
|
if sess.opts.test {
|
2019-05-22 12:42:23 +10:00
|
|
|
user_cfg.insert((sym::test, None));
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
2016-11-15 08:54:27 +00:00
|
|
|
user_cfg.extend(default_cfg.iter().cloned());
|
|
|
|
user_cfg
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
|
2020-10-14 18:42:13 +02:00
|
|
|
pub fn build_target_config(opts: &Options, target_override: Option<Target>) -> Target {
|
2020-09-17 12:01:12 +02:00
|
|
|
let target_result = target_override.map_or_else(|| Target::search(&opts.target_triple), Ok);
|
|
|
|
let target = target_result.unwrap_or_else(|e| {
|
2020-03-30 22:17:15 -07:00
|
|
|
early_error(
|
2020-09-17 12:01:12 +02:00
|
|
|
opts.error_format,
|
2020-03-30 22:17:15 -07:00
|
|
|
&format!(
|
|
|
|
"Error loading target specification: {}. \
|
|
|
|
Use `--print target-list` for a list of built-in targets",
|
|
|
|
e
|
|
|
|
),
|
|
|
|
)
|
2018-10-10 15:33:10 +02:00
|
|
|
});
|
2014-07-23 11:56:36 -07:00
|
|
|
|
2020-10-14 18:22:10 +02:00
|
|
|
if !matches!(target.pointer_width, 16 | 32 | 64) {
|
|
|
|
early_error(
|
2020-09-17 12:01:12 +02:00
|
|
|
opts.error_format,
|
2020-03-30 22:17:15 -07:00
|
|
|
&format!(
|
2019-12-22 17:42:04 -05:00
|
|
|
"target specification was invalid: \
|
2018-03-06 02:29:03 -03:00
|
|
|
unrecognized target-pointer-width {}",
|
2020-10-14 18:22:10 +02:00
|
|
|
target.pointer_width
|
2020-03-30 22:17:15 -07:00
|
|
|
),
|
2020-10-14 18:22:10 +02:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-10-14 18:42:13 +02:00
|
|
|
target
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
|
2015-01-28 08:34:18 -05:00
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
2016-02-19 22:03:54 -08:00
|
|
|
pub enum OptionStability {
|
|
|
|
Stable,
|
|
|
|
Unstable,
|
|
|
|
}
|
2014-12-17 14:42:50 +01:00
|
|
|
|
|
|
|
pub struct RustcOptGroup {
|
2018-02-23 09:53:00 -08:00
|
|
|
pub apply: Box<dyn Fn(&mut getopts::Options) -> &mut getopts::Options>,
|
2017-06-08 14:20:55 -07:00
|
|
|
pub name: &'static str,
|
2014-12-17 14:42:50 +01:00
|
|
|
pub stability: OptionStability,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl RustcOptGroup {
|
|
|
|
pub fn is_stable(&self) -> bool {
|
|
|
|
self.stability == OptionStability::Stable
|
|
|
|
}
|
|
|
|
|
2017-06-08 14:20:55 -07:00
|
|
|
pub fn stable<F>(name: &'static str, f: F) -> RustcOptGroup
|
2018-03-06 02:29:03 -03:00
|
|
|
where
|
|
|
|
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
|
2017-06-08 14:20:55 -07:00
|
|
|
{
|
2019-12-22 17:42:04 -05:00
|
|
|
RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Stable }
|
2014-12-17 14:42:50 +01:00
|
|
|
}
|
|
|
|
|
2017-06-08 14:20:55 -07:00
|
|
|
pub fn unstable<F>(name: &'static str, f: F) -> RustcOptGroup
|
2018-03-06 02:29:03 -03:00
|
|
|
where
|
|
|
|
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
|
2017-06-08 14:20:55 -07:00
|
|
|
{
|
2019-12-22 17:42:04 -05:00
|
|
|
RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Unstable }
|
2014-12-17 14:42:50 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The `opt` local module holds wrappers around the `getopts` API that
|
|
|
|
// adds extra rustc-specific metadata to each option; such metadata
|
|
|
|
// is exposed by . The public
|
|
|
|
// functions below ending with `_u` are the functions that return
|
2018-11-27 02:59:49 +00:00
|
|
|
// *unstable* options, i.e., options that are only enabled when the
|
2014-12-17 14:42:50 +01:00
|
|
|
// user also passes the `-Z unstable-options` debugging flag.
|
|
|
|
mod opt {
|
2019-07-23 20:34:17 +03:00
|
|
|
// The `fn flag*` etc below are written so that we can use them
|
2014-12-17 14:42:50 +01:00
|
|
|
// in the future; do not warn about them not being used right now.
|
|
|
|
#![allow(dead_code)]
|
|
|
|
|
|
|
|
use super::RustcOptGroup;
|
|
|
|
|
2015-03-12 10:44:56 +13:00
|
|
|
pub type R = RustcOptGroup;
|
2017-06-08 14:20:55 -07:00
|
|
|
pub type S = &'static str;
|
|
|
|
|
|
|
|
fn stable<F>(name: S, f: F) -> R
|
2018-03-06 02:29:03 -03:00
|
|
|
where
|
|
|
|
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
|
2017-06-08 14:20:55 -07:00
|
|
|
{
|
|
|
|
RustcOptGroup::stable(name, f)
|
|
|
|
}
|
2014-12-17 14:42:50 +01:00
|
|
|
|
2017-06-08 14:20:55 -07:00
|
|
|
fn unstable<F>(name: S, f: F) -> R
|
2018-03-06 02:29:03 -03:00
|
|
|
where
|
|
|
|
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
|
2017-06-08 14:20:55 -07:00
|
|
|
{
|
|
|
|
RustcOptGroup::unstable(name, f)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn longer(a: S, b: S) -> S {
|
2019-12-22 17:42:04 -05:00
|
|
|
if a.len() > b.len() { a } else { b }
|
2017-06-08 14:20:55 -07:00
|
|
|
}
|
2014-12-17 14:42:50 +01:00
|
|
|
|
2016-02-19 22:03:54 -08:00
|
|
|
pub fn opt_s(a: S, b: S, c: S, d: S) -> R {
|
2017-06-08 14:20:55 -07:00
|
|
|
stable(longer(a, b), move |opts| opts.optopt(a, b, c, d))
|
2016-02-19 22:03:54 -08:00
|
|
|
}
|
|
|
|
pub fn multi_s(a: S, b: S, c: S, d: S) -> R {
|
2017-06-08 14:20:55 -07:00
|
|
|
stable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
|
2016-02-19 22:03:54 -08:00
|
|
|
}
|
|
|
|
pub fn flag_s(a: S, b: S, c: S) -> R {
|
2017-06-08 14:20:55 -07:00
|
|
|
stable(longer(a, b), move |opts| opts.optflag(a, b, c))
|
2016-02-19 22:03:54 -08:00
|
|
|
}
|
|
|
|
pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R {
|
2017-06-08 14:20:55 -07:00
|
|
|
stable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d))
|
2016-02-19 22:03:54 -08:00
|
|
|
}
|
|
|
|
pub fn flagmulti_s(a: S, b: S, c: S) -> R {
|
2017-06-08 14:20:55 -07:00
|
|
|
stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
|
2016-02-19 22:03:54 -08:00
|
|
|
}
|
2015-04-29 17:20:36 +02:00
|
|
|
|
2016-02-19 22:03:54 -08:00
|
|
|
pub fn opt(a: S, b: S, c: S, d: S) -> R {
|
2017-06-08 14:20:55 -07:00
|
|
|
unstable(longer(a, b), move |opts| opts.optopt(a, b, c, d))
|
2016-02-19 22:03:54 -08:00
|
|
|
}
|
|
|
|
pub fn multi(a: S, b: S, c: S, d: S) -> R {
|
2017-06-08 14:20:55 -07:00
|
|
|
unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
|
2016-02-19 22:03:54 -08:00
|
|
|
}
|
|
|
|
pub fn flag(a: S, b: S, c: S) -> R {
|
2017-06-08 14:20:55 -07:00
|
|
|
unstable(longer(a, b), move |opts| opts.optflag(a, b, c))
|
2016-02-19 22:03:54 -08:00
|
|
|
}
|
|
|
|
pub fn flagopt(a: S, b: S, c: S, d: S) -> R {
|
2017-06-08 14:20:55 -07:00
|
|
|
unstable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d))
|
2016-02-19 22:03:54 -08:00
|
|
|
}
|
|
|
|
pub fn flagmulti(a: S, b: S, c: S) -> R {
|
2017-06-08 14:20:55 -07:00
|
|
|
unstable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
|
2016-02-19 22:03:54 -08:00
|
|
|
}
|
2014-12-17 14:42:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the "short" subset of the rustc command line options,
|
|
|
|
/// including metadata for each option, such as whether the option is
|
|
|
|
/// part of the stable long-term interface for rustc.
|
|
|
|
pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
|
2014-12-15 16:03:39 -08:00
|
|
|
vec![
|
2016-02-19 22:03:54 -08:00
|
|
|
opt::flag_s("h", "help", "Display this message"),
|
|
|
|
opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"),
|
2018-03-06 02:29:03 -03:00
|
|
|
opt::multi_s(
|
|
|
|
"L",
|
|
|
|
"",
|
|
|
|
"Add a directory to the library search path. The
|
2016-04-15 23:55:42 +03:00
|
|
|
optional KIND can be one of dependency, crate, native,
|
2019-07-06 05:30:15 +02:00
|
|
|
framework, or all (the default).",
|
2018-03-06 02:29:03 -03:00
|
|
|
"[KIND=]PATH",
|
|
|
|
),
|
|
|
|
opt::multi_s(
|
|
|
|
"l",
|
|
|
|
"",
|
|
|
|
"Link the generated crate(s) to the specified native
|
2016-04-10 06:59:19 -07:00
|
|
|
library NAME. The optional KIND can be one of
|
2019-07-06 05:30:15 +02:00
|
|
|
static, framework, or dylib (the default).",
|
2018-03-06 02:29:03 -03:00
|
|
|
"[KIND=]NAME",
|
|
|
|
),
|
2019-07-20 16:34:41 -04:00
|
|
|
make_crate_type_option(),
|
2019-12-22 17:42:04 -05:00
|
|
|
opt::opt_s("", "crate-name", "Specify the name of the crate being built", "NAME"),
|
2019-03-22 11:51:37 +00:00
|
|
|
opt::opt_s(
|
|
|
|
"",
|
|
|
|
"edition",
|
|
|
|
"Specify which edition of the compiler to use when compiling code.",
|
|
|
|
EDITION_NAME_LIST,
|
|
|
|
),
|
2018-03-06 02:29:03 -03:00
|
|
|
opt::multi_s(
|
|
|
|
"",
|
|
|
|
"emit",
|
|
|
|
"Comma separated list of types of output for \
|
|
|
|
the compiler to emit",
|
|
|
|
"[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]",
|
|
|
|
),
|
|
|
|
opt::multi_s(
|
|
|
|
"",
|
|
|
|
"print",
|
2019-05-12 14:16:50 -07:00
|
|
|
"Compiler information to print on stdout",
|
2020-03-01 16:14:26 +03:00
|
|
|
"[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\
|
2018-03-06 02:29:03 -03:00
|
|
|
target-cpus|target-features|relocation-models|\
|
|
|
|
code-models|tls-models|target-spec-json|native-static-libs]",
|
|
|
|
),
|
|
|
|
opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"),
|
2016-02-19 22:03:54 -08:00
|
|
|
opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
|
|
|
|
opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
|
2018-03-06 02:29:03 -03:00
|
|
|
opt::opt_s(
|
|
|
|
"",
|
|
|
|
"out-dir",
|
|
|
|
"Write output to compiler-chosen filename \
|
|
|
|
in <dir>",
|
|
|
|
"DIR",
|
|
|
|
),
|
|
|
|
opt::opt_s(
|
|
|
|
"",
|
|
|
|
"explain",
|
|
|
|
"Provide a detailed explanation of an error \
|
|
|
|
message",
|
|
|
|
"OPT",
|
|
|
|
),
|
2016-02-19 22:03:54 -08:00
|
|
|
opt::flag_s("", "test", "Build a test harness"),
|
2019-12-22 17:42:04 -05:00
|
|
|
opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"),
|
2016-02-19 22:03:54 -08:00
|
|
|
opt::multi_s("W", "warn", "Set lint warnings", "OPT"),
|
|
|
|
opt::multi_s("A", "allow", "Set lint allowed", "OPT"),
|
|
|
|
opt::multi_s("D", "deny", "Set lint denied", "OPT"),
|
|
|
|
opt::multi_s("F", "forbid", "Set lint forbidden", "OPT"),
|
2018-03-06 02:29:03 -03:00
|
|
|
opt::multi_s(
|
|
|
|
"",
|
|
|
|
"cap-lints",
|
|
|
|
"Set the most restrictive lint level. \
|
|
|
|
More restrictive lints are capped at this \
|
|
|
|
level",
|
|
|
|
"LEVEL",
|
|
|
|
),
|
2016-02-19 22:03:54 -08:00
|
|
|
opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
|
|
|
|
opt::flag_s("V", "version", "Print version info and exit"),
|
|
|
|
opt::flag_s("v", "verbose", "Use verbose output"),
|
2014-12-15 16:03:39 -08:00
|
|
|
]
|
|
|
|
}
|
|
|
|
|
2014-12-17 14:42:50 +01:00
|
|
|
/// Returns all rustc command line options, including metadata for
|
|
|
|
/// each option, such as whether the option is part of the stable
|
|
|
|
/// long-term interface for rustc.
|
|
|
|
pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
|
|
|
|
let mut opts = rustc_short_optgroups();
|
2017-06-08 14:20:55 -07:00
|
|
|
opts.extend(vec![
|
2018-03-06 02:29:03 -03:00
|
|
|
opt::multi_s(
|
|
|
|
"",
|
|
|
|
"extern",
|
|
|
|
"Specify where an external rust library is located",
|
2019-09-29 18:17:48 -07:00
|
|
|
"NAME[=PATH]",
|
2018-03-06 02:29:03 -03:00
|
|
|
),
|
2016-02-19 22:03:54 -08:00
|
|
|
opt::opt_s("", "sysroot", "Override the system root", "PATH"),
|
2017-05-04 09:34:44 -07:00
|
|
|
opt::multi("Z", "", "Set internal debugging options", "FLAG"),
|
2018-03-06 02:29:03 -03:00
|
|
|
opt::opt_s(
|
|
|
|
"",
|
|
|
|
"error-format",
|
|
|
|
"How errors and other messages are produced",
|
|
|
|
"human|json|short",
|
|
|
|
),
|
2019-12-22 17:42:04 -05:00
|
|
|
opt::multi_s("", "json", "Configure the JSON output of the compiler", "CONFIG"),
|
2018-03-06 02:29:03 -03:00
|
|
|
opt::opt_s(
|
|
|
|
"",
|
|
|
|
"color",
|
|
|
|
"Configure coloring of output:
|
2016-03-15 09:09:29 +01:00
|
|
|
auto = colorize, if output goes to a tty (default);
|
|
|
|
always = always colorize output;
|
2018-03-06 02:29:03 -03:00
|
|
|
never = never colorize output",
|
|
|
|
"auto|always|never",
|
|
|
|
),
|
|
|
|
opt::opt(
|
|
|
|
"",
|
|
|
|
"pretty",
|
|
|
|
"Pretty-print the input instead of compiling;
|
2017-09-22 21:34:27 -07:00
|
|
|
valid types are: `normal` (un-annotated source),
|
|
|
|
`expanded` (crates expanded), or
|
|
|
|
`expanded,identified` (fully parenthesized, AST nodes with IDs).",
|
2018-03-06 02:29:03 -03:00
|
|
|
"TYPE",
|
|
|
|
),
|
|
|
|
opt::multi_s(
|
|
|
|
"",
|
|
|
|
"remap-path-prefix",
|
2018-03-13 13:26:07 -07:00
|
|
|
"Remap source names in all output (compiler messages and output files)",
|
2018-03-06 02:29:03 -03:00
|
|
|
"FROM=TO",
|
|
|
|
),
|
2014-12-15 16:03:39 -08:00
|
|
|
]);
|
|
|
|
opts
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
pub fn get_cmd_lint_options(
|
|
|
|
matches: &getopts::Matches,
|
|
|
|
error_format: ErrorOutputType,
|
|
|
|
) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) {
|
2020-01-04 18:04:30 -08:00
|
|
|
let mut lint_opts_with_position = vec![];
|
2018-06-23 15:09:21 +02:00
|
|
|
let mut describe_lints = false;
|
|
|
|
|
|
|
|
for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] {
|
2020-04-07 21:41:54 -07:00
|
|
|
for (passed_arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) {
|
|
|
|
let arg_pos = if let lint::Forbid = level {
|
2020-04-09 23:02:13 +02:00
|
|
|
// HACK: forbid is always specified last, so it can't be overridden.
|
|
|
|
// FIXME: remove this once <https://github.com/rust-lang/rust/issues/70819> is
|
|
|
|
// fixed and `forbid` works as expected.
|
2020-06-02 07:59:11 +00:00
|
|
|
usize::MAX
|
2020-04-07 21:41:54 -07:00
|
|
|
} else {
|
|
|
|
passed_arg_pos
|
|
|
|
};
|
2018-06-23 15:09:21 +02:00
|
|
|
if lint_name == "help" {
|
|
|
|
describe_lints = true;
|
|
|
|
} else {
|
2020-01-04 18:04:30 -08:00
|
|
|
lint_opts_with_position.push((arg_pos, lint_name.replace("-", "_"), level));
|
2018-06-23 15:09:21 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-04 18:04:30 -08:00
|
|
|
lint_opts_with_position.sort_by_key(|x| x.0);
|
|
|
|
let lint_opts = lint_opts_with_position
|
|
|
|
.iter()
|
|
|
|
.cloned()
|
|
|
|
.map(|(_, lint_name, level)| (lint_name, level))
|
|
|
|
.collect();
|
|
|
|
|
2018-06-23 15:09:21 +02:00
|
|
|
let lint_cap = matches.opt_str("cap-lints").map(|cap| {
|
|
|
|
lint::Level::from_str(&cap)
|
|
|
|
.unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap)))
|
|
|
|
});
|
|
|
|
(lint_opts, describe_lints, lint_cap)
|
|
|
|
}
|
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Parses the `--color` flag.
|
2019-07-17 12:52:56 -07:00
|
|
|
pub fn parse_color(matches: &getopts::Matches) -> ColorConfig {
|
|
|
|
match matches.opt_str("color").as_ref().map(|s| &s[..]) {
|
2018-03-06 02:29:03 -03:00
|
|
|
Some("auto") => ColorConfig::Auto,
|
2015-12-14 11:17:55 +13:00
|
|
|
Some("always") => ColorConfig::Always,
|
2018-03-06 02:29:03 -03:00
|
|
|
Some("never") => ColorConfig::Never,
|
2015-08-22 23:51:53 +09:00
|
|
|
|
2015-12-14 11:17:55 +13:00
|
|
|
None => ColorConfig::Auto,
|
2015-08-22 23:51:53 +09:00
|
|
|
|
2018-03-06 02:29:03 -03:00
|
|
|
Some(arg) => early_error(
|
|
|
|
ErrorOutputType::default(),
|
|
|
|
&format!(
|
2019-09-06 03:57:44 +01:00
|
|
|
"argument for `--color` must be auto, \
|
2018-03-06 02:29:03 -03:00
|
|
|
always or never (instead was `{}`)",
|
|
|
|
arg
|
|
|
|
),
|
|
|
|
),
|
2019-07-17 12:52:56 -07:00
|
|
|
}
|
|
|
|
}
|
2015-08-22 23:51:53 +09:00
|
|
|
|
2019-07-17 12:52:56 -07:00
|
|
|
/// Parse the `--json` flag.
|
|
|
|
///
|
|
|
|
/// The first value returned is how to render JSON diagnostics, and the second
|
|
|
|
/// is whether or not artifact notifications are enabled.
|
|
|
|
pub fn parse_json(matches: &getopts::Matches) -> (HumanReadableErrorType, bool) {
|
|
|
|
let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType =
|
|
|
|
HumanReadableErrorType::Default;
|
|
|
|
let mut json_color = ColorConfig::Never;
|
|
|
|
let mut json_artifact_notifications = false;
|
|
|
|
for option in matches.opt_strs("json") {
|
|
|
|
// For now conservatively forbid `--color` with `--json` since `--json`
|
|
|
|
// won't actually be emitting any colors and anything colorized is
|
|
|
|
// embedded in a diagnostic message anyway.
|
|
|
|
if matches.opt_str("color").is_some() {
|
2018-10-10 15:33:10 +02:00
|
|
|
early_error(
|
2018-04-19 13:56:26 -07:00
|
|
|
ErrorOutputType::default(),
|
2019-07-17 12:52:56 -07:00
|
|
|
"cannot specify the `--color` option with `--json`",
|
|
|
|
);
|
|
|
|
}
|
2018-04-19 13:56:26 -07:00
|
|
|
|
2019-07-17 12:52:56 -07:00
|
|
|
for sub_option in option.split(',') {
|
|
|
|
match sub_option {
|
|
|
|
"diagnostic-short" => json_rendered = HumanReadableErrorType::Short,
|
|
|
|
"diagnostic-rendered-ansi" => json_color = ColorConfig::Always,
|
|
|
|
"artifacts" => json_artifact_notifications = true,
|
2019-12-22 17:42:04 -05:00
|
|
|
s => early_error(
|
|
|
|
ErrorOutputType::default(),
|
|
|
|
&format!("unknown `--json` option `{}`", s),
|
|
|
|
),
|
2019-07-17 12:52:56 -07:00
|
|
|
}
|
|
|
|
}
|
2018-04-19 21:03:21 -07:00
|
|
|
}
|
2019-07-17 12:52:56 -07:00
|
|
|
(json_rendered(json_color), json_artifact_notifications)
|
|
|
|
}
|
2018-04-19 21:03:21 -07:00
|
|
|
|
2019-09-06 03:57:44 +01:00
|
|
|
/// Parses the `--error-format` flag.
|
2019-07-17 12:52:56 -07:00
|
|
|
pub fn parse_error_format(
|
|
|
|
matches: &getopts::Matches,
|
|
|
|
color: ColorConfig,
|
|
|
|
json_rendered: HumanReadableErrorType,
|
|
|
|
) -> ErrorOutputType {
|
2019-09-06 03:57:44 +01:00
|
|
|
// We need the `opts_present` check because the driver will send us Matches
|
2016-01-07 09:23:01 +13:00
|
|
|
// with only stable options if no unstable options are used. Since error-format
|
2019-09-06 03:57:44 +01:00
|
|
|
// is unstable, it will not be present. We have to use `opts_present` not
|
|
|
|
// `opt_present` because the latter will panic.
|
2016-01-07 09:23:01 +13:00
|
|
|
let error_format = if matches.opts_present(&["error-format".to_owned()]) {
|
|
|
|
match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
|
2019-12-22 17:42:04 -05:00
|
|
|
None | Some("human") => {
|
|
|
|
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
|
|
|
|
}
|
2019-05-31 21:15:59 +02:00
|
|
|
Some("human-annotate-rs") => {
|
2019-06-05 21:13:56 +02:00
|
|
|
ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(color))
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2019-03-25 11:16:58 +01:00
|
|
|
Some("json") => ErrorOutputType::Json { pretty: false, json_rendered },
|
|
|
|
Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered },
|
|
|
|
Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)),
|
2015-12-31 16:50:06 +13:00
|
|
|
|
2018-03-06 02:29:03 -03:00
|
|
|
Some(arg) => early_error(
|
2019-03-25 11:16:58 +01:00
|
|
|
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)),
|
2018-03-06 02:29:03 -03:00
|
|
|
&format!(
|
2019-09-01 18:09:59 +01:00
|
|
|
"argument for `--error-format` must be `human`, `json` or \
|
2018-03-06 02:29:03 -03:00
|
|
|
`short` (instead was `{}`)",
|
|
|
|
arg
|
|
|
|
),
|
|
|
|
),
|
2015-12-31 16:50:06 +13:00
|
|
|
}
|
|
|
|
} else {
|
2019-03-25 11:16:58 +01:00
|
|
|
ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color))
|
2015-12-31 16:50:06 +13:00
|
|
|
};
|
|
|
|
|
2019-07-17 12:52:56 -07:00
|
|
|
match error_format {
|
|
|
|
ErrorOutputType::Json { .. } => {}
|
|
|
|
|
|
|
|
// Conservatively require that the `--json` argument is coupled with
|
|
|
|
// `--error-format=json`. This means that `--json` is specified we
|
|
|
|
// should actually be emitting JSON blobs.
|
2020-02-28 14:20:33 +01:00
|
|
|
_ if !matches.opt_strs("json").is_empty() => {
|
2019-07-17 12:52:56 -07:00
|
|
|
early_error(
|
|
|
|
ErrorOutputType::default(),
|
|
|
|
"using `--json` requires also using `--error-format=json`",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
2020-03-20 15:03:11 +01:00
|
|
|
error_format
|
2019-07-17 12:52:56 -07:00
|
|
|
}
|
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
fn parse_crate_edition(matches: &getopts::Matches) -> Edition {
|
2019-07-17 12:52:56 -07:00
|
|
|
let edition = match matches.opt_str("edition") {
|
2019-12-22 17:42:04 -05:00
|
|
|
Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| {
|
2019-07-17 12:52:56 -07:00
|
|
|
early_error(
|
|
|
|
ErrorOutputType::default(),
|
|
|
|
&format!(
|
2019-09-01 18:09:59 +01:00
|
|
|
"argument for `--edition` must be one of: \
|
2019-07-17 12:52:56 -07:00
|
|
|
{}. (instead was `{}`)",
|
2019-12-22 17:42:04 -05:00
|
|
|
EDITION_NAME_LIST, arg
|
2019-07-17 12:52:56 -07:00
|
|
|
),
|
2019-12-22 17:42:04 -05:00
|
|
|
)
|
|
|
|
}),
|
2019-07-17 12:52:56 -07:00
|
|
|
None => DEFAULT_EDITION,
|
|
|
|
};
|
|
|
|
|
2020-10-10 14:27:52 -04:00
|
|
|
if !edition.is_stable() && !nightly_options::match_is_nightly_build(matches) {
|
2019-07-17 12:52:56 -07:00
|
|
|
early_error(
|
2019-12-22 17:42:04 -05:00
|
|
|
ErrorOutputType::default(),
|
|
|
|
&format!(
|
|
|
|
"edition {} is unstable and only \
|
2019-07-17 12:52:56 -07:00
|
|
|
available for nightly builds of rustc.",
|
2019-12-22 17:42:04 -05:00
|
|
|
edition,
|
|
|
|
),
|
2019-07-17 12:52:56 -07:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
edition
|
|
|
|
}
|
2014-05-06 23:38:01 +12:00
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
fn check_debug_option_stability(
|
|
|
|
debugging_opts: &DebuggingOptions,
|
|
|
|
error_format: ErrorOutputType,
|
|
|
|
json_rendered: HumanReadableErrorType,
|
|
|
|
) {
|
2019-03-12 13:06:43 +01:00
|
|
|
if !debugging_opts.unstable_options {
|
2019-03-25 11:16:58 +01:00
|
|
|
if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format {
|
2019-03-12 13:06:43 +01:00
|
|
|
early_error(
|
2019-03-25 11:16:58 +01:00
|
|
|
ErrorOutputType::Json { pretty: false, json_rendered },
|
2019-09-01 18:09:59 +01:00
|
|
|
"`--error-format=pretty-json` is unstable",
|
2019-03-12 13:06:43 +01:00
|
|
|
);
|
|
|
|
}
|
2019-06-05 21:13:56 +02:00
|
|
|
if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) =
|
2019-12-22 17:42:04 -05:00
|
|
|
error_format
|
|
|
|
{
|
2019-05-31 21:15:59 +02:00
|
|
|
early_error(
|
|
|
|
ErrorOutputType::Json { pretty: false, json_rendered },
|
2019-09-01 18:09:59 +01:00
|
|
|
"`--error-format=human-annotate-rs` is unstable",
|
2019-05-31 21:15:59 +02:00
|
|
|
);
|
|
|
|
}
|
2017-11-03 13:38:26 +01:00
|
|
|
}
|
2019-10-11 23:30:58 +02:00
|
|
|
}
|
2017-11-03 13:38:26 +01:00
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
fn parse_output_types(
|
|
|
|
debugging_opts: &DebuggingOptions,
|
|
|
|
matches: &getopts::Matches,
|
|
|
|
error_format: ErrorOutputType,
|
|
|
|
) -> OutputTypes {
|
2016-08-02 16:53:58 -04:00
|
|
|
let mut output_types = BTreeMap::new();
|
2016-05-25 08:46:36 +03:00
|
|
|
if !debugging_opts.parse_only {
|
2015-09-30 10:08:37 -07:00
|
|
|
for list in matches.opt_strs("emit") {
|
|
|
|
for output_type in list.split(',') {
|
|
|
|
let mut parts = output_type.splitn(2, '=');
|
2017-11-05 09:20:59 -05:00
|
|
|
let shorthand = parts.next().unwrap();
|
2019-12-22 17:42:04 -05:00
|
|
|
let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| {
|
2018-10-10 15:33:10 +02:00
|
|
|
early_error(
|
2018-03-06 02:29:03 -03:00
|
|
|
error_format,
|
|
|
|
&format!(
|
|
|
|
"unknown emission type: `{}` - expected one of: {}",
|
|
|
|
shorthand,
|
|
|
|
OutputType::shorthands_display(),
|
|
|
|
),
|
2019-12-22 17:42:04 -05:00
|
|
|
)
|
|
|
|
});
|
2015-09-30 10:08:37 -07:00
|
|
|
let path = parts.next().map(PathBuf::from);
|
|
|
|
output_types.insert(output_type, path);
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2017-05-28 13:49:14 +07:00
|
|
|
if output_types.is_empty() {
|
2015-09-30 10:08:37 -07:00
|
|
|
output_types.insert(OutputType::Exe, None);
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
2019-10-11 23:30:58 +02:00
|
|
|
OutputTypes(output_types)
|
|
|
|
}
|
2014-05-06 23:38:01 +12:00
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
fn should_override_cgus_and_disable_thinlto(
|
|
|
|
output_types: &OutputTypes,
|
|
|
|
matches: &getopts::Matches,
|
|
|
|
error_format: ErrorOutputType,
|
|
|
|
mut codegen_units: Option<usize>,
|
|
|
|
) -> (bool, Option<usize>) {
|
2018-01-16 15:02:31 -08:00
|
|
|
let mut disable_thinlto = false;
|
2019-09-06 03:57:44 +01:00
|
|
|
// Issue #30063: if user requests LLVM-related output to one
|
2015-12-04 19:35:16 +01:00
|
|
|
// particular path, disable codegen-units.
|
2019-12-22 17:42:04 -05:00
|
|
|
let incompatible: Vec<_> = output_types
|
|
|
|
.0
|
2018-03-06 02:29:03 -03:00
|
|
|
.iter()
|
2017-09-25 12:26:25 -07:00
|
|
|
.map(|ot_path| ot_path.0)
|
2018-03-06 02:29:03 -03:00
|
|
|
.filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file())
|
2017-09-25 12:26:25 -07:00
|
|
|
.map(|ot| ot.shorthand())
|
|
|
|
.collect();
|
|
|
|
if !incompatible.is_empty() {
|
|
|
|
match codegen_units {
|
|
|
|
Some(n) if n > 1 => {
|
|
|
|
if matches.opt_present("o") {
|
|
|
|
for ot in &incompatible {
|
2018-03-06 02:29:03 -03:00
|
|
|
early_warn(
|
|
|
|
error_format,
|
|
|
|
&format!(
|
2019-09-01 18:09:59 +01:00
|
|
|
"`--emit={}` with `-o` incompatible with \
|
|
|
|
`-C codegen-units=N` for N > 1",
|
2018-03-06 02:29:03 -03:00
|
|
|
ot
|
|
|
|
),
|
|
|
|
);
|
2017-09-25 12:26:25 -07:00
|
|
|
}
|
|
|
|
early_warn(error_format, "resetting to default -C codegen-units=1");
|
|
|
|
codegen_units = Some(1);
|
2018-01-16 15:02:31 -08:00
|
|
|
disable_thinlto = true;
|
2017-09-25 12:26:25 -07:00
|
|
|
}
|
2015-12-04 19:35:16 +01:00
|
|
|
}
|
2017-11-25 11:13:58 -08:00
|
|
|
_ => {
|
|
|
|
codegen_units = Some(1);
|
2018-01-16 15:02:31 -08:00
|
|
|
disable_thinlto = true;
|
2017-11-25 11:13:58 -08:00
|
|
|
}
|
2015-12-04 19:35:16 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
if codegen_units == Some(0) {
|
2019-12-22 17:42:04 -05:00
|
|
|
early_error(error_format, "value for codegen units must be a positive non-zero integer");
|
2017-12-03 14:16:19 +01:00
|
|
|
}
|
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
(disable_thinlto, codegen_units)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn check_thread_count(debugging_opts: &DebuggingOptions, error_format: ErrorOutputType) {
|
|
|
|
if debugging_opts.threads == 0 {
|
2019-12-22 17:42:04 -05:00
|
|
|
early_error(error_format, "value for threads must be a positive non-zero integer");
|
2018-04-01 08:20:39 +02:00
|
|
|
}
|
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
if debugging_opts.threads > 1 && debugging_opts.fuel.is_some() {
|
2019-12-22 17:42:04 -05:00
|
|
|
early_error(error_format, "optimization fuel is incompatible with multiple threads");
|
2016-03-12 16:01:34 +05:30
|
|
|
}
|
2019-10-11 23:30:58 +02:00
|
|
|
}
|
2016-03-12 16:01:34 +05:30
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
fn collect_print_requests(
|
|
|
|
cg: &mut CodegenOptions,
|
|
|
|
dopts: &mut DebuggingOptions,
|
|
|
|
matches: &getopts::Matches,
|
|
|
|
error_format: ErrorOutputType,
|
|
|
|
) -> Vec<PrintRequest> {
|
2016-07-11 00:22:13 +10:00
|
|
|
let mut prints = Vec::<PrintRequest>::new();
|
|
|
|
if cg.target_cpu.as_ref().map_or(false, |s| s == "help") {
|
|
|
|
prints.push(PrintRequest::TargetCPUs);
|
|
|
|
cg.target_cpu = None;
|
|
|
|
};
|
|
|
|
if cg.target_feature == "help" {
|
|
|
|
prints.push(PrintRequest::TargetFeatures);
|
2018-08-23 10:14:52 +02:00
|
|
|
cg.target_feature = String::new();
|
2016-07-11 00:22:13 +10:00
|
|
|
}
|
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
|
|
|
|
"crate-name" => PrintRequest::CrateName,
|
|
|
|
"file-names" => PrintRequest::FileNames,
|
|
|
|
"sysroot" => PrintRequest::Sysroot,
|
2020-03-01 14:33:52 +03:00
|
|
|
"target-libdir" => PrintRequest::TargetLibdir,
|
2019-10-11 23:30:58 +02:00
|
|
|
"cfg" => PrintRequest::Cfg,
|
|
|
|
"target-list" => PrintRequest::TargetList,
|
|
|
|
"target-cpus" => PrintRequest::TargetCPUs,
|
|
|
|
"target-features" => PrintRequest::TargetFeatures,
|
|
|
|
"relocation-models" => PrintRequest::RelocationModels,
|
|
|
|
"code-models" => PrintRequest::CodeModels,
|
|
|
|
"tls-models" => PrintRequest::TlsModels,
|
|
|
|
"native-static-libs" => PrintRequest::NativeStaticLibs,
|
|
|
|
"target-spec-json" => {
|
2019-10-16 09:55:40 -07:00
|
|
|
if dopts.unstable_options {
|
2019-10-11 23:30:58 +02:00
|
|
|
PrintRequest::TargetSpec
|
|
|
|
} else {
|
|
|
|
early_error(
|
|
|
|
error_format,
|
|
|
|
"the `-Z unstable-options` flag must also be passed to \
|
|
|
|
enable the target-spec-json print option",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
req => early_error(error_format, &format!("unknown print request `{}`", req)),
|
|
|
|
}));
|
2014-12-15 16:03:39 -08:00
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
prints
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_target_triple(matches: &getopts::Matches, error_format: ErrorOutputType) -> TargetTriple {
|
|
|
|
match matches.opt_str("target") {
|
|
|
|
Some(target) if target.ends_with(".json") => {
|
2018-03-24 20:14:59 +01:00
|
|
|
let path = Path::new(&target);
|
2019-12-22 17:42:04 -05:00
|
|
|
TargetTriple::from_path(&path).unwrap_or_else(|_| {
|
|
|
|
early_error(error_format, &format!("target file {:?} does not exist", path))
|
|
|
|
})
|
2019-10-11 23:30:58 +02:00
|
|
|
}
|
|
|
|
Some(target) => TargetTriple::TargetTriple(target),
|
|
|
|
_ => TargetTriple::from_triple(host_triple()),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_opt_level(
|
|
|
|
matches: &getopts::Matches,
|
|
|
|
cg: &CodegenOptions,
|
|
|
|
error_format: ErrorOutputType,
|
|
|
|
) -> OptLevel {
|
|
|
|
// The `-O` and `-C opt-level` flags specify the same setting, so we want to be able
|
|
|
|
// to use them interchangeably. However, because they're technically different flags,
|
|
|
|
// we need to work out manually which should take precedence if both are supplied (i.e.
|
|
|
|
// the rightmost flag). We do this by finding the (rightmost) position of both flags and
|
|
|
|
// comparing them. Note that if a flag is not found, its position will be `None`, which
|
|
|
|
// always compared less than `Some(_)`.
|
|
|
|
let max_o = matches.opt_positions("O").into_iter().max();
|
2019-12-22 17:42:04 -05:00
|
|
|
let max_c = matches
|
|
|
|
.opt_strs_pos("C")
|
|
|
|
.into_iter()
|
|
|
|
.flat_map(
|
|
|
|
|(i, s)| {
|
|
|
|
if let Some("opt-level") = s.splitn(2, '=').next() { Some(i) } else { None }
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.max();
|
2019-10-11 23:30:58 +02:00
|
|
|
if max_o > max_c {
|
|
|
|
OptLevel::Default
|
2018-03-14 15:27:06 +01:00
|
|
|
} else {
|
2020-04-02 16:44:47 +11:00
|
|
|
match cg.opt_level.as_ref() {
|
|
|
|
"0" => OptLevel::No,
|
|
|
|
"1" => OptLevel::Less,
|
|
|
|
"2" => OptLevel::Default,
|
|
|
|
"3" => OptLevel::Aggressive,
|
|
|
|
"s" => OptLevel::Size,
|
|
|
|
"z" => OptLevel::SizeMin,
|
|
|
|
arg => {
|
2019-10-11 23:30:58 +02:00
|
|
|
early_error(
|
|
|
|
error_format,
|
|
|
|
&format!(
|
|
|
|
"optimization level needs to be \
|
|
|
|
between 0-3, s or z (instead was `{}`)",
|
|
|
|
arg
|
|
|
|
),
|
|
|
|
);
|
2014-12-15 16:03:39 -08:00
|
|
|
}
|
2014-05-06 23:38:01 +12:00
|
|
|
}
|
2019-10-11 23:30:58 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn select_debuginfo(
|
|
|
|
matches: &getopts::Matches,
|
|
|
|
cg: &CodegenOptions,
|
|
|
|
error_format: ErrorOutputType,
|
|
|
|
) -> DebugInfo {
|
2019-04-30 21:52:05 +01:00
|
|
|
let max_g = matches.opt_positions("g").into_iter().max();
|
2019-12-22 17:42:04 -05:00
|
|
|
let max_c = matches
|
|
|
|
.opt_strs_pos("C")
|
|
|
|
.into_iter()
|
|
|
|
.flat_map(
|
|
|
|
|(i, s)| {
|
|
|
|
if let Some("debuginfo") = s.splitn(2, '=').next() { Some(i) } else { None }
|
|
|
|
},
|
|
|
|
)
|
|
|
|
.max();
|
2019-10-11 23:30:58 +02:00
|
|
|
if max_g > max_c {
|
2018-07-26 11:41:10 -06:00
|
|
|
DebugInfo::Full
|
2014-05-06 23:38:01 +12:00
|
|
|
} else {
|
2014-12-15 16:03:39 -08:00
|
|
|
match cg.debuginfo {
|
2020-04-02 16:44:47 +11:00
|
|
|
0 => DebugInfo::None,
|
|
|
|
1 => DebugInfo::Limited,
|
|
|
|
2 => DebugInfo::Full,
|
|
|
|
arg => {
|
2018-03-06 02:29:03 -03:00
|
|
|
early_error(
|
|
|
|
error_format,
|
|
|
|
&format!(
|
|
|
|
"debug info level needs to be between \
|
|
|
|
0-2 (instead was `{}`)",
|
|
|
|
arg
|
|
|
|
),
|
|
|
|
);
|
2014-12-15 16:03:39 -08:00
|
|
|
}
|
|
|
|
}
|
2014-12-16 14:32:02 -08:00
|
|
|
}
|
2019-10-11 23:30:58 +02:00
|
|
|
}
|
2014-05-06 23:38:01 +12:00
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
fn parse_libs(
|
|
|
|
matches: &getopts::Matches,
|
|
|
|
error_format: ErrorOutputType,
|
2020-05-18 01:52:34 +03:00
|
|
|
) -> Vec<(String, Option<String>, NativeLibKind)> {
|
2019-10-11 23:30:58 +02:00
|
|
|
matches
|
2018-03-06 02:29:03 -03:00
|
|
|
.opt_strs("l")
|
|
|
|
.into_iter()
|
|
|
|
.map(|s| {
|
|
|
|
// Parse string of the form "[KIND=]lib[:new_name]",
|
|
|
|
// where KIND is one of "dylib", "framework", "static".
|
|
|
|
let mut parts = s.splitn(2, '=');
|
|
|
|
let kind = parts.next().unwrap();
|
|
|
|
let (name, kind) = match (parts.next(), kind) {
|
2020-05-18 01:52:34 +03:00
|
|
|
(None, name) => (name, NativeLibKind::Unspecified),
|
|
|
|
(Some(name), "dylib") => (name, NativeLibKind::Dylib),
|
|
|
|
(Some(name), "framework") => (name, NativeLibKind::Framework),
|
|
|
|
(Some(name), "static") => (name, NativeLibKind::StaticBundle),
|
|
|
|
(Some(name), "static-nobundle") => (name, NativeLibKind::StaticNoBundle),
|
2018-03-06 02:29:03 -03:00
|
|
|
(_, s) => {
|
|
|
|
early_error(
|
|
|
|
error_format,
|
|
|
|
&format!(
|
|
|
|
"unknown library kind `{}`, expected \
|
|
|
|
one of dylib, framework, or static",
|
|
|
|
s
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
};
|
2020-10-10 14:27:52 -04:00
|
|
|
if kind == NativeLibKind::StaticNoBundle
|
|
|
|
&& !nightly_options::match_is_nightly_build(matches)
|
|
|
|
{
|
2018-03-06 02:29:03 -03:00
|
|
|
early_error(
|
|
|
|
error_format,
|
2020-02-27 13:34:08 +01:00
|
|
|
"the library kind 'static-nobundle' is only \
|
|
|
|
accepted on the nightly compiler",
|
2018-03-06 02:29:03 -03:00
|
|
|
);
|
2014-10-20 23:04:16 -07:00
|
|
|
}
|
2018-03-06 02:29:03 -03:00
|
|
|
let mut name_parts = name.splitn(2, ':');
|
|
|
|
let name = name_parts.next().unwrap();
|
|
|
|
let new_name = name_parts.next();
|
2018-10-10 15:34:07 +02:00
|
|
|
(name.to_owned(), new_name.map(|n| n.to_owned()), kind)
|
2018-03-06 02:29:03 -03:00
|
|
|
})
|
2019-10-11 23:30:58 +02:00
|
|
|
.collect()
|
|
|
|
}
|
2014-05-06 23:38:01 +12:00
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
fn parse_borrowck_mode(dopts: &DebuggingOptions, error_format: ErrorOutputType) -> BorrowckMode {
|
2020-04-02 16:44:47 +11:00
|
|
|
match dopts.borrowck.as_ref() {
|
|
|
|
"migrate" => BorrowckMode::Migrate,
|
|
|
|
"mir" => BorrowckMode::Mir,
|
|
|
|
m => early_error(error_format, &format!("unknown borrowck mode `{}`", m)),
|
2014-09-12 08:17:58 -07:00
|
|
|
}
|
2019-10-11 23:30:58 +02:00
|
|
|
}
|
2014-09-12 08:17:58 -07:00
|
|
|
|
2019-12-05 14:43:53 -08:00
|
|
|
pub fn parse_externs(
|
2019-10-11 23:30:58 +02:00
|
|
|
matches: &getopts::Matches,
|
|
|
|
debugging_opts: &DebuggingOptions,
|
|
|
|
error_format: ErrorOutputType,
|
|
|
|
) -> Externs {
|
2019-12-05 14:43:53 -08:00
|
|
|
let is_unstable_enabled = debugging_opts.unstable_options;
|
2019-04-07 18:48:40 -04:00
|
|
|
let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new();
|
2019-12-05 14:43:53 -08:00
|
|
|
for arg in matches.opt_strs("extern") {
|
2015-04-01 11:28:34 -07:00
|
|
|
let mut parts = arg.splitn(2, '=');
|
2019-12-05 14:43:53 -08:00
|
|
|
let name = parts
|
|
|
|
.next()
|
|
|
|
.unwrap_or_else(|| early_error(error_format, "--extern value must not be empty"));
|
|
|
|
let path = parts.next().map(|s| s.to_string());
|
|
|
|
|
|
|
|
let mut name_parts = name.splitn(2, ':');
|
|
|
|
let first_part = name_parts.next();
|
|
|
|
let second_part = name_parts.next();
|
|
|
|
let (options, name) = match (first_part, second_part) {
|
|
|
|
(Some(opts), Some(name)) => (Some(opts), name),
|
|
|
|
(Some(name), None) => (None, name),
|
|
|
|
(None, None) => early_error(error_format, "--extern name must not be empty"),
|
|
|
|
_ => unreachable!(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let entry = externs.entry(name.to_owned());
|
|
|
|
|
|
|
|
use std::collections::btree_map::Entry;
|
|
|
|
|
|
|
|
let entry = if let Some(path) = path {
|
|
|
|
// --extern prelude_name=some_file.rlib
|
|
|
|
match entry {
|
|
|
|
Entry::Vacant(vacant) => {
|
|
|
|
let files = BTreeSet::from_iter(iter::once(path));
|
|
|
|
vacant.insert(ExternEntry::new(ExternLocation::ExactPaths(files)))
|
|
|
|
}
|
|
|
|
Entry::Occupied(occupied) => {
|
|
|
|
let ext_ent = occupied.into_mut();
|
|
|
|
match ext_ent {
|
|
|
|
ExternEntry { location: ExternLocation::ExactPaths(files), .. } => {
|
|
|
|
files.insert(path);
|
|
|
|
}
|
|
|
|
ExternEntry {
|
|
|
|
location: location @ ExternLocation::FoundInLibrarySearchDirectories,
|
|
|
|
..
|
|
|
|
} => {
|
|
|
|
// Exact paths take precedence over search directories.
|
|
|
|
let files = BTreeSet::from_iter(iter::once(path));
|
|
|
|
*location = ExternLocation::ExactPaths(files);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ext_ent
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// --extern prelude_name
|
|
|
|
match entry {
|
|
|
|
Entry::Vacant(vacant) => {
|
|
|
|
vacant.insert(ExternEntry::new(ExternLocation::FoundInLibrarySearchDirectories))
|
|
|
|
}
|
|
|
|
Entry::Occupied(occupied) => {
|
|
|
|
// Ignore if already specified.
|
|
|
|
occupied.into_mut()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2019-04-09 17:24:24 -04:00
|
|
|
|
2019-12-05 14:43:53 -08:00
|
|
|
let mut is_private_dep = false;
|
|
|
|
let mut add_prelude = true;
|
|
|
|
if let Some(opts) = options {
|
|
|
|
if !is_unstable_enabled {
|
|
|
|
early_error(
|
|
|
|
error_format,
|
|
|
|
"the `-Z unstable-options` flag must also be passed to \
|
|
|
|
enable `--extern options",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
for opt in opts.split(',') {
|
|
|
|
match opt {
|
|
|
|
"priv" => is_private_dep = true,
|
|
|
|
"noprelude" => {
|
|
|
|
if let ExternLocation::ExactPaths(_) = &entry.location {
|
|
|
|
add_prelude = false;
|
|
|
|
} else {
|
|
|
|
early_error(
|
|
|
|
error_format,
|
|
|
|
"the `noprelude` --extern option requires a file path",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => early_error(error_format, &format!("unknown --extern option `{}`", opt)),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-09 17:24:24 -04:00
|
|
|
|
2019-12-05 14:43:53 -08:00
|
|
|
// Crates start out being not private, and go to being private `priv`
|
|
|
|
// is specified.
|
|
|
|
entry.is_private_dep |= is_private_dep;
|
|
|
|
// If any flag is missing `noprelude`, then add to the prelude.
|
|
|
|
entry.add_prelude |= add_prelude;
|
2019-04-07 18:48:40 -04:00
|
|
|
}
|
2019-10-11 23:30:58 +02:00
|
|
|
Externs(externs)
|
|
|
|
}
|
2014-07-01 08:37:54 -07:00
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
fn parse_remap_path_prefix(
|
|
|
|
matches: &getopts::Matches,
|
2019-12-22 17:42:04 -05:00
|
|
|
error_format: ErrorOutputType,
|
2019-10-11 23:30:58 +02:00
|
|
|
) -> Vec<(PathBuf, PathBuf)> {
|
|
|
|
matches
|
2018-03-06 02:29:03 -03:00
|
|
|
.opt_strs("remap-path-prefix")
|
2018-02-18 15:05:24 -08:00
|
|
|
.into_iter()
|
|
|
|
.map(|remap| {
|
|
|
|
let mut parts = remap.rsplitn(2, '='); // reverse iterator
|
|
|
|
let to = parts.next();
|
|
|
|
let from = parts.next();
|
|
|
|
match (from, to) {
|
|
|
|
(Some(from), Some(to)) => (PathBuf::from(from), PathBuf::from(to)),
|
2018-03-06 02:29:03 -03:00
|
|
|
_ => early_error(
|
|
|
|
error_format,
|
|
|
|
"--remap-path-prefix must contain '=' between FROM and TO",
|
|
|
|
),
|
2018-02-18 15:05:24 -08:00
|
|
|
}
|
|
|
|
})
|
2019-10-11 23:30:58 +02:00
|
|
|
.collect()
|
|
|
|
}
|
2018-02-18 15:05:24 -08:00
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
pub fn build_session_options(matches: &getopts::Matches) -> Options {
|
|
|
|
let color = parse_color(matches);
|
|
|
|
|
|
|
|
let edition = parse_crate_edition(matches);
|
|
|
|
|
|
|
|
let (json_rendered, json_artifact_notifications) = parse_json(matches);
|
|
|
|
|
|
|
|
let error_format = parse_error_format(matches, color, json_rendered);
|
|
|
|
|
|
|
|
let unparsed_crate_types = matches.opt_strs("crate-type");
|
|
|
|
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
|
|
|
|
.unwrap_or_else(|e| early_error(error_format, &e[..]));
|
|
|
|
|
|
|
|
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
|
|
|
|
|
|
|
|
let mut debugging_opts = build_debugging_options(matches, error_format);
|
|
|
|
check_debug_option_stability(&debugging_opts, error_format, json_rendered);
|
|
|
|
|
|
|
|
let output_types = parse_output_types(&debugging_opts, matches, error_format);
|
|
|
|
|
|
|
|
let mut cg = build_codegen_options(matches, error_format);
|
2020-04-17 19:53:31 +01:00
|
|
|
let (disable_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto(
|
2019-10-11 23:30:58 +02:00
|
|
|
&output_types,
|
|
|
|
matches,
|
|
|
|
error_format,
|
|
|
|
cg.codegen_units,
|
|
|
|
);
|
|
|
|
|
|
|
|
check_thread_count(&debugging_opts, error_format);
|
|
|
|
|
2020-03-29 20:19:14 +02:00
|
|
|
let incremental = cg.incremental.as_ref().map(PathBuf::from);
|
2019-10-11 23:30:58 +02:00
|
|
|
|
|
|
|
if debugging_opts.profile && incremental.is_some() {
|
|
|
|
early_error(
|
2018-03-06 02:29:03 -03:00
|
|
|
error_format,
|
2019-10-11 23:30:58 +02:00
|
|
|
"can't instrument with gcov profiling when compiling incrementally",
|
|
|
|
);
|
|
|
|
}
|
2020-04-17 19:53:31 +01:00
|
|
|
if debugging_opts.profile {
|
|
|
|
match codegen_units {
|
|
|
|
Some(1) => {}
|
|
|
|
None => codegen_units = Some(1),
|
|
|
|
Some(_) => early_error(
|
|
|
|
error_format,
|
|
|
|
"can't instrument with gcov profiling with multiple codegen units",
|
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
2019-10-11 23:30:58 +02:00
|
|
|
|
|
|
|
if cg.profile_generate.enabled() && cg.profile_use.is_some() {
|
|
|
|
early_error(
|
|
|
|
error_format,
|
|
|
|
"options `-C profile-generate` and `-C profile-use` are exclusive",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-07-02 11:27:15 -07:00
|
|
|
if debugging_opts.instrument_coverage {
|
|
|
|
if cg.profile_generate.enabled() || cg.profile_use.is_some() {
|
|
|
|
early_error(
|
|
|
|
error_format,
|
|
|
|
"option `-Z instrument-coverage` is not compatible with either `-C profile-use` \
|
|
|
|
or `-C profile-generate`",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2020-08-27 12:53:43 -07:00
|
|
|
// `-Z instrument-coverage` implies `-Z symbol-mangling-version=v0` - to ensure consistent
|
|
|
|
// and reversible name mangling. Note, LLVM coverage tools can analyze coverage over
|
|
|
|
// multiple runs, including some changes to source code; so mangled names must be consistent
|
|
|
|
// across compilations.
|
2020-07-02 11:27:15 -07:00
|
|
|
debugging_opts.symbol_mangling_version = SymbolManglingVersion::V0;
|
|
|
|
}
|
|
|
|
|
2020-09-16 10:47:56 -07:00
|
|
|
if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") {
|
|
|
|
debugging_opts.graphviz_font = graphviz_font;
|
|
|
|
}
|
|
|
|
|
2020-04-30 10:53:16 -07:00
|
|
|
if !cg.embed_bitcode {
|
2020-04-19 20:48:43 +10:00
|
|
|
match cg.lto {
|
|
|
|
LtoCli::No | LtoCli::Unspecified => {}
|
|
|
|
LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => early_error(
|
|
|
|
error_format,
|
2020-04-30 10:53:16 -07:00
|
|
|
"options `-C embed-bitcode=no` and `-C lto` are incompatible",
|
2020-04-19 20:48:43 +10:00
|
|
|
),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
let prints = collect_print_requests(&mut cg, &mut debugging_opts, matches, error_format);
|
2019-10-11 23:30:58 +02:00
|
|
|
|
|
|
|
let cg = cg;
|
|
|
|
|
|
|
|
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
|
|
|
|
let target_triple = parse_target_triple(matches, error_format);
|
|
|
|
let opt_level = parse_opt_level(matches, &cg, error_format);
|
|
|
|
// The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able
|
|
|
|
// to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`)
|
|
|
|
// for more details.
|
|
|
|
let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
|
|
|
|
let debuginfo = select_debuginfo(matches, &cg, error_format);
|
|
|
|
|
|
|
|
let mut search_paths = vec![];
|
|
|
|
for s in &matches.opt_strs("L") {
|
|
|
|
search_paths.push(SearchPath::from_cli_opt(&s[..], error_format));
|
|
|
|
}
|
|
|
|
|
|
|
|
let libs = parse_libs(matches, error_format);
|
|
|
|
|
|
|
|
let test = matches.opt_present("test");
|
|
|
|
|
|
|
|
let borrowck_mode = parse_borrowck_mode(&debugging_opts, error_format);
|
|
|
|
|
|
|
|
if !cg.remark.is_empty() && debuginfo == DebugInfo::None {
|
2019-12-22 17:42:04 -05:00
|
|
|
early_warn(error_format, "-C remark requires \"-C debuginfo=n\" to show source locations");
|
2019-10-11 23:30:58 +02:00
|
|
|
}
|
|
|
|
|
2019-10-16 09:55:40 -07:00
|
|
|
let externs = parse_externs(matches, &debugging_opts, error_format);
|
2019-10-11 23:30:58 +02:00
|
|
|
|
|
|
|
let crate_name = matches.opt_str("crate-name");
|
|
|
|
|
|
|
|
let remap_path_prefix = parse_remap_path_prefix(matches, error_format);
|
|
|
|
|
2019-11-03 21:42:03 -05:00
|
|
|
let pretty = parse_pretty(matches, &debugging_opts, error_format);
|
|
|
|
|
2019-10-11 23:30:58 +02:00
|
|
|
Options {
|
|
|
|
crate_types,
|
|
|
|
optimize: opt_level,
|
|
|
|
debuginfo,
|
|
|
|
lint_opts,
|
|
|
|
lint_cap,
|
|
|
|
describe_lints,
|
|
|
|
output_types,
|
|
|
|
search_paths,
|
|
|
|
maybe_sysroot: sysroot_opt,
|
|
|
|
target_triple,
|
|
|
|
test,
|
|
|
|
incremental,
|
|
|
|
debugging_opts,
|
|
|
|
prints,
|
|
|
|
borrowck_mode,
|
|
|
|
cg,
|
|
|
|
error_format,
|
|
|
|
externs,
|
2020-10-10 14:27:52 -04:00
|
|
|
unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()),
|
2019-10-11 23:30:58 +02:00
|
|
|
crate_name,
|
|
|
|
alt_std_name: None,
|
|
|
|
libs,
|
|
|
|
debug_assertions,
|
|
|
|
actually_rustdoc: false,
|
2020-09-02 10:40:56 +03:00
|
|
|
trimmed_def_paths: TrimmedDefPaths::default(),
|
2019-10-11 23:30:58 +02:00
|
|
|
cli_forced_codegen_units: codegen_units,
|
|
|
|
cli_forced_thinlto_off: disable_thinlto,
|
|
|
|
remap_path_prefix,
|
|
|
|
edition,
|
|
|
|
json_artifact_notifications,
|
2019-11-03 21:42:03 -05:00
|
|
|
pretty,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn parse_pretty(
|
|
|
|
matches: &getopts::Matches,
|
|
|
|
debugging_opts: &DebuggingOptions,
|
|
|
|
efmt: ErrorOutputType,
|
2019-11-20 08:27:42 -05:00
|
|
|
) -> Option<PpMode> {
|
2019-11-03 21:42:03 -05:00
|
|
|
let pretty = if debugging_opts.unstable_options {
|
|
|
|
matches.opt_default("pretty", "normal").map(|a| {
|
|
|
|
// stable pretty-print variants only
|
|
|
|
parse_pretty_inner(efmt, &a, false)
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
|
|
|
|
|
|
|
return if pretty.is_none() {
|
|
|
|
debugging_opts.unpretty.as_ref().map(|a| {
|
|
|
|
// extended with unstable pretty-print variants
|
|
|
|
parse_pretty_inner(efmt, &a, true)
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
pretty
|
|
|
|
};
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
fn parse_pretty_inner(efmt: ErrorOutputType, name: &str, extended: bool) -> PpMode {
|
2019-11-03 21:42:03 -05:00
|
|
|
use PpMode::*;
|
|
|
|
use PpSourceMode::*;
|
2019-11-20 08:27:42 -05:00
|
|
|
let first = match (name, extended) {
|
2019-11-03 21:42:03 -05:00
|
|
|
("normal", _) => PpmSource(PpmNormal),
|
|
|
|
("identified", _) => PpmSource(PpmIdentified),
|
|
|
|
("everybody_loops", true) => PpmSource(PpmEveryBodyLoops),
|
|
|
|
("expanded", _) => PpmSource(PpmExpanded),
|
|
|
|
("expanded,identified", _) => PpmSource(PpmExpandedIdentified),
|
|
|
|
("expanded,hygiene", _) => PpmSource(PpmExpandedHygiene),
|
|
|
|
("hir", true) => PpmHir(PpmNormal),
|
|
|
|
("hir,identified", true) => PpmHir(PpmIdentified),
|
|
|
|
("hir,typed", true) => PpmHir(PpmTyped),
|
|
|
|
("hir-tree", true) => PpmHirTree(PpmNormal),
|
|
|
|
("mir", true) => PpmMir,
|
|
|
|
("mir-cfg", true) => PpmMirCFG,
|
|
|
|
_ => {
|
|
|
|
if extended {
|
2019-12-22 17:42:04 -05:00
|
|
|
early_error(
|
|
|
|
efmt,
|
|
|
|
&format!(
|
|
|
|
"argument to `unpretty` must be one of `normal`, \
|
2019-11-03 21:42:03 -05:00
|
|
|
`expanded`, `identified`, `expanded,identified`, \
|
|
|
|
`expanded,hygiene`, `everybody_loops`, \
|
|
|
|
`hir`, `hir,identified`, `hir,typed`, `hir-tree`, \
|
|
|
|
`mir` or `mir-cfg`; got {}",
|
2019-12-22 17:42:04 -05:00
|
|
|
name
|
|
|
|
),
|
|
|
|
);
|
2019-11-03 21:42:03 -05:00
|
|
|
} else {
|
2019-12-22 17:42:04 -05:00
|
|
|
early_error(
|
|
|
|
efmt,
|
|
|
|
&format!(
|
|
|
|
"argument to `pretty` must be one of `normal`, \
|
2019-11-03 21:42:03 -05:00
|
|
|
`expanded`, `identified`, or `expanded,identified`; got {}",
|
2019-12-22 17:42:04 -05:00
|
|
|
name
|
|
|
|
),
|
|
|
|
);
|
2019-11-03 21:42:03 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
2020-08-13 23:05:01 -07:00
|
|
|
tracing::debug!("got unpretty option: {:?}", first);
|
2019-11-20 08:27:42 -05:00
|
|
|
first
|
2019-10-11 23:30:58 +02:00
|
|
|
}
|
2015-01-30 21:44:27 +13:00
|
|
|
}
|
|
|
|
|
2019-07-20 16:34:41 -04:00
|
|
|
pub fn make_crate_type_option() -> RustcOptGroup {
|
|
|
|
opt::multi_s(
|
|
|
|
"",
|
|
|
|
"crate-type",
|
|
|
|
"Comma separated list of types of crates
|
|
|
|
for the compiler to emit",
|
|
|
|
"[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]",
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2018-03-06 02:29:03 -03:00
|
|
|
pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
|
2014-07-19 21:11:26 -07:00
|
|
|
let mut crate_types: Vec<CrateType> = Vec::new();
|
2015-01-31 12:20:46 -05:00
|
|
|
for unparsed_crate_type in &list_list {
|
2014-11-27 13:53:34 -05:00
|
|
|
for part in unparsed_crate_type.split(',') {
|
2014-07-19 21:11:26 -07:00
|
|
|
let new_part = match part {
|
2018-03-06 02:29:03 -03:00
|
|
|
"lib" => default_lib_output(),
|
2018-07-26 11:13:11 -06:00
|
|
|
"rlib" => CrateType::Rlib,
|
|
|
|
"staticlib" => CrateType::Staticlib,
|
|
|
|
"dylib" => CrateType::Dylib,
|
|
|
|
"cdylib" => CrateType::Cdylib,
|
|
|
|
"bin" => CrateType::Executable,
|
|
|
|
"proc-macro" => CrateType::ProcMacro,
|
2019-12-22 17:42:04 -05:00
|
|
|
_ => return Err(format!("unknown crate type: `{}`", part)),
|
2014-07-19 21:11:26 -07:00
|
|
|
};
|
2015-02-09 19:30:22 +02:00
|
|
|
if !crate_types.contains(&new_part) {
|
|
|
|
crate_types.push(new_part)
|
|
|
|
}
|
2014-07-19 21:11:26 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-28 13:49:14 +07:00
|
|
|
Ok(crate_types)
|
2014-07-19 21:11:26 -07:00
|
|
|
}
|
|
|
|
|
2016-03-15 09:09:29 +01:00
|
|
|
pub mod nightly_options {
|
2016-09-24 19:20:57 +02:00
|
|
|
use super::{ErrorOutputType, OptionStability, RustcOptGroup};
|
2019-11-29 16:05:28 -05:00
|
|
|
use crate::early_error;
|
2019-12-22 17:42:04 -05:00
|
|
|
use rustc_feature::UnstableFeatures;
|
2016-03-15 09:09:29 +01:00
|
|
|
|
|
|
|
pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
|
2020-10-10 14:27:52 -04:00
|
|
|
match_is_nightly_build(matches)
|
|
|
|
&& matches.opt_strs("Z").iter().any(|x| *x == "unstable-options")
|
2016-03-15 09:09:29 +01:00
|
|
|
}
|
|
|
|
|
2020-10-10 14:27:52 -04:00
|
|
|
pub fn match_is_nightly_build(matches: &getopts::Matches) -> bool {
|
|
|
|
is_nightly_build(matches.opt_str("crate-name").as_deref())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_nightly_build(krate: Option<&str>) -> bool {
|
|
|
|
UnstableFeatures::from_environment(krate).is_nightly_build()
|
2016-03-15 09:09:29 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) {
|
2019-12-22 17:42:04 -05:00
|
|
|
let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options");
|
2020-10-10 14:27:52 -04:00
|
|
|
let really_allows_unstable_options = match_is_nightly_build(matches);
|
2016-03-15 09:09:29 +01:00
|
|
|
|
|
|
|
for opt in flags.iter() {
|
|
|
|
if opt.stability == OptionStability::Stable {
|
2018-03-06 02:29:03 -03:00
|
|
|
continue;
|
2016-03-15 09:09:29 +01:00
|
|
|
}
|
2017-06-08 14:20:55 -07:00
|
|
|
if !matches.opt_present(opt.name) {
|
2018-03-06 02:29:03 -03:00
|
|
|
continue;
|
2016-03-15 09:09:29 +01:00
|
|
|
}
|
2017-06-08 14:20:55 -07:00
|
|
|
if opt.name != "Z" && !has_z_unstable_option {
|
2018-03-06 02:29:03 -03:00
|
|
|
early_error(
|
|
|
|
ErrorOutputType::default(),
|
|
|
|
&format!(
|
|
|
|
"the `-Z unstable-options` flag must also be passed to enable \
|
|
|
|
the flag `{}`",
|
|
|
|
opt.name
|
|
|
|
),
|
|
|
|
);
|
2016-03-15 09:09:29 +01:00
|
|
|
}
|
|
|
|
if really_allows_unstable_options {
|
2018-03-06 02:29:03 -03:00
|
|
|
continue;
|
2016-03-15 09:09:29 +01:00
|
|
|
}
|
|
|
|
match opt.stability {
|
|
|
|
OptionStability::Unstable => {
|
2018-03-06 02:29:03 -03:00
|
|
|
let msg = format!(
|
|
|
|
"the option `{}` is only accepted on the \
|
|
|
|
nightly compiler",
|
|
|
|
opt.name
|
|
|
|
);
|
2016-03-15 09:09:29 +01:00
|
|
|
early_error(ErrorOutputType::default(), &msg);
|
|
|
|
}
|
|
|
|
OptionStability::Stable => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-20 15:45:07 -08:00
|
|
|
impl fmt::Display for CrateType {
|
2018-08-29 22:02:42 -07:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2014-06-11 10:48:17 +03:00
|
|
|
match *self {
|
2018-07-26 11:13:11 -06:00
|
|
|
CrateType::Executable => "bin".fmt(f),
|
|
|
|
CrateType::Dylib => "dylib".fmt(f),
|
|
|
|
CrateType::Rlib => "rlib".fmt(f),
|
|
|
|
CrateType::Staticlib => "staticlib".fmt(f),
|
|
|
|
CrateType::Cdylib => "cdylib".fmt(f),
|
|
|
|
CrateType::ProcMacro => "proc-macro".fmt(f),
|
2014-06-11 10:48:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-05-06 23:38:01 +12:00
|
|
|
|
2019-11-03 21:42:03 -05:00
|
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
|
|
pub enum PpSourceMode {
|
|
|
|
PpmNormal,
|
|
|
|
PpmEveryBodyLoops,
|
|
|
|
PpmExpanded,
|
|
|
|
PpmIdentified,
|
|
|
|
PpmExpandedIdentified,
|
|
|
|
PpmExpandedHygiene,
|
|
|
|
PpmTyped,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
|
|
|
pub enum PpMode {
|
|
|
|
PpmSource(PpSourceMode),
|
|
|
|
PpmHir(PpSourceMode),
|
|
|
|
PpmHirTree(PpSourceMode),
|
|
|
|
PpmMir,
|
|
|
|
PpmMirCFG,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl PpMode {
|
2019-11-20 08:27:42 -05:00
|
|
|
pub fn needs_ast_map(&self) -> bool {
|
2019-11-03 21:42:03 -05:00
|
|
|
use PpMode::*;
|
|
|
|
use PpSourceMode::*;
|
|
|
|
match *self {
|
2020-06-19 20:06:49 -04:00
|
|
|
PpmSource(PpmNormal | PpmIdentified) => false,
|
2019-12-22 17:42:04 -05:00
|
|
|
|
2020-06-19 20:06:49 -04:00
|
|
|
PpmSource(
|
|
|
|
PpmExpanded | PpmEveryBodyLoops | PpmExpandedIdentified | PpmExpandedHygiene,
|
|
|
|
)
|
2019-12-22 17:42:04 -05:00
|
|
|
| PpmHir(_)
|
|
|
|
| PpmHirTree(_)
|
|
|
|
| PpmMir
|
|
|
|
| PpmMirCFG => true,
|
2019-11-03 21:42:03 -05:00
|
|
|
PpmSource(PpmTyped) => panic!("invalid state"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn needs_analysis(&self) -> bool {
|
|
|
|
use PpMode::*;
|
2020-10-26 21:02:48 -04:00
|
|
|
matches!(*self, PpmMir | PpmMirCFG)
|
2019-11-03 21:42:03 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-12 13:05:20 -05:00
|
|
|
/// Command-line arguments passed to the compiler have to be incorporated with
|
2016-08-02 16:53:58 -04:00
|
|
|
/// the dependency tracking system for incremental compilation. This module
|
|
|
|
/// provides some utilities to make this more convenient.
|
|
|
|
///
|
2018-11-12 13:05:20 -05:00
|
|
|
/// The values of all command-line arguments that are relevant for dependency
|
2016-08-02 16:53:58 -04:00
|
|
|
/// tracking are hashed into a single value that determines whether the
|
|
|
|
/// incremental compilation cache can be re-used or not. This hashing is done
|
2019-09-06 03:57:44 +01:00
|
|
|
/// via the `DepTrackingHash` trait defined below, since the standard `Hash`
|
|
|
|
/// implementation might not be suitable (e.g., arguments are stored in a `Vec`,
|
2016-08-02 16:53:58 -04:00
|
|
|
/// the hash of which is order dependent, but we might not want the order of
|
|
|
|
/// arguments to make a difference for the hash).
|
|
|
|
///
|
2019-09-06 03:57:44 +01:00
|
|
|
/// However, since the value provided by `Hash::hash` often *is* suitable,
|
2016-08-02 16:53:58 -04:00
|
|
|
/// especially for primitive types, there is the
|
2019-09-06 03:57:44 +01:00
|
|
|
/// `impl_dep_tracking_hash_via_hash!()` macro that allows to simply reuse the
|
|
|
|
/// `Hash` implementation for `DepTrackingHash`. It's important though that
|
2016-08-02 16:53:58 -04:00
|
|
|
/// we have an opt-in scheme here, so one is hopefully forced to think about
|
2018-11-12 13:05:20 -05:00
|
|
|
/// how the hash should be calculated when adding a new command-line argument.
|
2019-12-17 23:22:55 +11:00
|
|
|
crate mod dep_tracking {
|
2019-12-22 17:42:04 -05:00
|
|
|
use super::{
|
2020-01-13 13:25:39 +00:00
|
|
|
CFGuard, CrateType, DebugInfo, ErrorOutputType, LinkerPluginLto, LtoCli, OptLevel,
|
2020-06-14 00:00:00 +00:00
|
|
|
OutputTypes, Passes, SanitizerSet, SourceFileHashAlgorithm, SwitchWithOptPath,
|
2020-09-02 10:40:56 +03:00
|
|
|
SymbolManglingVersion, TrimmedDefPaths,
|
2019-12-22 17:42:04 -05:00
|
|
|
};
|
2019-11-29 16:05:28 -05:00
|
|
|
use crate::lint;
|
2020-05-18 00:18:50 +03:00
|
|
|
use crate::utils::NativeLibKind;
|
2019-12-22 17:42:04 -05:00
|
|
|
use rustc_feature::UnstableFeatures;
|
2019-12-31 20:15:40 +03:00
|
|
|
use rustc_span::edition::Edition;
|
2020-05-07 03:34:27 +03:00
|
|
|
use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel};
|
2020-04-25 21:45:21 +03:00
|
|
|
use rustc_target::spec::{RelroLevel, TargetTriple, TlsModel};
|
2019-12-22 17:42:04 -05:00
|
|
|
use std::collections::hash_map::DefaultHasher;
|
2016-08-02 16:53:58 -04:00
|
|
|
use std::collections::BTreeMap;
|
2016-09-28 17:23:36 -07:00
|
|
|
use std::hash::Hash;
|
2016-08-02 16:53:58 -04:00
|
|
|
use std::path::PathBuf;
|
|
|
|
|
|
|
|
pub trait DepTrackingHash {
|
2017-05-02 05:55:20 +02:00
|
|
|
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
|
2016-08-02 16:53:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_dep_tracking_hash_via_hash {
|
2019-12-22 17:42:04 -05:00
|
|
|
($t:ty) => {
|
2016-08-02 16:53:58 -04:00
|
|
|
impl DepTrackingHash for $t {
|
2016-09-28 17:23:36 -07:00
|
|
|
fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
|
2016-08-02 16:53:58 -04:00
|
|
|
Hash::hash(self, hasher);
|
|
|
|
}
|
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
};
|
2016-08-02 16:53:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
macro_rules! impl_dep_tracking_hash_for_sortable_vec_of {
|
2019-12-22 17:42:04 -05:00
|
|
|
($t:ty) => {
|
2016-08-02 16:53:58 -04:00
|
|
|
impl DepTrackingHash for Vec<$t> {
|
2016-09-28 17:23:36 -07:00
|
|
|
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
|
2016-08-09 15:28:24 -04:00
|
|
|
let mut elems: Vec<&$t> = self.iter().collect();
|
2016-08-02 16:53:58 -04:00
|
|
|
elems.sort();
|
2016-08-09 15:28:24 -04:00
|
|
|
Hash::hash(&elems.len(), hasher);
|
|
|
|
for (index, elem) in elems.iter().enumerate() {
|
|
|
|
Hash::hash(&index, hasher);
|
|
|
|
DepTrackingHash::hash(*elem, hasher, error_format);
|
2016-08-02 16:53:58 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
};
|
2016-08-02 16:53:58 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl_dep_tracking_hash_via_hash!(bool);
|
|
|
|
impl_dep_tracking_hash_via_hash!(usize);
|
2017-03-08 16:28:47 -05:00
|
|
|
impl_dep_tracking_hash_via_hash!(u64);
|
2016-08-02 16:53:58 -04:00
|
|
|
impl_dep_tracking_hash_via_hash!(String);
|
2017-12-14 08:09:19 +01:00
|
|
|
impl_dep_tracking_hash_via_hash!(PathBuf);
|
2016-08-02 16:53:58 -04:00
|
|
|
impl_dep_tracking_hash_via_hash!(lint::Level);
|
|
|
|
impl_dep_tracking_hash_via_hash!(Option<bool>);
|
|
|
|
impl_dep_tracking_hash_via_hash!(Option<usize>);
|
|
|
|
impl_dep_tracking_hash_via_hash!(Option<String>);
|
2017-03-08 16:28:47 -05:00
|
|
|
impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
|
2019-01-29 16:10:49 -05:00
|
|
|
impl_dep_tracking_hash_via_hash!(Option<Vec<String>>);
|
2018-12-31 10:58:13 -08:00
|
|
|
impl_dep_tracking_hash_via_hash!(Option<MergeFunctions>);
|
2020-04-23 00:46:45 +03:00
|
|
|
impl_dep_tracking_hash_via_hash!(Option<RelocModel>);
|
2020-05-07 03:34:27 +03:00
|
|
|
impl_dep_tracking_hash_via_hash!(Option<CodeModel>);
|
2020-04-25 21:45:21 +03:00
|
|
|
impl_dep_tracking_hash_via_hash!(Option<TlsModel>);
|
2016-09-27 21:26:08 -05:00
|
|
|
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
|
2017-07-14 22:01:37 +02:00
|
|
|
impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
|
2016-08-02 16:53:58 -04:00
|
|
|
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
|
|
|
|
impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
|
|
|
|
impl_dep_tracking_hash_via_hash!(CrateType);
|
2018-12-31 10:58:13 -08:00
|
|
|
impl_dep_tracking_hash_via_hash!(MergeFunctions);
|
2016-08-02 16:53:58 -04:00
|
|
|
impl_dep_tracking_hash_via_hash!(PanicStrategy);
|
2017-07-14 22:01:37 +02:00
|
|
|
impl_dep_tracking_hash_via_hash!(RelroLevel);
|
2016-08-02 16:53:58 -04:00
|
|
|
impl_dep_tracking_hash_via_hash!(Passes);
|
|
|
|
impl_dep_tracking_hash_via_hash!(OptLevel);
|
2018-09-04 17:57:17 +02:00
|
|
|
impl_dep_tracking_hash_via_hash!(LtoCli);
|
2018-07-26 11:41:10 -06:00
|
|
|
impl_dep_tracking_hash_via_hash!(DebugInfo);
|
2016-08-02 16:53:58 -04:00
|
|
|
impl_dep_tracking_hash_via_hash!(UnstableFeatures);
|
|
|
|
impl_dep_tracking_hash_via_hash!(OutputTypes);
|
2020-05-18 00:18:50 +03:00
|
|
|
impl_dep_tracking_hash_via_hash!(NativeLibKind);
|
2020-06-14 00:00:00 +00:00
|
|
|
impl_dep_tracking_hash_via_hash!(SanitizerSet);
|
2020-01-13 13:25:39 +00:00
|
|
|
impl_dep_tracking_hash_via_hash!(CFGuard);
|
2018-03-14 15:27:06 +01:00
|
|
|
impl_dep_tracking_hash_via_hash!(TargetTriple);
|
2018-04-19 21:03:21 -07:00
|
|
|
impl_dep_tracking_hash_via_hash!(Edition);
|
2019-02-01 15:15:43 +01:00
|
|
|
impl_dep_tracking_hash_via_hash!(LinkerPluginLto);
|
2019-05-28 16:13:59 +02:00
|
|
|
impl_dep_tracking_hash_via_hash!(SwitchWithOptPath);
|
2019-01-29 07:24:32 +02:00
|
|
|
impl_dep_tracking_hash_via_hash!(SymbolManglingVersion);
|
2020-03-30 22:17:15 -07:00
|
|
|
impl_dep_tracking_hash_via_hash!(Option<SourceFileHashAlgorithm>);
|
2020-09-02 10:40:56 +03:00
|
|
|
impl_dep_tracking_hash_via_hash!(TrimmedDefPaths);
|
2016-08-02 16:53:58 -04:00
|
|
|
|
|
|
|
impl_dep_tracking_hash_for_sortable_vec_of!(String);
|
2017-12-14 08:09:19 +01:00
|
|
|
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
|
2016-08-02 16:53:58 -04:00
|
|
|
impl_dep_tracking_hash_for_sortable_vec_of!(CrateType);
|
|
|
|
impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
|
2020-05-18 01:52:34 +03:00
|
|
|
impl_dep_tracking_hash_for_sortable_vec_of!((String, Option<String>, NativeLibKind));
|
2017-03-08 16:28:47 -05:00
|
|
|
impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
|
2016-08-02 16:53:58 -04:00
|
|
|
|
|
|
|
impl<T1, T2> DepTrackingHash for (T1, T2)
|
2018-03-06 02:29:03 -03:00
|
|
|
where
|
|
|
|
T1: DepTrackingHash,
|
|
|
|
T2: DepTrackingHash,
|
2016-08-02 16:53:58 -04:00
|
|
|
{
|
2016-09-28 17:23:36 -07:00
|
|
|
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
|
2016-08-02 16:53:58 -04:00
|
|
|
Hash::hash(&0, hasher);
|
|
|
|
DepTrackingHash::hash(&self.0, hasher, error_format);
|
|
|
|
Hash::hash(&1, hasher);
|
|
|
|
DepTrackingHash::hash(&self.1, hasher, error_format);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-23 16:09:51 -08:00
|
|
|
impl<T1, T2, T3> DepTrackingHash for (T1, T2, T3)
|
2018-03-06 02:29:03 -03:00
|
|
|
where
|
|
|
|
T1: DepTrackingHash,
|
|
|
|
T2: DepTrackingHash,
|
|
|
|
T3: DepTrackingHash,
|
2016-11-23 16:09:51 -08:00
|
|
|
{
|
|
|
|
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
|
|
|
|
Hash::hash(&0, hasher);
|
|
|
|
DepTrackingHash::hash(&self.0, hasher, error_format);
|
|
|
|
Hash::hash(&1, hasher);
|
|
|
|
DepTrackingHash::hash(&self.1, hasher, error_format);
|
|
|
|
Hash::hash(&2, hasher);
|
|
|
|
DepTrackingHash::hash(&self.2, hasher, error_format);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-08-02 16:53:58 -04:00
|
|
|
// This is a stable hash because BTreeMap is a sorted container
|
2018-03-06 02:29:03 -03:00
|
|
|
pub fn stable_hash(
|
|
|
|
sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
|
|
|
|
hasher: &mut DefaultHasher,
|
|
|
|
error_format: ErrorOutputType,
|
|
|
|
) {
|
2016-08-02 16:53:58 -04:00
|
|
|
for (key, sub_hash) in sub_hashes {
|
|
|
|
// Using Hash::hash() instead of DepTrackingHash::hash() is fine for
|
|
|
|
// the keys, as they are just plain strings
|
|
|
|
Hash::hash(&key.len(), hasher);
|
|
|
|
Hash::hash(key, hasher);
|
|
|
|
sub_hash.hash(hasher, error_format);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|