rust/src/librustc/session/config.rs

3076 lines
118 KiB
Rust
Raw Normal View History

// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Contains infrastructure for configuring the compiler, including parsing
//! command line options.
pub use self::EntryFnType::*;
pub use self::CrateType::*;
pub use self::Passes::*;
pub use self::DebugInfoLevel::*;
use session::{early_error, early_warn, Session};
use session::search_paths::SearchPaths;
2017-09-18 10:14:52 +00:00
use ich::StableHashingContext;
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
use rustc_back::target::{Target, TargetTriple};
2017-09-18 10:14:52 +00:00
use rustc_data_structures::stable_hasher::ToStableHashKey;
use lint;
use middle::cstore;
use syntax::ast::{self, IntTy, UintTy};
2018-03-06 05:29:03 +00:00
use syntax::codemap::{FileName, FilePathMapping};
2018-03-15 03:30:06 +00:00
use syntax::edition::Edition;
use syntax::parse::token;
use syntax::parse;
use syntax::symbol::Symbol;
use syntax::feature_gate::UnstableFeatures;
use errors::{ColorConfig, FatalError, Handler};
use getopts;
use std::collections::{BTreeMap, BTreeSet};
use std::collections::btree_map::Iter as BTreeMapIter;
use std::collections::btree_map::Keys as BTreeMapKeysIter;
use std::collections::btree_map::Values as BTreeMapValuesIter;
use std::{fmt, str};
use std::hash::Hasher;
use std::collections::hash_map::DefaultHasher;
2016-11-15 08:54:27 +00:00
use std::collections::HashSet;
use std::iter::FromIterator;
2018-03-24 19:14:59 +00:00
use std::path::{Path, PathBuf};
pub struct Config {
pub target: Target,
pub isize_ty: IntTy,
pub usize_ty: UintTy,
}
#[derive(Clone, Hash, Debug)]
2016-12-30 04:28:11 +00:00
pub enum Sanitizer {
Address,
Leak,
Memory,
Thread,
}
#[derive(Clone, Copy, PartialEq, Hash)]
pub enum OptLevel {
2018-03-06 05:29:03 +00:00
No, // -O0
Less, // -O1
Default, // -O2
Aggressive, // -O3
2018-03-06 05:29:03 +00:00
Size, // -Os
SizeMin, // -Oz
}
#[derive(Clone, Copy, PartialEq, Hash)]
pub enum Lto {
/// Don't do any LTO whatsoever
No,
/// Do a full crate graph LTO. The flavor is determined by the compiler
/// (currently the default is "fat").
Yes,
/// 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,
}
#[derive(Clone, Copy, PartialEq, Hash)]
pub enum DebugInfoLevel {
NoDebugInfo,
LimitedDebugInfo,
FullDebugInfo,
}
2018-03-06 05:29:03 +00:00
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, RustcEncodable, RustcDecodable)]
pub enum OutputType {
Bitcode,
Assembly,
LlvmAssembly,
2017-02-16 21:59:09 +00:00
Mir,
Metadata,
Object,
Exe,
DepInfo,
}
2017-09-18 10:14:52 +00:00
impl_stable_hash_for!(enum self::OutputType {
Bitcode,
Assembly,
LlvmAssembly,
Mir,
Metadata,
Object,
Exe,
DepInfo
});
impl<'a, 'tcx> ToStableHashKey<StableHashingContext<'a>> for OutputType {
2017-09-18 10:14:52 +00:00
type KeyType = OutputType;
#[inline]
fn to_stable_hash_key(&self, _: &StableHashingContext<'a>) -> Self::KeyType {
2017-09-18 10:14:52 +00:00
*self
}
}
impl OutputType {
fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool {
match *self {
2018-03-06 05:29:03 +00:00
OutputType::Exe | OutputType::DepInfo => true,
OutputType::Bitcode
| OutputType::Assembly
| OutputType::LlvmAssembly
| OutputType::Mir
| OutputType::Object
| OutputType::Metadata => false,
}
}
fn shorthand(&self) -> &'static str {
match *self {
OutputType::Bitcode => "llvm-bc",
OutputType::Assembly => "asm",
OutputType::LlvmAssembly => "llvm-ir",
2017-02-16 21:59:09 +00:00
OutputType::Mir => "mir",
OutputType::Object => "obj",
OutputType::Metadata => "metadata",
OutputType::Exe => "link",
OutputType::DepInfo => "dep-info",
}
}
fn from_shorthand(shorthand: &str) -> Option<Self> {
Some(match shorthand {
2018-03-06 05:29:03 +00: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,
_ => 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(),
)
}
pub fn extension(&self) -> &'static str {
match *self {
OutputType::Bitcode => "bc",
OutputType::Assembly => "s",
OutputType::LlvmAssembly => "ll",
2017-02-16 21:59:09 +00:00
OutputType::Mir => "mir",
OutputType::Object => "o",
OutputType::Metadata => "rmeta",
OutputType::DepInfo => "d",
OutputType::Exe => "",
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ErrorOutputType {
HumanReadable(ColorConfig),
2017-11-03 12:38:26 +00:00
Json(bool),
2017-09-16 17:24:08 +00:00
Short(ColorConfig),
}
impl Default for ErrorOutputType {
fn default() -> ErrorOutputType {
ErrorOutputType::HumanReadable(ColorConfig::Auto)
}
}
// 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 commandline arguments.
#[derive(Clone, Hash)]
pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>);
2017-09-18 10:14:52 +00:00
impl_stable_hash_for!(tuple_struct self::OutputTypes {
map
});
impl OutputTypes {
pub fn new(entries: &[(OutputType, Option<PathBuf>)]) -> OutputTypes {
2018-03-06 05:29:03 +00:00
OutputTypes(BTreeMap::from_iter(
entries.iter().map(|&(k, ref v)| (k, v.clone())),
))
}
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)
}
pub fn keys<'a>(&'a self) -> BTreeMapKeysIter<'a, OutputType, Option<PathBuf>> {
self.0.keys()
}
pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option<PathBuf>> {
self.0.values()
}
2016-12-29 00:23:38 +00:00
// True if any of the output types require codegen or linking.
pub fn should_trans(&self) -> bool {
self.0.keys().any(|k| match *k {
2018-03-06 05:29:03 +00:00
OutputType::Bitcode
| OutputType::Assembly
| OutputType::LlvmAssembly
| OutputType::Mir
| OutputType::Object
| OutputType::Exe => true,
OutputType::Metadata | OutputType::DepInfo => false,
2016-12-29 00:23:38 +00: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 commandline arguments.
#[derive(Clone, Hash)]
pub struct Externs(BTreeMap<String, BTreeSet<String>>);
impl Externs {
pub fn new(data: BTreeMap<String, BTreeSet<String>>) -> Externs {
Externs(data)
}
pub fn get(&self, key: &str) -> Option<&BTreeSet<String>> {
self.0.get(key)
}
pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<String>> {
self.0.iter()
}
}
macro_rules! hash_option {
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [UNTRACKED]) => ({});
($opt_name:ident, $opt_expr:expr, $sub_hashes:expr, [TRACKED]) => ({
if $sub_hashes.insert(stringify!($opt_name),
2018-02-23 18:02:10 +00:00
$opt_expr as &dyn dep_tracking::DepTrackingHash).is_some() {
bug!("Duplicate key in CLI DepTrackingHash: {}", stringify!($opt_name))
}
});
($opt_name:ident,
$opt_expr:expr,
$sub_hashes:expr,
[UNTRACKED_WITH_WARNING $warn_val:expr, $warn_text:expr, $error_format:expr]) => ({
if *$opt_expr == $warn_val {
early_warn($error_format, $warn_text)
}
});
}
macro_rules! top_level_options {
(pub struct Options { $(
$opt:ident : $t:ty [$dep_tracking_marker:ident $($warn_val:expr, $warn_text:expr)*],
)* } ) => (
#[derive(Clone)]
pub struct Options {
$(pub $opt: $t),*
}
impl Options {
pub fn dep_tracking_hash(&self) -> u64 {
let mut sub_hashes = BTreeMap::new();
$({
hash_option!($opt,
&self.$opt,
&mut sub_hashes,
[$dep_tracking_marker $($warn_val,
$warn_text,
self.error_format)*]);
})*
let mut hasher = DefaultHasher::new();
dep_tracking::stable_hash(sub_hashes,
&mut hasher,
self.error_format);
hasher.finish()
}
}
);
Preliminary feature staging This partially implements the feature staging described in the [release channel RFC][rc]. It does not yet fully conform to the RFC as written, but does accomplish its goals sufficiently for the 1.0 alpha release. It has three primary user-visible effects: * On the nightly channel, use of unstable APIs generates a warning. * On the beta channel, use of unstable APIs generates a warning. * On the beta channel, use of feature gates generates a warning. Code that does not trigger these warnings is considered 'stable', modulo pre-1.0 bugs. Disabling the warnings for unstable APIs continues to be done in the existing (i.e. old) style, via `#[allow(...)]`, not that specified in the RFC. I deem this marginally acceptable since any code that must do this is not using the stable dialect of Rust. Use of feature gates is itself gated with the new 'unstable_features' lint, on nightly set to 'allow', and on beta 'warn'. The attribute scheme used here corresponds to an older version of the RFC, with the `#[staged_api]` crate attribute toggling the staging behavior of the stability attributes, but the user impact is only in-tree so I'm not concerned about having to make design changes later (and I may ultimately prefer the scheme here after all, with the `#[staged_api]` crate attribute). Since the Rust codebase itself makes use of unstable features the compiler and build system to a midly elaborate dance to allow it to bootstrap while disobeying these lints (which would otherwise be errors because Rust builds with `-D warnings`). This patch includes one significant hack that causes a regression. Because the `format_args!` macro emits calls to unstable APIs it would trigger the lint. I added a hack to the lint to make it not trigger, but this in turn causes arguments to `println!` not to be checked for feature gates. I don't presently understand macro expansion well enough to fix. This is bug #20661. Closes #16678 [rc]: https://github.com/rust-lang/rfcs/blob/master/text/0507-release-channels.md
2015-01-06 14:26:08 +00:00
}
// The top-level commandline options struct
//
// For each option, one has to specify how it behaves with regard to the
// dependency tracking system of incremental compilation. This is done via the
// square-bracketed directive after the field type. The options are:
//
// [TRACKED]
// A change in the given field will cause the compiler to completely clear the
// incremental compilation cache before proceeding.
//
// [UNTRACKED]
// Incremental compilation is not influenced by this option.
//
// [UNTRACKED_WITH_WARNING(val, warning)]
// The option is incompatible with incremental compilation in some way. If it
// has the value `val`, the string `warning` is emitted as a warning.
//
// If you add a new option to this struct or one of the sub-structs like
// CodegenOptions, think about how it influences incremental compilation. If in
// doubt, specify [TRACKED], which is always "correct" but might lead to
// unnecessary re-compilation.
top_level_options!(
pub struct Options {
// The crate config requested for the session, which may be combined
// with additional crate configurations during the compile process
crate_types: Vec<CrateType> [TRACKED],
optimize: OptLevel [TRACKED],
// Include the debug_assertions flag into dependency tracking, since it
// can influence whether overflow checks are done or not.
debug_assertions: bool [TRACKED],
debuginfo: DebugInfoLevel [TRACKED],
lint_opts: Vec<(String, lint::Level)> [TRACKED],
lint_cap: Option<lint::Level> [TRACKED],
describe_lints: bool [UNTRACKED],
output_types: OutputTypes [TRACKED],
search_paths: SearchPaths [UNTRACKED],
2017-02-21 21:18:58 +00:00
libs: Vec<(String, Option<String>, Option<cstore::NativeLibraryKind>)> [TRACKED],
maybe_sysroot: Option<PathBuf> [TRACKED],
target_triple: TargetTriple [TRACKED],
test: bool [TRACKED],
error_format: ErrorOutputType [UNTRACKED],
// if Some, enable incremental compilation, using the given
// directory to store intermediate results
incremental: Option<PathBuf> [UNTRACKED],
debugging_opts: DebuggingOptions [TRACKED],
prints: Vec<PrintRequest> [UNTRACKED],
// Determines which borrow checker(s) to run. This is the parsed, sanitized
// version of `debugging_opts.borrowck`, which is just a plain string.
borrowck_mode: BorrowckMode [UNTRACKED],
cg: CodegenOptions [TRACKED],
externs: Externs [UNTRACKED],
crate_name: Option<String> [TRACKED],
// An optional name to use as the crate for std during std injection,
// written `extern crate name as std`. Defaults to `std`. Used by
// out-of-tree drivers.
alt_std_name: Option<String> [TRACKED],
// Indicates how the compiler should treat unstable features
unstable_features: UnstableFeatures [TRACKED],
// Indicates whether this run of the compiler is actually rustdoc. This
// is currently just a hack and will be removed eventually, so please
// try to not rely on this too much.
actually_rustdoc: bool [TRACKED],
2017-09-25 19:26:25 +00:00
// Specifications of codegen units / ThinLTO which are forced as a
// result of parsing command line options. These are not necessarily
// what rustc was invoked with, but massaged a bit to agree with
// commands like `--emit llvm-ir` which they're often incompatible with
// if we otherwise use the defaults of rustc.
cli_forced_codegen_units: Option<usize> [UNTRACKED],
cli_forced_thinlto_off: bool [UNTRACKED],
// Remap source path prefixes in all output (messages, object files, debug, etc)
remap_path_prefix: Vec<(PathBuf, PathBuf)> [UNTRACKED],
}
);
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
pub enum PrintRequest {
FileNames,
Sysroot,
CrateName,
Cfg,
TargetList,
TargetCPUs,
TargetFeatures,
RelocationModels,
CodeModels,
TlsModels,
TargetSpec,
2017-08-22 20:20:42 +00:00
NativeStaticLibs,
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum BorrowckMode {
Ast,
Mir,
Compare,
}
impl BorrowckMode {
/// Should we emit the AST-based borrow checker errors?
pub fn use_ast(self) -> bool {
match self {
BorrowckMode::Ast => true,
BorrowckMode::Compare => true,
BorrowckMode::Mir => false,
}
}
/// Should we emit the MIR-based borrow checker errors?
pub fn use_mir(self) -> bool {
match self {
BorrowckMode::Ast => false,
BorrowckMode::Compare => true,
BorrowckMode::Mir => true,
}
}
}
pub enum Input {
/// Load source from file
File(PathBuf),
Str {
/// String that is shown in place of a filename
name: FileName,
/// Anonymous source string
input: String,
},
}
impl Input {
pub fn filestem(&self) -> String {
match *self {
2018-03-06 05:29:03 +00:00
Input::File(ref ifile) => ifile.file_stem().unwrap().to_str().unwrap().to_string(),
Input::Str { .. } => "rust_out".to_string(),
}
}
}
#[derive(Clone)]
pub struct OutputFilenames {
pub out_directory: PathBuf,
pub out_filestem: String,
pub single_output_file: Option<PathBuf>,
pub extra: String,
pub outputs: OutputTypes,
}
2017-09-18 10:14:52 +00:00
impl_stable_hash_for!(struct self::OutputFilenames {
out_directory,
out_filestem,
single_output_file,
extra,
outputs
});
pub const RUST_CGU_EXT: &str = "rcgu";
impl OutputFilenames {
pub fn path(&self, flavor: OutputType) -> PathBuf {
2018-03-06 05:29:03 +00:00
self.outputs
.get(&flavor)
.and_then(|p| p.to_owned())
.or_else(|| self.single_output_file.clone())
.unwrap_or_else(|| self.temp_path(flavor, None))
}
/// Get the path where a compilation artifact of the given type for the
/// 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 05:29:03 +00:00
pub fn temp_path(&self, flavor: OutputType, codegen_unit_name: Option<&str>) -> PathBuf {
let extension = flavor.extension();
self.temp_path_ext(extension, codegen_unit_name)
}
/// Like temp_path, but also supports things where there is no corresponding
/// OutputType, like no-opt-bitcode or lto-bitcode.
2018-03-06 05:29:03 +00:00
pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf {
let base = self.out_directory.join(&self.filestem());
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 15:14:38 +00:00
extension.push_str(codegen_unit_name);
}
if !ext.is_empty() {
if !extension.is_empty() {
extension.push_str(".");
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 15:14:38 +00:00
extension.push_str(RUST_CGU_EXT);
extension.push_str(".");
}
extension.push_str(ext);
}
let path = base.with_extension(&extension[..]);
path
}
pub fn with_extension(&self, extension: &str) -> PathBuf {
2018-03-06 05:29:03 +00:00
self.out_directory
.join(&self.filestem())
.with_extension(extension)
}
pub fn filestem(&self) -> String {
format!("{}{}", self.out_filestem, self.extra)
}
}
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 05:29:03 +00:00
(option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE")
}
/// Some reasonable defaults
pub fn basic_options() -> Options {
Options {
crate_types: Vec::new(),
optimize: OptLevel::No,
debuginfo: NoDebugInfo,
lint_opts: Vec::new(),
lint_cap: None,
describe_lints: false,
output_types: OutputTypes(BTreeMap::new()),
search_paths: SearchPaths::new(),
maybe_sysroot: None,
target_triple: TargetTriple::from_triple(host_triple()),
test: false,
incremental: None,
debugging_opts: basic_debugging_options(),
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
prints: Vec::new(),
borrowck_mode: BorrowckMode::Ast,
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,
cli_forced_codegen_units: None,
cli_forced_thinlto_off: false,
remap_path_prefix: Vec::new(),
}
}
impl Options {
/// True if there is a reason to build the dep graph.
pub fn build_dep_graph(&self) -> bool {
2018-03-06 05:29:03 +00:00
self.incremental.is_some() || self.debugging_opts.dump_dep_graph
|| self.debugging_opts.query_dep_graph
}
#[inline(always)]
pub fn enable_dep_node_debug_strs(&self) -> bool {
2018-03-06 05:29:03 +00:00
cfg!(debug_assertions)
&& (self.debugging_opts.query_dep_graph || self.debugging_opts.incremental_info)
}
pub fn file_path_mapping(&self) -> FilePathMapping {
FilePathMapping::new(self.remap_path_prefix.clone())
}
/// True if there will be an output file generated
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
}
}
// The type of entry function, so
// users can have their own entry
// functions
2015-03-30 13:38:44 +00:00
#[derive(Copy, Clone, PartialEq)]
pub enum EntryFnType {
EntryMain,
EntryStart,
}
2015-01-28 13:34:18 +00:00
#[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)]
pub enum CrateType {
CrateTypeExecutable,
CrateTypeDylib,
CrateTypeRlib,
CrateTypeStaticlib,
CrateTypeCdylib,
CrateTypeProcMacro,
}
#[derive(Clone, Hash)]
pub enum Passes {
SomePasses(Vec<String>),
AllPasses,
}
impl Passes {
pub fn is_empty(&self) -> bool {
match *self {
SomePasses(ref v) => v.is_empty(),
AllPasses => false,
}
}
}
/// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all
/// at once. The goal of this macro is to define an interface that can be
/// programmatically used by the option parser in order to initialize the struct
/// without hardcoding field names all over the place.
///
/// The goal is to invoke this macro once with the correct fields, and then this
/// macro generates all necessary code. The main gotcha of this macro is the
/// cgsetters module which is a bunch of generated code to parse an option into
/// its respective field in the struct. There are a few hand-written parsers for
/// parsing specific types of values in this module.
macro_rules! options {
($struct_name:ident, $setter_name:ident, $defaultfn:ident,
$buildfn:ident, $prefix:expr, $outputname:expr,
$stat:ident, $mod_desc:ident, $mod_set:ident,
$($opt:ident : $t:ty = (
$init:expr,
$parse:ident,
[$dep_tracking_marker:ident $(($dep_warn_val:expr, $dep_warn_text:expr))*],
$desc:expr)
),* ,) =>
(
#[derive(Clone)]
pub struct $struct_name { $(pub $opt: $t),* }
pub fn $defaultfn() -> $struct_name {
$struct_name { $($opt: $init),* }
}
pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $struct_name
{
let mut op = $defaultfn();
for option in matches.opt_strs($prefix) {
let mut iter = option.splitn(2, '=');
let key = iter.next().unwrap();
let value = iter.next();
let option_to_lookup = key.replace("-", "_");
let mut found = false;
2015-01-31 17:20:46 +00:00
for &(candidate, setter, opt_type_desc, _) in $stat {
if option_to_lookup != candidate { continue }
if !setter(&mut op, value) {
match (value, opt_type_desc) {
(Some(..), None) => {
early_error(error_format, &format!("{} option `{}` takes no \
value", $outputname, key))
}
(None, Some(type_desc)) => {
early_error(error_format, &format!("{0} option `{1}` requires \
{2} ({3} {1}=<value>)",
$outputname, key,
type_desc, $prefix))
}
(Some(value), Some(type_desc)) => {
early_error(error_format, &format!("incorrect value `{}` for {} \
option `{}` - {} was expected",
value, $outputname,
key, type_desc))
}
(None, None) => bug!()
}
}
found = true;
break;
}
if !found {
early_error(error_format, &format!("unknown {} option: `{}`",
$outputname, key));
}
}
return op;
}
impl<'a> dep_tracking::DepTrackingHash for $struct_name {
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
let mut sub_hashes = BTreeMap::new();
$({
hash_option!($opt,
&self.$opt,
&mut sub_hashes,
[$dep_tracking_marker $($dep_warn_val,
$dep_warn_text,
error_format)*]);
})*
dep_tracking::stable_hash(sub_hashes, hasher, error_format);
}
}
pub type $setter_name = fn(&mut $struct_name, v: Option<&str>) -> bool;
pub const $stat: &'static [(&'static str, $setter_name,
Option<&'static str>, &'static str)] =
&[ $( (stringify!($opt), $mod_set::$opt, $mod_desc::$parse, $desc) ),* ];
#[allow(non_upper_case_globals, dead_code)]
mod $mod_desc {
pub const parse_bool: Option<&'static str> = None;
pub const parse_opt_bool: Option<&'static str> =
Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`");
pub const parse_string: Option<&'static str> = Some("a string");
pub const parse_string_push: Option<&'static str> = Some("a string");
pub const parse_pathbuf_push: Option<&'static str> = Some("a path");
pub const parse_opt_string: Option<&'static str> = Some("a string");
pub const parse_opt_pathbuf: Option<&'static str> = Some("a path");
pub const parse_list: Option<&'static str> = Some("a space-separated list of strings");
pub const parse_opt_list: Option<&'static str> = Some("a space-separated list of strings");
pub const parse_uint: Option<&'static str> = Some("a number");
pub const parse_passes: Option<&'static str> =
Some("a space-separated list of passes, or `all`");
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
pub const parse_opt_uint: Option<&'static str> =
Some("a number");
rustc: Implement custom panic runtimes This commit is an implementation of [RFC 1513] which allows applications to alter the behavior of panics at compile time. A new compiler flag, `-C panic`, is added and accepts the values `unwind` or `panic`, with the default being `unwind`. This model affects how code is generated for the local crate, skipping generation of landing pads with `-C panic=abort`. [RFC 1513]: https://github.com/rust-lang/rfcs/blob/master/text/1513-less-unwinding.md Panic implementations are then provided by crates tagged with `#![panic_runtime]` and lazily required by crates with `#![needs_panic_runtime]`. The panic strategy (`-C panic` value) of the panic runtime must match the final product, and if the panic strategy is not `abort` then the entire DAG must have the same panic strategy. With the `-C panic=abort` strategy, users can expect a stable method to disable generation of landing pads, improving optimization in niche scenarios, decreasing compile time, and decreasing output binary size. With the `-C panic=unwind` strategy users can expect the existing ability to isolate failure in Rust code from the outside world. Organizationally, this commit dismantles the `sys_common::unwind` module in favor of some bits moving part of it to `libpanic_unwind` and the rest into the `panicking` module in libstd. The custom panic runtime support is pretty similar to the custom allocator support with the only major difference being how the panic runtime is injected (takes the `-C panic` flag into account).
2016-04-08 23:18:40 +00:00
pub const parse_panic_strategy: Option<&'static str> =
Some("either `panic` or `abort`");
pub const parse_relro_level: Option<&'static str> =
Some("one of: `full`, `partial`, or `off`");
2016-12-30 04:28:11 +00:00
pub const parse_sanitizer: Option<&'static str> =
Some("one of: `address`, `leak`, `memory` or `thread`");
-Z linker-flavor This patch adds a `-Z linker-flavor` flag to rustc which can be used to invoke the linker using a different interface. For example, by default rustc assumes that all the Linux targets will be linked using GCC. This makes it impossible to use LLD as a linker using just `-C linker=ld.lld` because that will invoke LLD with invalid command line arguments. (e.g. rustc will pass -Wl,--gc-sections to LLD but LLD doesn't understand that; --gc-sections would be the right argument) With this patch one can pass `-Z linker-flavor=ld` to rustc to invoke the linker using a LD-like interface. This way, `rustc -C linker=ld.lld -Z linker-flavor=ld` will invoke LLD with the right arguments. `-Z linker-flavor` accepts 4 different arguments: `em` (emcc), `ld`, `gcc`, `msvc` (link.exe). `em`, `gnu` and `msvc` cover all the existing linker interfaces. `ld` is a new flavor for interfacing GNU's ld and LLD. This patch also changes target specifications. `linker-flavor` is now a mandatory field that specifies the *default* linker flavor that the target will use. This change also makes the linker interface *explicit*; before, it used to be derived from other fields like linker-is-gnu, is-like-msvc, is-like-emscripten, etc. Another change to target specifications is that the fields `pre-link-args`, `post-link-args` and `late-link-args` now expect a map from flavor to linker arguments. ``` diff - "pre-link-args": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"], + "pre-link-args": { + "gcc": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"], + "ld": ["--as-needed", "-z,-noexecstack"], + }, ``` [breaking-change] for users of custom targets specifications
2017-02-21 19:47:15 +00:00
pub const parse_linker_flavor: Option<&'static str> =
Some(::rustc_back::LinkerFlavor::one_of());
pub const parse_optimization_fuel: Option<&'static str> =
Some("crate=integer");
pub const parse_unpretty: Option<&'static str> =
Some("`string` or `string=string`");
pub const parse_lto: Option<&'static str> =
Some("one of `thin`, `fat`, or omitted");
2018-03-15 03:30:06 +00:00
pub const parse_edition: Option<&'static str> =
2018-02-04 16:52:26 +00:00
Some("one of: `2015`, `2018`");
}
#[allow(dead_code)]
mod $mod_set {
2018-03-06 22:05:03 +00:00
use super::{$struct_name, Passes, SomePasses, AllPasses, Sanitizer, Lto};
use rustc_back::{LinkerFlavor, PanicStrategy, RelroLevel};
use std::path::PathBuf;
2018-03-15 03:30:06 +00:00
use syntax::edition::Edition;
$(
pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool {
$parse(&mut cg.$opt, v)
}
)*
fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
match v {
Some(..) => false,
None => { *slot = true; true }
}
}
fn parse_opt_bool(slot: &mut Option<bool>, v: Option<&str>) -> bool {
match v {
Some(s) => {
match s {
"n" | "no" | "off" => {
*slot = Some(false);
}
"y" | "yes" | "on" => {
*slot = Some(true);
}
_ => { return false; }
}
true
},
None => { *slot = Some(true); true }
}
}
fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool {
match v {
Some(s) => { *slot = Some(s.to_string()); true },
None => false,
}
}
fn parse_opt_pathbuf(slot: &mut Option<PathBuf>, v: Option<&str>) -> bool {
match v {
Some(s) => { *slot = Some(PathBuf::from(s)); true },
None => false,
}
}
fn parse_string(slot: &mut String, v: Option<&str>) -> bool {
match v {
Some(s) => { *slot = s.to_string(); true },
None => false,
}
}
fn parse_string_push(slot: &mut Vec<String>, v: Option<&str>) -> bool {
match v {
Some(s) => { slot.push(s.to_string()); true },
None => false,
}
}
fn parse_pathbuf_push(slot: &mut Vec<PathBuf>, v: Option<&str>) -> bool {
match v {
Some(s) => { slot.push(PathBuf::from(s)); true },
None => false,
}
}
fn parse_list(slot: &mut Vec<String>, v: Option<&str>)
-> bool {
match v {
Some(s) => {
for s in s.split_whitespace() {
slot.push(s.to_string());
}
true
},
None => false,
}
}
fn parse_opt_list(slot: &mut Option<Vec<String>>, v: Option<&str>)
-> bool {
match v {
Some(s) => {
let v = s.split_whitespace().map(|s| s.to_string()).collect();
*slot = Some(v);
true
},
None => false,
}
}
fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool {
match v.and_then(|s| s.parse().ok()) {
Some(i) => { *slot = i; true },
None => false
}
}
fn parse_opt_uint(slot: &mut Option<usize>, v: Option<&str>) -> bool {
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
match v {
Some(s) => { *slot = s.parse().ok(); slot.is_some() }
2017-09-25 19:26:25 +00:00
None => { *slot = None; false }
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
}
}
fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
match v {
Some("all") => {
*slot = AllPasses;
true
}
v => {
let mut passes = vec![];
if parse_list(&mut passes, v) {
*slot = SomePasses(passes);
true
} else {
false
}
}
}
}
rustc: Implement custom panic runtimes This commit is an implementation of [RFC 1513] which allows applications to alter the behavior of panics at compile time. A new compiler flag, `-C panic`, is added and accepts the values `unwind` or `panic`, with the default being `unwind`. This model affects how code is generated for the local crate, skipping generation of landing pads with `-C panic=abort`. [RFC 1513]: https://github.com/rust-lang/rfcs/blob/master/text/1513-less-unwinding.md Panic implementations are then provided by crates tagged with `#![panic_runtime]` and lazily required by crates with `#![needs_panic_runtime]`. The panic strategy (`-C panic` value) of the panic runtime must match the final product, and if the panic strategy is not `abort` then the entire DAG must have the same panic strategy. With the `-C panic=abort` strategy, users can expect a stable method to disable generation of landing pads, improving optimization in niche scenarios, decreasing compile time, and decreasing output binary size. With the `-C panic=unwind` strategy users can expect the existing ability to isolate failure in Rust code from the outside world. Organizationally, this commit dismantles the `sys_common::unwind` module in favor of some bits moving part of it to `libpanic_unwind` and the rest into the `panicking` module in libstd. The custom panic runtime support is pretty similar to the custom allocator support with the only major difference being how the panic runtime is injected (takes the `-C panic` flag into account).
2016-04-08 23:18:40 +00:00
fn parse_panic_strategy(slot: &mut Option<PanicStrategy>, v: Option<&str>) -> bool {
rustc: Implement custom panic runtimes This commit is an implementation of [RFC 1513] which allows applications to alter the behavior of panics at compile time. A new compiler flag, `-C panic`, is added and accepts the values `unwind` or `panic`, with the default being `unwind`. This model affects how code is generated for the local crate, skipping generation of landing pads with `-C panic=abort`. [RFC 1513]: https://github.com/rust-lang/rfcs/blob/master/text/1513-less-unwinding.md Panic implementations are then provided by crates tagged with `#![panic_runtime]` and lazily required by crates with `#![needs_panic_runtime]`. The panic strategy (`-C panic` value) of the panic runtime must match the final product, and if the panic strategy is not `abort` then the entire DAG must have the same panic strategy. With the `-C panic=abort` strategy, users can expect a stable method to disable generation of landing pads, improving optimization in niche scenarios, decreasing compile time, and decreasing output binary size. With the `-C panic=unwind` strategy users can expect the existing ability to isolate failure in Rust code from the outside world. Organizationally, this commit dismantles the `sys_common::unwind` module in favor of some bits moving part of it to `libpanic_unwind` and the rest into the `panicking` module in libstd. The custom panic runtime support is pretty similar to the custom allocator support with the only major difference being how the panic runtime is injected (takes the `-C panic` flag into account).
2016-04-08 23:18:40 +00:00
match v {
Some("unwind") => *slot = Some(PanicStrategy::Unwind),
Some("abort") => *slot = Some(PanicStrategy::Abort),
rustc: Implement custom panic runtimes This commit is an implementation of [RFC 1513] which allows applications to alter the behavior of panics at compile time. A new compiler flag, `-C panic`, is added and accepts the values `unwind` or `panic`, with the default being `unwind`. This model affects how code is generated for the local crate, skipping generation of landing pads with `-C panic=abort`. [RFC 1513]: https://github.com/rust-lang/rfcs/blob/master/text/1513-less-unwinding.md Panic implementations are then provided by crates tagged with `#![panic_runtime]` and lazily required by crates with `#![needs_panic_runtime]`. The panic strategy (`-C panic` value) of the panic runtime must match the final product, and if the panic strategy is not `abort` then the entire DAG must have the same panic strategy. With the `-C panic=abort` strategy, users can expect a stable method to disable generation of landing pads, improving optimization in niche scenarios, decreasing compile time, and decreasing output binary size. With the `-C panic=unwind` strategy users can expect the existing ability to isolate failure in Rust code from the outside world. Organizationally, this commit dismantles the `sys_common::unwind` module in favor of some bits moving part of it to `libpanic_unwind` and the rest into the `panicking` module in libstd. The custom panic runtime support is pretty similar to the custom allocator support with the only major difference being how the panic runtime is injected (takes the `-C panic` flag into account).
2016-04-08 23:18:40 +00:00
_ => return false
}
true
}
2016-12-30 04:28:11 +00:00
fn parse_relro_level(slot: &mut Option<RelroLevel>, v: Option<&str>) -> bool {
match v {
Some(s) => {
match s.parse::<RelroLevel>() {
Ok(level) => *slot = Some(level),
_ => return false
}
},
_ => return false
}
true
}
2016-12-30 04:28:11 +00:00
fn parse_sanitizer(slote: &mut Option<Sanitizer>, v: Option<&str>) -> bool {
match v {
Some("address") => *slote = Some(Sanitizer::Address),
Some("leak") => *slote = Some(Sanitizer::Leak),
Some("memory") => *slote = Some(Sanitizer::Memory),
Some("thread") => *slote = Some(Sanitizer::Thread),
_ => return false,
}
true
}
-Z linker-flavor This patch adds a `-Z linker-flavor` flag to rustc which can be used to invoke the linker using a different interface. For example, by default rustc assumes that all the Linux targets will be linked using GCC. This makes it impossible to use LLD as a linker using just `-C linker=ld.lld` because that will invoke LLD with invalid command line arguments. (e.g. rustc will pass -Wl,--gc-sections to LLD but LLD doesn't understand that; --gc-sections would be the right argument) With this patch one can pass `-Z linker-flavor=ld` to rustc to invoke the linker using a LD-like interface. This way, `rustc -C linker=ld.lld -Z linker-flavor=ld` will invoke LLD with the right arguments. `-Z linker-flavor` accepts 4 different arguments: `em` (emcc), `ld`, `gcc`, `msvc` (link.exe). `em`, `gnu` and `msvc` cover all the existing linker interfaces. `ld` is a new flavor for interfacing GNU's ld and LLD. This patch also changes target specifications. `linker-flavor` is now a mandatory field that specifies the *default* linker flavor that the target will use. This change also makes the linker interface *explicit*; before, it used to be derived from other fields like linker-is-gnu, is-like-msvc, is-like-emscripten, etc. Another change to target specifications is that the fields `pre-link-args`, `post-link-args` and `late-link-args` now expect a map from flavor to linker arguments. ``` diff - "pre-link-args": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"], + "pre-link-args": { + "gcc": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"], + "ld": ["--as-needed", "-z,-noexecstack"], + }, ``` [breaking-change] for users of custom targets specifications
2017-02-21 19:47:15 +00:00
fn parse_linker_flavor(slote: &mut Option<LinkerFlavor>, v: Option<&str>) -> bool {
match v.and_then(LinkerFlavor::from_str) {
Some(lf) => *slote = Some(lf),
_ => return false,
}
true
}
fn parse_optimization_fuel(slot: &mut Option<(String, u64)>, v: Option<&str>) -> bool {
match v {
None => false,
Some(s) => {
let parts = s.split('=').collect::<Vec<_>>();
if parts.len() != 2 { return false; }
let crate_name = parts[0].to_string();
let fuel = parts[1].parse::<u64>();
if fuel.is_err() { return false; }
*slot = Some((crate_name, fuel.unwrap()));
true
}
}
}
fn parse_unpretty(slot: &mut Option<String>, v: Option<&str>) -> bool {
match v {
None => false,
Some(s) if s.split('=').count() <= 2 => {
*slot = Some(s.to_string());
true
}
_ => false,
}
}
fn parse_lto(slot: &mut Lto, v: Option<&str>) -> bool {
*slot = match v {
None => Lto::Yes,
Some("thin") => Lto::Thin,
Some("fat") => Lto::Fat,
Some(_) => return false,
};
true
}
2018-02-04 16:52:26 +00:00
2018-03-15 03:30:06 +00:00
fn parse_edition(slot: &mut Edition, v: Option<&str>) -> bool {
2018-02-04 16:52:26 +00:00
match v {
Some(s) => {
2018-03-15 03:30:06 +00:00
let edition = s.parse();
if let Ok(parsed) = edition {
*slot = parsed;
true
} else {
false
}
}
_ => false,
2018-02-04 16:52:26 +00:00
}
}
}
) }
options! {CodegenOptions, CodegenSetter, basic_codegen_options,
build_codegen_options, "C", "codegen",
CG_OPTIONS, cg_type_desc, cgsetters,
ar: Option<String> = (None, parse_opt_string, [UNTRACKED],
"this option is deprecated and does nothing"),
linker: Option<PathBuf> = (None, parse_opt_pathbuf, [UNTRACKED],
"system linker to link outputs with"),
link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
"a single extra argument to append to the linker invocation (can be used several times)"),
link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
"extra arguments to append to the linker invocation (space separated)"),
link_dead_code: bool = (false, parse_bool, [UNTRACKED],
2016-02-15 16:44:06 +00:00
"don't let linker strip dead code (turning it on can be used for code coverage)"),
lto: Lto = (Lto::No, parse_lto, [TRACKED],
2014-09-21 04:36:17 +00:00
"perform LLVM link-time optimizations"),
target_cpu: Option<String> = (None, parse_opt_string, [TRACKED],
"select target processor (rustc --print target-cpus for details)"),
target_feature: String = ("".to_string(), parse_string, [TRACKED],
"target specific attributes (rustc --print target-features for details)"),
passes: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"a list of extra LLVM passes to run (space separated)"),
llvm_args: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"a list of arguments to pass to llvm (space separated)"),
save_temps: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
"`-C save-temps` might not produce all requested temporary products \
when incremental compilation is enabled.")],
"save all temporary output files during compilation"),
rpath: bool = (false, parse_bool, [UNTRACKED],
"set rpath values in libs/exes"),
overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
"use overflow checks for integer arithmetic"),
no_prepopulate_passes: bool = (false, parse_bool, [TRACKED],
"don't pre-populate the pass manager with a list of passes"),
no_vectorize_loops: bool = (false, parse_bool, [TRACKED],
"don't run the loop vectorization optimization passes"),
no_vectorize_slp: bool = (false, parse_bool, [TRACKED],
"don't run LLVM's SLP vectorization pass"),
soft_float: bool = (false, parse_bool, [TRACKED],
"use soft float ABI (*eabihf targets only)"),
prefer_dynamic: bool = (false, parse_bool, [TRACKED],
"prefer dynamic linking to static linking"),
no_integrated_as: bool = (false, parse_bool, [TRACKED],
"use an external assembler rather than LLVM's integrated one"),
no_redzone: Option<bool> = (None, parse_opt_bool, [TRACKED],
"disable the use of the redzone"),
relocation_model: Option<String> = (None, parse_opt_string, [TRACKED],
"choose the relocation model to use (rustc --print relocation-models for details)"),
code_model: Option<String> = (None, parse_opt_string, [TRACKED],
"choose the code model to use (rustc --print code-models for details)"),
metadata: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"metadata to mangle symbol names with"),
extra_filename: String = ("".to_string(), parse_string, [UNTRACKED],
"extra data to put in each output filename"),
2017-09-25 19:26:25 +00:00
codegen_units: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
"divide crate into N units to optimize in parallel"),
remark: Passes = (SomePasses(Vec::new()), parse_passes, [UNTRACKED],
"print remarks for these optimization passes (space separated, or \"all\")"),
no_stack_check: bool = (false, parse_bool, [UNTRACKED],
"the --no-stack-check flag is deprecated and does nothing"),
debuginfo: Option<usize> = (None, parse_opt_uint, [TRACKED],
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
"debug info emission level, 0 = no debug info, 1 = line tables only, \
2 = full debug info with variable and type information"),
opt_level: Option<String> = (None, parse_opt_string, [TRACKED],
"optimize with possible levels 0-3, s, or z"),
debug_assertions: Option<bool> = (None, parse_opt_bool, [TRACKED],
"explicitly enable the cfg(debug_assertions) directive"),
inline_threshold: Option<usize> = (None, parse_opt_uint, [TRACKED],
"set the threshold for inlining a function (default: 225)"),
panic: Option<PanicStrategy> = (None, parse_panic_strategy,
[TRACKED], "panic strategy to compile crate with"),
incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
"enable incremental compilation"),
}
options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
build_debugging_options, "Z", "debugging",
DB_OPTIONS, db_type_desc, dbsetters,
codegen_backend: Option<String> = (None, parse_opt_string, [TRACKED],
"the backend to use"),
verbose: bool = (false, parse_bool, [UNTRACKED],
"in general, enable more debug printouts"),
span_free_formats: bool = (false, parse_bool, [UNTRACKED],
"when debug-printing compiler state, do not include spans"), // o/w tests have closure@path
identify_regions: bool = (false, parse_bool, [UNTRACKED],
"make unnamed regions display as '# (where # is some non-ident unique id)"),
emit_end_regions: bool = (false, parse_bool, [UNTRACKED],
"emit EndRegion as part of MIR; enable transforms that solely process EndRegion"),
borrowck: Option<String> = (None, parse_opt_string, [UNTRACKED],
"select which borrowck is used (`ast`, `mir`, or `compare`)"),
two_phase_borrows: bool = (false, parse_bool, [UNTRACKED],
"use two-phase reserved/active distinction for `&mut` borrows in MIR borrowck"),
two_phase_beyond_autoref: bool = (false, parse_bool, [UNTRACKED],
"when using two-phase-borrows, allow two phases even for non-autoref `&mut` borrows"),
time_passes: bool = (false, parse_bool, [UNTRACKED],
"measure time of each rustc pass"),
count_llvm_insns: bool = (false, parse_bool,
[UNTRACKED_WITH_WARNING(true,
"The output generated by `-Z count_llvm_insns` might not be reliable \
when used with incremental compilation")],
"count where LLVM instrs originate"),
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
"The output of `-Z time-llvm-passes` will only reflect timings of \
re-translated modules when used with incremental compilation" )],
"measure time of each LLVM pass"),
input_stats: bool = (false, parse_bool, [UNTRACKED],
"gather statistics about the input"),
trans_stats: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
"The output of `-Z trans-stats` might not be accurate when incremental \
compilation is enabled")],
"gather trans statistics"),
asm_comments: bool = (false, parse_bool, [TRACKED],
"generate comments into the assembly (may change behavior)"),
no_verify: bool = (false, parse_bool, [TRACKED],
"skip LLVM verification"),
borrowck_stats: bool = (false, parse_bool, [UNTRACKED],
"gather borrowck statistics"),
no_landing_pads: bool = (false, parse_bool, [TRACKED],
"omit landing pads for unwinding"),
fewer_names: bool = (false, parse_bool, [TRACKED],
"reduce memory use by retaining fewer names within compilation artifacts (LLVM-IR)"),
meta_stats: bool = (false, parse_bool, [UNTRACKED],
"gather metadata statistics"),
print_link_args: bool = (false, parse_bool, [UNTRACKED],
"print the arguments passed to the linker"),
print_llvm_passes: bool = (false, parse_bool, [UNTRACKED],
"prints the llvm optimization passes being run"),
ast_json: bool = (false, parse_bool, [UNTRACKED],
"print the AST as JSON and halt"),
2017-12-03 13:16:19 +00:00
query_threads: Option<usize> = (None, parse_opt_uint, [UNTRACKED],
"execute queries on a thread pool with N threads"),
ast_json_noexpand: bool = (false, parse_bool, [UNTRACKED],
"print the pre-expansion AST as JSON and halt"),
ls: bool = (false, parse_bool, [UNTRACKED],
"list the symbols defined by a library crate"),
save_analysis: bool = (false, parse_bool, [UNTRACKED],
2016-08-30 04:40:44 +00:00
"write syntax and type analysis (in JSON format) information, in \
addition to normal output"),
flowgraph_print_loans: bool = (false, parse_bool, [UNTRACKED],
"include loan analysis data in -Z unpretty flowgraph output"),
flowgraph_print_moves: bool = (false, parse_bool, [UNTRACKED],
"include move analysis data in -Z unpretty flowgraph output"),
flowgraph_print_assigns: bool = (false, parse_bool, [UNTRACKED],
"include assignment analysis data in -Z unpretty flowgraph output"),
flowgraph_print_all: bool = (false, parse_bool, [UNTRACKED],
"include all dataflow analysis data in -Z unpretty flowgraph output"),
print_region_graph: bool = (false, parse_bool, [UNTRACKED],
"prints region inference graph. \
Use with RUST_REGION_GRAPH=help for more info"),
parse_only: bool = (false, parse_bool, [UNTRACKED],
"parse only; do not compile, assemble, or link"),
no_trans: bool = (false, parse_bool, [TRACKED],
"run all passes except translation; no output"),
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],
"treat all errors that occur as bugs"),
2017-11-20 18:03:20 +00:00
external_macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
"show macro backtraces even for non-local macros"),
2018-01-23 19:34:57 +00:00
teach: bool = (false, parse_bool, [TRACKED],
"show extended diagnostic help"),
continue_parse_after_error: bool = (false, parse_bool, [TRACKED],
"attempt to recover from parse errors (experimental)"),
incremental: Option<String> = (None, parse_opt_string, [UNTRACKED],
"enable incremental compilation (experimental)"),
incremental_queries: bool = (true, parse_bool, [UNTRACKED],
"enable incremental compilation support for queries (experimental)"),
incremental_info: bool = (false, parse_bool, [UNTRACKED],
2016-08-06 00:12:02 +00:00
"print high-level information about incremental reuse (or the lack thereof)"),
incremental_dump_hash: bool = (false, parse_bool, [UNTRACKED],
"dump hash information in textual format to stdout"),
incremental_verify_ich: bool = (false, parse_bool, [UNTRACKED],
"verify incr. comp. hashes of green query instances"),
incremental_ignore_spans: bool = (false, parse_bool, [UNTRACKED],
"ignore spans during ICH computation -- used for testing"),
dump_dep_graph: bool = (false, parse_bool, [UNTRACKED],
"dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"),
query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
"enable queries of the dependency graph for regression testing"),
profile_queries: bool = (false, parse_bool, [UNTRACKED],
"trace and profile the queries of the incremental compilation framework"),
profile_queries_and_keys: bool = (false, parse_bool, [UNTRACKED],
"trace and profile the queries and keys of the incremental compilation framework"),
no_analysis: bool = (false, parse_bool, [UNTRACKED],
"parse and expand the source, but run no analysis"),
extra_plugins: Vec<String> = (Vec::new(), parse_list, [TRACKED],
"load extra plugins"),
unstable_options: bool = (false, parse_bool, [UNTRACKED],
"adds unstable command line options to rustc interface"),
force_overflow_checks: Option<bool> = (None, parse_opt_bool, [TRACKED],
"force overflow checks on or off"),
trace_macros: bool = (false, parse_bool, [UNTRACKED],
"for every macro invocation, print its name and arguments"),
debug_macros: bool = (false, parse_bool, [TRACKED],
"emit line numbers debug info inside macros"),
enable_nonzeroing_move_hints: bool = (false, parse_bool, [TRACKED],
"force nonzeroing move optimization on"),
keep_hygiene_data: bool = (false, parse_bool, [UNTRACKED],
2016-07-16 19:11:28 +00:00
"don't clear the hygiene data after analysis"),
keep_ast: bool = (false, parse_bool, [UNTRACKED],
2015-12-25 16:17:45 +00:00
"keep the AST after lowering it to HIR"),
show_span: Option<String> = (None, parse_opt_string, [TRACKED],
2016-01-12 04:44:24 +00:00
"show spans for compiler debugging (expr|pat|ty)"),
print_type_sizes: bool = (false, parse_bool, [UNTRACKED],
"print layout information for each type encountered"),
print_trans_items: Option<String> = (None, parse_opt_string, [UNTRACKED],
"print the result of the translation item collection pass"),
mir_opt_level: usize = (1, parse_uint, [TRACKED],
"set the MIR optimization level (0-3, default: 1)"),
2017-10-03 23:49:45 +00:00
mutable_noalias: bool = (false, parse_bool, [UNTRACKED],
"emit noalias metadata for mutable references"),
arg_align_attributes: bool = (false, parse_bool, [UNTRACKED],
"emit align metadata for reference arguments"),
dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
"dump MIR state at various points in translation"),
2018-01-14 20:02:07 +00:00
dump_mir_dir: String = (String::from("mir_dump"), parse_string, [UNTRACKED],
"the directory the MIR is dumped into"),
dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
"in addition to `.mir` files, create graphviz `.dot` files"),
dump_mir_exclude_pass_number: bool = (false, parse_bool, [UNTRACKED],
"if set, exclude the pass number when dumping MIR (used in tests)"),
mir_emit_validate: usize = (0, parse_uint, [TRACKED],
"emit Validate MIR statements, interpreted e.g. by miri (0: do not emit; 1: if function \
contains unsafe block, only validate arguments; 2: always emit full validation)"),
perf_stats: bool = (false, parse_bool, [UNTRACKED],
"print some performance-related statistics"),
hir_stats: bool = (false, parse_bool, [UNTRACKED],
"print some statistics about AST and HIR"),
Adds `-Z mir-stats`, which is similar to `-Z hir-stats`. Some notes: * This code attempts to present the breakdown of each variant for every enum in the MIR. This is meant to guide decisions about how to revise representations e.g. when to box payloads for rare variants to shrink the size of the enum overall. * I left out the "Total:" line that hir-stats presents, because this implementation uses the MIR Visitor infrastructure, and the memory usage of structures directly embedded in other structures (e.g. the `func: Operand` in a `TerminatorKind:Call`) is not distinguished from similar structures allocated in a `Vec` (e.g. the `args: Vec<Operand>` in a `TerminatorKind::Call`). This means that a naive summation of all the accumulated sizes is misleading, because it will double-count the contribution of the `Operand` of the `func` as well as the size of the whole `TerminatorKind`. * I did consider abandoning the MIR Visitor and instead hand-coding a traversal that distinguished embedded storage from indirect storage. But such code would be fragile; better to just require people to take care when interpreting the presented results. * This traverses the `mir.promoted` rvalues to capture stats for MIR stored there, even though the MIR visitor super_mir method does not do so. (I did not observe any new mir being traversed when compiling the rustc crate, however.) * It might be nice to try to unify this code with hir-stats. Then again, the reporting portion is the only common code (I think), and it is small compared to the visitors in hir-stats and mir-stats.
2016-11-30 17:14:17 +00:00
mir_stats: bool = (false, parse_bool, [UNTRACKED],
"print some statistics about MIR"),
always_encode_mir: bool = (false, parse_bool, [TRACKED],
"encode MIR of all functions into the crate metadata"),
miri: bool = (false, parse_bool, [TRACKED],
"check the miri const evaluator against the old ctfe"),
rustbuild: Fix LC_ID_DYLIB directives on OSX Currently libraries installed by rustbuild on OSX have an incorrect `LC_ID_DYLIB` directive located in the dynamic libraries that are installed. The directive we expect looks like: @rpath/libstd.dylib Which means that if you want to find that dynamic library you should look at the dylib's other `@rpath` directives. Typically our `@rpath` directives look like `@loader_path/../lib` for the compiler as that's where the installed libraries will be located. Currently, though, rustbuild produces dylibs with the directive that looks like: /Users/rustbuild/src/rust-buildbot/slave/nightly-dist-rustc-mac/build/build/x86_64-apple-darwin/stage1-std/x86_64-apple-darwin/release/deps/libstd-713ad88203512705.dylib In other words, the build directory is encoded erroneously. The compiler already [knows how] to change this directive, but it only passes that argument when `-C rpath` is also passed. The rustbuild system, however, explicitly [does not pass] this option explicitly and instead bakes its own. This logic then also erroneously didn't pass `-Wl,-install_name` like the compiler. [knows how]: https://github.com/rust-lang/rust/blob/4a008cccaabc8b3fe65ccf5868b9d16319c9ac58/src/librustc_trans/back/linker.rs#L210-L214 [does not pass]: https://github.com/rust-lang/rust/blob/4a008cccaabc8b3fe65ccf5868b9d16319c9ac58/src/bootstrap/bin/rustc.rs#L133-L158 To fix this regression this patch introduces a new `-Z` flag, `-Z osx-rpath-install-name` which basically just forces the compiler to take the previous `-install_name` branch when creating a dynamic library. Hopefully we can sort out a better rpath story in the future, but for now this "hack" should suffice in getting our nightly builds back to the same state as before. Closes #38430
2016-12-17 22:11:02 +00:00
osx_rpath_install_name: bool = (false, parse_bool, [TRACKED],
"pass `-install_name @rpath/...` to the macOS linker"),
sanitizer: Option<Sanitizer> = (None, parse_sanitizer, [TRACKED],
2016-12-30 04:28:11 +00:00
"Use a sanitizer"),
-Z linker-flavor This patch adds a `-Z linker-flavor` flag to rustc which can be used to invoke the linker using a different interface. For example, by default rustc assumes that all the Linux targets will be linked using GCC. This makes it impossible to use LLD as a linker using just `-C linker=ld.lld` because that will invoke LLD with invalid command line arguments. (e.g. rustc will pass -Wl,--gc-sections to LLD but LLD doesn't understand that; --gc-sections would be the right argument) With this patch one can pass `-Z linker-flavor=ld` to rustc to invoke the linker using a LD-like interface. This way, `rustc -C linker=ld.lld -Z linker-flavor=ld` will invoke LLD with the right arguments. `-Z linker-flavor` accepts 4 different arguments: `em` (emcc), `ld`, `gcc`, `msvc` (link.exe). `em`, `gnu` and `msvc` cover all the existing linker interfaces. `ld` is a new flavor for interfacing GNU's ld and LLD. This patch also changes target specifications. `linker-flavor` is now a mandatory field that specifies the *default* linker flavor that the target will use. This change also makes the linker interface *explicit*; before, it used to be derived from other fields like linker-is-gnu, is-like-msvc, is-like-emscripten, etc. Another change to target specifications is that the fields `pre-link-args`, `post-link-args` and `late-link-args` now expect a map from flavor to linker arguments. ``` diff - "pre-link-args": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"], + "pre-link-args": { + "gcc": ["-Wl,--as-needed", "-Wl,-z,-noexecstack"], + "ld": ["--as-needed", "-z,-noexecstack"], + }, ``` [breaking-change] for users of custom targets specifications
2017-02-21 19:47:15 +00:00
linker_flavor: Option<LinkerFlavor> = (None, parse_linker_flavor, [UNTRACKED],
"Linker flavor"),
fuel: Option<(String, u64)> = (None, parse_optimization_fuel, [TRACKED],
"set the optimization fuel quota for a crate"),
print_fuel: Option<String> = (None, parse_opt_string, [TRACKED],
"make Rustc print the total optimization fuel used by a crate"),
force_unstable_if_unmarked: bool = (false, parse_bool, [TRACKED],
"force all crates to be `rustc_private` unstable"),
pre_link_arg: Vec<String> = (vec![], parse_string_push, [UNTRACKED],
"a single extra argument to prepend the linker invocation (can be used several times)"),
pre_link_args: Option<Vec<String>> = (None, parse_opt_list, [UNTRACKED],
"extra arguments to prepend to the linker invocation (space separated)"),
profile: bool = (false, parse_bool, [TRACKED],
"insert profiling code"),
pgo_gen: Option<String> = (None, parse_opt_string, [TRACKED],
"Generate PGO profile data, to a given file, or to the default \
location if it's empty."),
pgo_use: String = (String::new(), parse_string, [TRACKED],
"Use PGO profile data from the given profile file."),
disable_instrumentation_preinliner: bool =
(false, parse_bool, [TRACKED], "Disable the instrumentation pre-inliner, \
useful for profiling / PGO."),
relro_level: Option<RelroLevel> = (None, parse_relro_level, [TRACKED],
"choose which RELRO level to use"),
nll: bool = (false, parse_bool, [UNTRACKED],
"run the non-lexical lifetimes MIR pass"),
disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED],
"disable user provided type assertion in NLL"),
trans_time_graph: bool = (false, parse_bool, [UNTRACKED],
"generate a graphical HTML report of time spent in trans and LLVM"),
thinlto: Option<bool> = (None, parse_opt_bool, [TRACKED],
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 15:14:38 +00:00
"enable ThinLTO when possible"),
rustc: Don't inline in CGUs at -O0 This commit tweaks the behavior of inlining functions into multiple codegen units when rustc is compiling in debug mode. Today rustc will unconditionally treat `#[inline]` functions by translating them into all codegen units that they're needed within, marking the linkage as `internal`. This commit changes the behavior so that in debug mode (compiling at `-O0`) rustc will instead only translate `#[inline]` functions into *one* codegen unit, forcing all other codegen units to reference this one copy. The goal here is to improve debug compile times by reducing the amount of translation that happens on behalf of multiple codegen units. It was discovered in #44941 that increasing the number of codegen units had the adverse side effect of increasing the overal work done by the compiler, and the suspicion here was that the compiler was inlining, translating, and codegen'ing more functions with more codegen units (for example `String` would be basically inlined into all codegen units if used). The strategy in this commit should reduce the cost of `#[inline]` functions to being equivalent to one codegen unit, which is only translating and codegen'ing inline functions once. Collected [data] shows that this does indeed improve the situation from [before] as the overall cpu-clock time increases at a much slower rate and when pinned to one core rustc does not consume significantly more wall clock time than with one codegen unit. One caveat of this commit is that the symbol names for inlined functions that are only translated once needed some slight tweaking. These inline functions could be translated into multiple crates and we need to make sure the symbols don't collideA so the crate name/disambiguator is mixed in to the symbol name hash in these situations. [data]: https://github.com/rust-lang/rust/issues/44941#issuecomment-334880911 [before]: https://github.com/rust-lang/rust/issues/44941#issuecomment-334583384
2017-10-06 21:59:33 +00:00
inline_in_all_cgus: Option<bool> = (None, parse_opt_bool, [TRACKED],
"control whether #[inline] functions are in all cgus"),
tls_model: Option<String> = (None, parse_opt_string, [TRACKED],
"choose the TLS model to use (rustc --print tls-models for details)"),
saturating_float_casts: bool = (false, parse_bool, [TRACKED],
"make float->int casts UB-free: numbers outside the integer type's range are clipped to \
the max/min integer respectively, and NaN is mapped to 0"),
lower_128bit_ops: Option<bool> = (None, parse_opt_bool, [TRACKED],
"rewrite operators on i128 and u128 into lang item calls (typically provided \
by compiler-builtins) so translation doesn't need to support them,
overriding the default for the current target"),
human_readable_cgu_names: bool = (false, parse_bool, [TRACKED],
"generate human-readable, predictable names for codegen units"),
dep_info_omit_d_target: bool = (false, parse_bool, [TRACKED],
"in dep-info output, omit targets for tracking dependencies of the dep-info files \
themselves"),
2018-01-19 07:34:14 +00:00
approximate_suggestions: bool = (false, parse_bool, [UNTRACKED],
"include machine-applicability of suggestions in JSON output"),
unpretty: Option<String> = (None, parse_unpretty, [UNTRACKED],
"Present the input source, unstable (and less-pretty) variants;
valid types are any of the types for `--pretty`, as well as:
`flowgraph=<nodeid>` (graphviz formatted flowgraph for node),
`everybody_loops` (all function bodies replaced with `loop {}`),
`hir` (the HIR), `hir,identified`, or
`hir,typed` (HIR with types for each node)."),
2018-03-15 03:30:06 +00:00
edition: Edition = (Edition::Edition2015, parse_edition, [TRACKED],
"The edition to build Rust with. Newer editions may include features
that require breaking changes. The default edition is 2015 (the first
edition). Crates compiled with different editions can be linked together."),
run_dsymutil: Option<bool> = (None, parse_opt_bool, [TRACKED],
"run `dsymutil` and delete intermediate object files"),
ui_testing: bool = (false, parse_bool, [UNTRACKED],
"format compiler diagnostics in a way that's better suitable for UI testing"),
embed_bitcode: bool = (false, parse_bool, [TRACKED],
"embed LLVM bitcode in object files"),
strip_debuginfo_if_disabled: Option<bool> = (None, parse_opt_bool, [TRACKED],
"tell the linker to strip debuginfo when building without debuginfo enabled."),
share_generics: Option<bool> = (None, parse_opt_bool, [TRACKED],
"make the current crate share its generic instantiations"),
}
pub fn default_lib_output() -> CrateType {
CrateTypeRlib
}
pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
let end = &sess.target.target.target_endian;
let arch = &sess.target.target.arch;
let wordsz = &sess.target.target.target_pointer_width;
let os = &sess.target.target.target_os;
let env = &sess.target.target.target_env;
let vendor = &sess.target.target.target_vendor;
let min_atomic_width = sess.target.target.min_atomic_width();
let max_atomic_width = sess.target.target.max_atomic_width();
2016-11-15 08:54:27 +00:00
let mut ret = HashSet::new();
// Target bindings.
ret.insert((Symbol::intern("target_os"), Some(Symbol::intern(os))));
2016-12-23 05:29:33 +00:00
if let Some(ref fam) = sess.target.target.options.target_family {
ret.insert((Symbol::intern("target_family"), Some(Symbol::intern(fam))));
2016-12-23 05:20:47 +00:00
if fam == "windows" || fam == "unix" {
2016-12-23 05:29:33 +00:00
ret.insert((Symbol::intern(fam), None));
2016-12-23 05:20:47 +00:00
}
}
ret.insert((Symbol::intern("target_arch"), Some(Symbol::intern(arch))));
ret.insert((Symbol::intern("target_endian"), Some(Symbol::intern(end))));
2018-03-06 05:29:03 +00:00
ret.insert((
Symbol::intern("target_pointer_width"),
Some(Symbol::intern(wordsz)),
));
ret.insert((Symbol::intern("target_env"), Some(Symbol::intern(env))));
2018-03-06 05:29:03 +00:00
ret.insert((
Symbol::intern("target_vendor"),
Some(Symbol::intern(vendor)),
));
if sess.target.target.options.has_elf_tls {
ret.insert((Symbol::intern("target_thread_local"), None));
}
for &i in &[8, 16, 32, 64, 128] {
if i >= min_atomic_width && i <= max_atomic_width {
let s = i.to_string();
2018-03-06 05:29:03 +00:00
ret.insert((
Symbol::intern("target_has_atomic"),
Some(Symbol::intern(&s)),
));
if &s == wordsz {
2018-03-06 05:29:03 +00:00
ret.insert((
Symbol::intern("target_has_atomic"),
Some(Symbol::intern("ptr")),
));
}
}
}
if sess.opts.debug_assertions {
ret.insert((Symbol::intern("debug_assertions"), None));
}
if sess.opts.crate_types.contains(&CrateTypeProcMacro) {
ret.insert((Symbol::intern("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-23 00:07:11 +00:00
}
return ret;
}
2018-03-06 05:29:03 +00:00
pub fn build_configuration(sess: &Session, mut user_cfg: ast::CrateConfig) -> ast::CrateConfig {
// Combine the configuration requested by the session (command line) with
// some default and generated configuration items
let default_cfg = default_configuration(sess);
// If the user wants a test runner, then add the test cfg
if sess.opts.test {
user_cfg.insert((Symbol::intern("test"), None));
}
2016-11-15 08:54:27 +00:00
user_cfg.extend(default_cfg.iter().cloned());
user_cfg
}
pub fn build_target_config(opts: &Options, sp: &Handler) -> Config {
let target = match Target::search(&opts.target_triple) {
Ok(t) => t,
Err(e) => {
sp.struct_fatal(&format!("Error loading target specification: {}", e))
.help("Use `--print target-list` for a list of built-in targets")
.emit();
FatalError.raise();
}
};
let (isize_ty, usize_ty) = match &target.target_pointer_width[..] {
"16" => (ast::IntTy::I16, ast::UintTy::U16),
"32" => (ast::IntTy::I32, ast::UintTy::U32),
"64" => (ast::IntTy::I64, ast::UintTy::U64),
2018-03-06 05:29:03 +00:00
w => sp.fatal(&format!(
"target specification was invalid: \
unrecognized target-pointer-width {}",
w
)).raise(),
};
Config {
target,
isize_ty,
usize_ty,
}
}
2015-01-28 13:34:18 +00:00
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum OptionStability {
Stable,
Unstable,
}
pub struct RustcOptGroup {
2018-02-23 17:53:00 +00:00
pub apply: Box<dyn Fn(&mut getopts::Options) -> &mut getopts::Options>,
pub name: &'static str,
pub stability: OptionStability,
}
impl RustcOptGroup {
pub fn is_stable(&self) -> bool {
self.stability == OptionStability::Stable
}
pub fn stable<F>(name: &'static str, f: F) -> RustcOptGroup
2018-03-06 05:29:03 +00:00
where
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
{
RustcOptGroup {
name,
apply: Box::new(f),
stability: OptionStability::Stable,
}
}
pub fn unstable<F>(name: &'static str, f: F) -> RustcOptGroup
2018-03-06 05:29:03 +00:00
where
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
{
RustcOptGroup {
name,
apply: Box::new(f),
stability: OptionStability::Unstable,
}
}
}
// 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
// *unstable* options, i.e. options that are only enabled when the
// user also passes the `-Z unstable-options` debugging flag.
mod opt {
// The `fn opt_u` etc below are written so that we can use them
// in the future; do not warn about them not being used right now.
#![allow(dead_code)]
use getopts;
use super::RustcOptGroup;
pub type R = RustcOptGroup;
pub type S = &'static str;
fn stable<F>(name: S, f: F) -> R
2018-03-06 05:29:03 +00:00
where
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
{
RustcOptGroup::stable(name, f)
}
fn unstable<F>(name: S, f: F) -> R
2018-03-06 05:29:03 +00:00
where
F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static,
{
RustcOptGroup::unstable(name, f)
}
fn longer(a: S, b: S) -> S {
if a.len() > b.len() {
a
} else {
b
}
}
pub fn opt_s(a: S, b: S, c: S, d: S) -> R {
stable(longer(a, b), move |opts| opts.optopt(a, b, c, d))
}
pub fn multi_s(a: S, b: S, c: S, d: S) -> R {
stable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
}
pub fn flag_s(a: S, b: S, c: S) -> R {
stable(longer(a, b), move |opts| opts.optflag(a, b, c))
}
pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R {
stable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d))
}
pub fn flagmulti_s(a: S, b: S, c: S) -> R {
stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
}
pub fn opt(a: S, b: S, c: S, d: S) -> R {
unstable(longer(a, b), move |opts| opts.optopt(a, b, c, d))
}
pub fn multi(a: S, b: S, c: S, d: S) -> R {
unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d))
}
pub fn flag(a: S, b: S, c: S) -> R {
unstable(longer(a, b), move |opts| opts.optflag(a, b, c))
}
pub fn flagopt(a: S, b: S, c: S, d: S) -> R {
unstable(longer(a, b), move |opts| opts.optflagopt(a, b, c, d))
}
pub fn flagmulti(a: S, b: S, c: S) -> R {
unstable(longer(a, b), move |opts| opts.optflagmulti(a, b, c))
}
}
/// 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> {
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
vec![
opt::flag_s("h", "help", "Display this message"),
opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"),
2018-03-06 05:29:03 +00:00
opt::multi_s(
"L",
"",
"Add a directory to the library search path. The
optional KIND can be one of dependency, crate, native,
2018-03-06 05:29:03 +00:00
framework or all (the default).",
"[KIND=]PATH",
),
opt::multi_s(
"l",
"",
"Link the generated crate(s) to the specified native
library NAME. The optional KIND can be one of
static, dylib, or framework. If omitted, dylib is
2018-03-06 05:29:03 +00:00
assumed.",
"[KIND=]NAME",
),
opt::multi_s(
"",
"crate-type",
"Comma separated list of types of crates
for the compiler to emit",
2018-03-06 05:29:03 +00:00
"[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]",
),
opt::opt_s(
"",
"crate-name",
"Specify the name of the crate being built",
"NAME",
),
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",
"Comma separated list of compiler information to \
print on stdout",
"[crate-name|file-names|sysroot|cfg|target-list|\
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"),
opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"),
opt::opt_s("o", "", "Write output to <filename>", "FILENAME"),
2018-03-06 05:29:03 +00: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",
),
opt::flag_s("", "test", "Build a test harness"),
2018-03-06 05:29:03 +00:00
opt::opt_s(
"",
"target",
"Target triple for which the code is compiled",
"TARGET",
),
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 05:29:03 +00:00
opt::multi_s(
"",
"cap-lints",
"Set the most restrictive lint level. \
More restrictive lints are capped at this \
level",
"LEVEL",
),
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"),
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00: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();
opts.extend(vec![
2018-03-06 05:29:03 +00:00
opt::multi_s(
"",
"extern",
"Specify where an external rust library is located",
"NAME=PATH",
),
opt::opt_s("", "sysroot", "Override the system root", "PATH"),
opt::multi("Z", "", "Set internal debugging options", "FLAG"),
2018-03-06 05:29:03 +00:00
opt::opt_s(
"",
"error-format",
"How errors and other messages are produced",
"human|json|short",
),
opt::opt_s(
"",
"color",
"Configure coloring of output:
auto = colorize, if output goes to a tty (default);
always = always colorize output;
2018-03-06 05:29:03 +00:00
never = never colorize output",
"auto|always|never",
),
opt::opt(
"",
"pretty",
"Pretty-print the input instead of compiling;
valid types are: `normal` (un-annotated source),
`expanded` (crates expanded), or
`expanded,identified` (fully parenthesized, AST nodes with IDs).",
2018-03-06 05:29:03 +00:00
"TYPE",
),
opt::multi_s(
"",
"remap-path-prefix",
"Remap source names in all output (compiler messages and output files)",
2018-03-06 05:29:03 +00:00
"FROM=TO",
),
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
]);
opts
}
// Convert strings provided as --cfg [cfgspec] into a crate_cfg
2018-03-06 05:29:03 +00:00
pub fn parse_cfgspecs(cfgspecs: Vec<String>) -> ast::CrateConfig {
cfgspecs
.into_iter()
.map(|s| {
let sess = parse::ParseSess::new(FilePathMapping::empty());
let mut parser =
parse::new_parser_from_source_str(&sess, FileName::CfgSpec, s.to_string());
let meta_item = panictry!(parser.parse_meta_item());
if parser.token != token::Eof {
early_error(
ErrorOutputType::default(),
&format!("invalid --cfg argument: {}", s),
)
} else if meta_item.is_meta_item_list() {
let msg = format!(
"invalid predicate in --cfg command line argument: `{}`",
meta_item.ident
2018-03-06 05:29:03 +00:00
);
early_error(ErrorOutputType::default(), &msg)
}
(meta_item.ident.name, meta_item.value_str())
2018-03-06 05:29:03 +00:00
})
.collect::<ast::CrateConfig>()
}
2018-03-06 05:29:03 +00:00
pub fn build_session_options_and_crate_config(
matches: &getopts::Matches,
) -> (Options, ast::CrateConfig) {
let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
2018-03-06 05:29:03 +00:00
Some("auto") => ColorConfig::Auto,
Some("always") => ColorConfig::Always,
2018-03-06 05:29:03 +00:00
Some("never") => ColorConfig::Never,
None => ColorConfig::Auto,
2018-03-06 05:29:03 +00:00
Some(arg) => early_error(
ErrorOutputType::default(),
&format!(
"argument for --color must be auto, \
always or never (instead was `{}`)",
arg
),
),
};
// We need the opts_present check because the driver will send us Matches
// with only stable options if no unstable options are used. Since error-format
// is unstable, it will not be present. We have to use opts_present not
// opt_present because the latter will panic.
let error_format = if matches.opts_present(&["error-format".to_owned()]) {
match matches.opt_str("error-format").as_ref().map(|s| &s[..]) {
2017-09-16 17:24:08 +00:00
Some("human") => ErrorOutputType::HumanReadable(color),
2018-03-06 05:29:03 +00:00
Some("json") => ErrorOutputType::Json(false),
2017-11-03 12:38:26 +00:00
Some("pretty-json") => ErrorOutputType::Json(true),
2017-11-15 15:13:15 +00:00
Some("short") => {
if nightly_options::is_unstable_enabled(matches) {
ErrorOutputType::Short(color)
} else {
2018-03-06 05:29:03 +00:00
early_error(
ErrorOutputType::default(),
&format!(
"the `-Z unstable-options` flag must also be passed to \
enable the short error message option"
),
);
2017-11-15 15:13:15 +00:00
}
}
None => ErrorOutputType::HumanReadable(color),
2018-03-06 05:29:03 +00:00
Some(arg) => early_error(
ErrorOutputType::HumanReadable(color),
&format!(
"argument for --error-format must be `human`, `json` or \
`short` (instead was `{}`)",
arg
),
),
}
} else {
ErrorOutputType::HumanReadable(color)
};
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 mut lint_opts = vec![];
let mut describe_lints = false;
2015-01-31 17:20:46 +00:00
for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] {
for lint_name in matches.opt_strs(level.as_str()) {
if lint_name == "help" {
describe_lints = true;
} else {
2014-12-11 03:46:38 +00:00
lint_opts.push((lint_name.replace("-", "_"), level));
}
}
}
let lint_cap = matches.opt_str("cap-lints").map(|cap| {
2018-03-06 05:29:03 +00:00
lint::Level::from_str(&cap)
.unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{}`", cap)))
});
let mut debugging_opts = build_debugging_options(matches, error_format);
if !debugging_opts.unstable_options && error_format == ErrorOutputType::Json(true) {
2018-03-06 05:29:03 +00:00
early_error(
ErrorOutputType::Json(false),
"--error-format=pretty-json is unstable",
);
2017-11-03 12:38:26 +00:00
}
if debugging_opts.pgo_gen.is_some() && !debugging_opts.pgo_use.is_empty() {
early_error(
error_format,
"options `-Z pgo-gen` and `-Z pgo-use` are exclusive",
);
}
let mut output_types = BTreeMap::new();
if !debugging_opts.parse_only {
for list in matches.opt_strs("emit") {
for output_type in list.split(',') {
let mut parts = output_type.splitn(2, '=');
let shorthand = parts.next().unwrap();
let output_type = match OutputType::from_shorthand(shorthand) {
Some(output_type) => output_type,
2018-03-06 05:29:03 +00:00
None => early_error(
error_format,
&format!(
"unknown emission type: `{}` - expected one of: {}",
shorthand,
OutputType::shorthands_display(),
),
),
};
let path = parts.next().map(PathBuf::from);
output_types.insert(output_type, path);
}
}
};
if output_types.is_empty() {
output_types.insert(OutputType::Exe, None);
}
let mut cg = build_codegen_options(matches, error_format);
2017-09-25 19:26:25 +00:00
let mut codegen_units = cg.codegen_units;
let mut disable_thinlto = false;
// Issue #30063: if user requests llvm-related output to one
// particular path, disable codegen-units.
2018-03-06 05:29:03 +00:00
let incompatible: Vec<_> = output_types
.iter()
2017-09-25 19:26:25 +00:00
.map(|ot_path| ot_path.0)
2018-03-06 05:29:03 +00:00
.filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file())
2017-09-25 19:26:25 +00: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 05:29:03 +00:00
early_warn(
error_format,
&format!(
"--emit={} with -o incompatible with \
-C codegen-units=N for N > 1",
ot
),
);
2017-09-25 19:26:25 +00:00
}
early_warn(error_format, "resetting to default -C codegen-units=1");
codegen_units = Some(1);
disable_thinlto = true;
2017-09-25 19:26:25 +00:00
}
}
_ => {
codegen_units = Some(1);
disable_thinlto = true;
}
}
}
2017-12-03 13:16:19 +00:00
if debugging_opts.query_threads == Some(0) {
2018-03-06 05:29:03 +00:00
early_error(
error_format,
"Value for query threads must be a positive nonzero integer",
);
2017-12-03 13:16:19 +00:00
}
2017-09-25 19:26:25 +00:00
if codegen_units == Some(0) {
2018-03-06 05:29:03 +00:00
early_error(
error_format,
"Value for codegen units must be a positive nonzero integer",
);
}
let incremental = match (&debugging_opts.incremental, &cg.incremental) {
(&Some(ref path1), &Some(ref path2)) => {
if path1 != path2 {
2018-03-06 05:29:03 +00:00
early_error(
error_format,
&format!(
"conflicting paths for `-Z incremental` and \
`-C incremental` specified: {} versus {}",
path1, path2
),
);
} else {
Some(path1)
}
}
(&Some(ref path), &None) => Some(path),
(&None, &Some(ref path)) => Some(path),
(&None, &None) => None,
}.map(|m| PathBuf::from(m));
if cg.lto != Lto::No && incremental.is_some() {
2018-03-06 05:29:03 +00:00
early_error(
error_format,
"can't perform LTO when compiling incrementally",
);
}
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);
cg.target_feature = "".to_string();
}
if cg.relocation_model.as_ref().map_or(false, |s| s == "help") {
prints.push(PrintRequest::RelocationModels);
cg.relocation_model = None;
}
if cg.code_model.as_ref().map_or(false, |s| s == "help") {
prints.push(PrintRequest::CodeModels);
cg.code_model = None;
}
2018-03-06 05:29:03 +00:00
if debugging_opts
.tls_model
.as_ref()
.map_or(false, |s| s == "help")
{
prints.push(PrintRequest::TlsModels);
debugging_opts.tls_model = None;
}
let cg = cg;
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m));
let target_triple = if let Some(target) = matches.opt_str("target") {
if target.ends_with(".json") {
2018-03-24 19:14:59 +00:00
let path = Path::new(&target);
match TargetTriple::from_path(&path) {
Ok(triple) => triple,
Err(_) => {
early_error(error_format, &format!("target file {:?} does not exist", path))
}
}
} else {
TargetTriple::TargetTriple(target)
}
} else {
TargetTriple::from_triple(host_triple())
};
let opt_level = {
2014-09-21 04:08:00 +00:00
if matches.opt_present("O") {
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
if cg.opt_level.is_some() {
early_error(error_format, "-O and -C opt-level both provided");
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
}
OptLevel::Default
} else {
2018-03-06 05:29:03 +00:00
match (
cg.opt_level.as_ref().map(String::as_ref),
nightly_options::is_nightly_build(),
) {
(None, _) => OptLevel::No,
(Some("0"), _) => OptLevel::No,
(Some("1"), _) => OptLevel::Less,
(Some("2"), _) => OptLevel::Default,
(Some("3"), _) => OptLevel::Aggressive,
(Some("s"), true) => OptLevel::Size,
(Some("z"), true) => OptLevel::SizeMin,
(Some("s"), false) | (Some("z"), false) => {
2018-03-06 05:29:03 +00:00
early_error(
error_format,
&format!(
"the optimizations s or z are only \
accepted on the nightly compiler"
),
);
}
(Some(arg), _) => {
2018-03-06 05:29:03 +00:00
early_error(
error_format,
&format!(
"optimization level needs to be \
between 0-3 (instead was `{}`)",
arg
),
);
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
}
}
}
};
let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No);
let debuginfo = if matches.opt_present("g") {
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
if cg.debuginfo.is_some() {
early_error(error_format, "-g and -C debuginfo both provided");
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
}
FullDebugInfo
} else {
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
match cg.debuginfo {
None | Some(0) => NoDebugInfo,
Some(1) => LimitedDebugInfo,
Some(2) => FullDebugInfo,
Some(arg) => {
2018-03-06 05:29:03 +00:00
early_error(
error_format,
&format!(
"debug info level needs to be between \
0-2 (instead was `{}`)",
arg
),
);
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
}
}
};
let mut search_paths = SearchPaths::new();
2015-01-31 17:20:46 +00:00
for s in &matches.opt_strs("L") {
search_paths.add_path(&s[..], error_format);
}
2018-03-06 05:29:03 +00:00
let libs = matches
.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) {
(None, name) => (name, None),
(Some(name), "dylib") => (name, Some(cstore::NativeUnknown)),
(Some(name), "framework") => (name, Some(cstore::NativeFramework)),
(Some(name), "static") => (name, Some(cstore::NativeStatic)),
(Some(name), "static-nobundle") => (name, Some(cstore::NativeStaticNobundle)),
(_, s) => {
early_error(
error_format,
&format!(
"unknown library kind `{}`, expected \
one of dylib, framework, or static",
s
),
);
}
};
if kind == Some(cstore::NativeStaticNobundle) && !nightly_options::is_nightly_build() {
early_error(
error_format,
&format!(
"the library kind 'static-nobundle' is only \
accepted on the nightly compiler"
),
);
}
2018-03-06 05:29:03 +00:00
let mut name_parts = name.splitn(2, ':');
let name = name_parts.next().unwrap();
let new_name = name_parts.next();
(name.to_string(), new_name.map(|n| n.to_string()), kind)
})
.collect();
let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
let test = matches.opt_present("test");
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
2018-03-06 05:29:03 +00:00
prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
"crate-name" => PrintRequest::CrateName,
"file-names" => PrintRequest::FileNames,
"sysroot" => PrintRequest::Sysroot,
"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" => {
if nightly_options::is_unstable_enabled(matches) {
PrintRequest::TargetSpec
} else {
early_error(
error_format,
&format!(
"the `-Z unstable-options` flag must also be passed to \
enable the target-spec-json print option"
),
);
rustc: Start "stabilizing" some flags This commit shuffles around some CLI flags of the compiler to some more stable locations with some renamings. The changes made were: * The `-v` flag has been repurposes as the "verbose" flag. The version flag has been renamed to `-V`. * The `-h` screen has been split into two parts. Most top-level options (not all) show with `-h`, and the remaining options (generally obscure) can be shown with `--help -v` which is a "verbose help screen" * The `-V` flag (version flag now) has lost its argument as it is now requested with `rustc -vV` "verbose version". * The `--emit` option has had its `ir` and `bc` variants renamed to `llvm-ir` and `llvm-bc` to emphasize that they are LLVM's IR/bytecode. * The `--emit` option has grown a new variant, `dep-info`, which subsumes the `--dep-info` CLI argument. The `--dep-info` flag is now deprecated. * The `--parse-only`, `--no-trans`, and `--no-analysis` flags have moved behind the `-Z` family of flags. * The `--debuginfo` and `--opt-level` flags were moved behind the top-level `-C` flag. * The `--print-file-name` and `--print-crate-name` flags were moved behind one global `--print` flag which now accepts one of `crate-name`, `file-names`, or `sysroot`. This global `--print` flag is intended to serve as a mechanism for learning various metadata about the compiler itself. No warnings are currently enabled to allow tools like Cargo to have time to migrate to the new flags before spraying warnings to all users.
2014-12-16 00:03:39 +00:00
}
}
2018-03-06 05:29:03 +00:00
req => early_error(error_format, &format!("unknown print request `{}`", req)),
}));
let borrowck_mode = match debugging_opts.borrowck.as_ref().map(|s| &s[..]) {
None | Some("ast") => BorrowckMode::Ast,
Some("mir") => BorrowckMode::Mir,
Some("compare") => BorrowckMode::Compare,
2018-03-06 05:29:03 +00:00
Some(m) => early_error(error_format, &format!("unknown borrowck mode `{}`", m)),
};
if !cg.remark.is_empty() && debuginfo == NoDebugInfo {
2018-03-06 05:29:03 +00:00
early_warn(
error_format,
"-C remark will not show source locations without \
--debuginfo",
);
}
let mut externs = BTreeMap::new();
2015-01-31 17:20:46 +00:00
for arg in &matches.opt_strs("extern") {
let mut parts = arg.splitn(2, '=');
let name = match parts.next() {
Some(s) => s,
None => early_error(error_format, "--extern value must not be empty"),
};
let location = match parts.next() {
Some(s) => s,
2018-03-06 05:29:03 +00:00
None => early_error(
error_format,
"--extern value must be of the format `foo=bar`",
),
};
2014-09-18 21:05:52 +00:00
2018-03-06 05:29:03 +00:00
externs
.entry(name.to_string())
.or_insert_with(BTreeSet::new)
.insert(location.to_string());
}
let crate_name = matches.opt_str("crate-name");
2018-03-06 05:29:03 +00:00
let remap_path_prefix = matches
.opt_strs("remap-path-prefix")
.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 05:29:03 +00:00
_ => early_error(
error_format,
"--remap-path-prefix must contain '=' between FROM and TO",
),
}
})
.collect();
2018-03-06 05:29:03 +00:00
(
Options {
crate_types,
optimize: opt_level,
debuginfo,
lint_opts,
lint_cap,
describe_lints,
output_types: OutputTypes(output_types),
search_paths,
maybe_sysroot: sysroot_opt,
target_triple,
2018-03-06 05:29:03 +00:00
test,
incremental,
debugging_opts,
prints,
borrowck_mode,
cg,
error_format,
externs: Externs(externs),
crate_name,
alt_std_name: None,
libs,
unstable_features: UnstableFeatures::from_environment(),
debug_assertions,
actually_rustdoc: false,
cli_forced_codegen_units: codegen_units,
cli_forced_thinlto_off: disable_thinlto,
remap_path_prefix,
},
cfg,
)
}
2018-03-06 05:29:03 +00:00
pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> {
let mut crate_types: Vec<CrateType> = Vec::new();
2015-01-31 17:20:46 +00:00
for unparsed_crate_type in &list_list {
for part in unparsed_crate_type.split(',') {
let new_part = match part {
2018-03-06 05:29:03 +00:00
"lib" => default_lib_output(),
"rlib" => CrateTypeRlib,
"staticlib" => CrateTypeStaticlib,
2018-03-06 05:29:03 +00:00
"dylib" => CrateTypeDylib,
"cdylib" => CrateTypeCdylib,
"bin" => CrateTypeExecutable,
"proc-macro" => CrateTypeProcMacro,
_ => {
2018-03-06 05:29:03 +00:00
return Err(format!("unknown crate type: `{}`", part));
}
};
if !crate_types.contains(&new_part) {
crate_types.push(new_part)
}
}
}
Ok(crate_types)
}
pub mod nightly_options {
use getopts;
use syntax::feature_gate::UnstableFeatures;
use super::{ErrorOutputType, OptionStability, RustcOptGroup};
use session::early_error;
pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool {
2018-03-06 05:29:03 +00:00
is_nightly_build()
&& matches
.opt_strs("Z")
.iter()
.any(|x| *x == "unstable-options")
}
pub fn is_nightly_build() -> bool {
UnstableFeatures::from_environment().is_nightly_build()
}
pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) {
2018-03-06 05:29:03 +00:00
let has_z_unstable_option = matches
.opt_strs("Z")
.iter()
.any(|x| *x == "unstable-options");
let really_allows_unstable_options =
UnstableFeatures::from_environment().is_nightly_build();
for opt in flags.iter() {
if opt.stability == OptionStability::Stable {
2018-03-06 05:29:03 +00:00
continue;
}
if !matches.opt_present(opt.name) {
2018-03-06 05:29:03 +00:00
continue;
}
if opt.name != "Z" && !has_z_unstable_option {
2018-03-06 05:29:03 +00:00
early_error(
ErrorOutputType::default(),
&format!(
"the `-Z unstable-options` flag must also be passed to enable \
the flag `{}`",
opt.name
),
);
}
if really_allows_unstable_options {
2018-03-06 05:29:03 +00:00
continue;
}
match opt.stability {
OptionStability::Unstable => {
2018-03-06 05:29:03 +00:00
let msg = format!(
"the option `{}` is only accepted on the \
nightly compiler",
opt.name
);
early_error(ErrorOutputType::default(), &msg);
}
OptionStability::Stable => {}
}
}
}
}
std: Rename Show/String to Debug/Display This commit is an implementation of [RFC 565][rfc] which is a stabilization of the `std::fmt` module and the implementations of various formatting traits. Specifically, the following changes were performed: [rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0565-show-string-guidelines.md * The `Show` trait is now deprecated, it was renamed to `Debug` * The `String` trait is now deprecated, it was renamed to `Display` * Many `Debug` and `Display` implementations were audited in accordance with the RFC and audited implementations now have the `#[stable]` attribute * Integers and floats no longer print a suffix * Smart pointers no longer print details that they are a smart pointer * Paths with `Debug` are now quoted and escape characters * The `unwrap` methods on `Result` now require `Display` instead of `Debug` * The `Error` trait no longer has a `detail` method and now requires that `Display` must be implemented. With the loss of `String`, this has moved into libcore. * `impl<E: Error> FromError<E> for Box<Error>` now exists * `derive(Show)` has been renamed to `derive(Debug)`. This is not currently warned about due to warnings being emitted on stage1+ While backwards compatibility is attempted to be maintained with a blanket implementation of `Display` for the old `String` trait (and the same for `Show`/`Debug`) this is still a breaking change due to primitives no longer implementing `String` as well as modifications such as `unwrap` and the `Error` trait. Most code is fairly straightforward to update with a rename or tweaks of method calls. [breaking-change] Closes #21436
2015-01-20 23:45:07 +00:00
impl fmt::Display for CrateType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
CrateTypeExecutable => "bin".fmt(f),
CrateTypeDylib => "dylib".fmt(f),
CrateTypeRlib => "rlib".fmt(f),
CrateTypeStaticlib => "staticlib".fmt(f),
CrateTypeCdylib => "cdylib".fmt(f),
CrateTypeProcMacro => "proc-macro".fmt(f),
}
}
}
/// Commandline arguments passed to the compiler have to be incorporated with
/// the dependency tracking system for incremental compilation. This module
/// provides some utilities to make this more convenient.
///
/// The values of all commandline arguments that are relevant for dependency
/// tracking are hashed into a single value that determines whether the
/// incremental compilation cache can be re-used or not. This hashing is done
/// via the DepTrackingHash trait defined below, since the standard Hash
/// implementation might not be suitable (e.g. arguments are stored in a Vec,
/// the hash of which is order dependent, but we might not want the order of
/// arguments to make a difference for the hash).
///
/// However, since the value provided by Hash::hash often *is* suitable,
/// especially for primitive types, there is the
/// impl_dep_tracking_hash_via_hash!() macro that allows to simply reuse the
/// Hash implementation for DepTrackingHash. It's important though that
/// we have an opt-in scheme here, so one is hopefully forced to think about
/// how the hash should be calculated when adding a new commandline argument.
mod dep_tracking {
use lint;
use middle::cstore;
use std::collections::BTreeMap;
use std::hash::Hash;
use std::path::PathBuf;
use std::collections::hash_map::DefaultHasher;
2018-03-15 03:30:06 +00:00
use super::{CrateType, DebugInfoLevel, Edition, ErrorOutputType, Lto, OptLevel, OutputTypes,
2018-03-06 05:29:03 +00:00
Passes, Sanitizer};
use syntax::feature_gate::UnstableFeatures;
use rustc_back::{PanicStrategy, RelroLevel};
use rustc_back::target::TargetTriple;
pub trait DepTrackingHash {
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType);
}
macro_rules! impl_dep_tracking_hash_via_hash {
($t:ty) => (
impl DepTrackingHash for $t {
fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType) {
Hash::hash(self, hasher);
}
}
)
}
macro_rules! impl_dep_tracking_hash_for_sortable_vec_of {
($t:ty) => (
impl DepTrackingHash for Vec<$t> {
fn hash(&self, hasher: &mut DefaultHasher, error_format: ErrorOutputType) {
2016-08-09 19:28:24 +00:00
let mut elems: Vec<&$t> = self.iter().collect();
elems.sort();
2016-08-09 19:28:24 +00:00
Hash::hash(&elems.len(), hasher);
for (index, elem) in elems.iter().enumerate() {
Hash::hash(&index, hasher);
DepTrackingHash::hash(*elem, hasher, error_format);
}
}
}
);
}
impl_dep_tracking_hash_via_hash!(bool);
impl_dep_tracking_hash_via_hash!(usize);
impl_dep_tracking_hash_via_hash!(u64);
impl_dep_tracking_hash_via_hash!(String);
impl_dep_tracking_hash_via_hash!(PathBuf);
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>);
impl_dep_tracking_hash_via_hash!(Option<(String, u64)>);
impl_dep_tracking_hash_via_hash!(Option<PanicStrategy>);
impl_dep_tracking_hash_via_hash!(Option<RelroLevel>);
impl_dep_tracking_hash_via_hash!(Option<lint::Level>);
impl_dep_tracking_hash_via_hash!(Option<PathBuf>);
2017-02-21 21:18:58 +00:00
impl_dep_tracking_hash_via_hash!(Option<cstore::NativeLibraryKind>);
impl_dep_tracking_hash_via_hash!(CrateType);
impl_dep_tracking_hash_via_hash!(PanicStrategy);
impl_dep_tracking_hash_via_hash!(RelroLevel);
impl_dep_tracking_hash_via_hash!(Passes);
impl_dep_tracking_hash_via_hash!(OptLevel);
impl_dep_tracking_hash_via_hash!(Lto);
impl_dep_tracking_hash_via_hash!(DebugInfoLevel);
impl_dep_tracking_hash_via_hash!(UnstableFeatures);
impl_dep_tracking_hash_via_hash!(OutputTypes);
impl_dep_tracking_hash_via_hash!(cstore::NativeLibraryKind);
impl_dep_tracking_hash_via_hash!(Sanitizer);
impl_dep_tracking_hash_via_hash!(Option<Sanitizer>);
2018-03-15 03:30:06 +00:00
impl_dep_tracking_hash_via_hash!(Edition);
impl_dep_tracking_hash_via_hash!(TargetTriple);
impl_dep_tracking_hash_for_sortable_vec_of!(String);
impl_dep_tracking_hash_for_sortable_vec_of!(PathBuf);
impl_dep_tracking_hash_for_sortable_vec_of!(CrateType);
impl_dep_tracking_hash_for_sortable_vec_of!((String, lint::Level));
2018-03-06 05:29:03 +00:00
impl_dep_tracking_hash_for_sortable_vec_of!((
String,
Option<String>,
Option<cstore::NativeLibraryKind>
));
impl_dep_tracking_hash_for_sortable_vec_of!((String, u64));
impl<T1, T2> DepTrackingHash for (T1, T2)
2018-03-06 05:29:03 +00:00
where
T1: DepTrackingHash,
T2: DepTrackingHash,
{
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);
}
}
impl<T1, T2, T3> DepTrackingHash for (T1, T2, T3)
2018-03-06 05:29:03 +00:00
where
T1: DepTrackingHash,
T2: DepTrackingHash,
T3: DepTrackingHash,
{
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);
}
}
// This is a stable hash because BTreeMap is a sorted container
2018-03-06 05:29:03 +00:00
pub fn stable_hash(
sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>,
hasher: &mut DefaultHasher,
error_format: ErrorOutputType,
) {
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);
}
}
}
#[cfg(test)]
mod tests {
use errors;
use getopts;
use lint;
use middle::cstore;
use session::config::{build_configuration, build_session_options_and_crate_config};
use session::config::Lto;
use session::build_session;
use std::collections::{BTreeMap, BTreeSet};
use std::iter::FromIterator;
use std::path::PathBuf;
2018-03-06 05:29:03 +00:00
use super::{Externs, OutputType, OutputTypes};
use rustc_back::{PanicStrategy, RelroLevel};
2016-11-17 14:04:36 +00:00
use syntax::symbol::Symbol;
use syntax;
fn optgroups() -> getopts::Options {
let mut opts = getopts::Options::new();
for group in super::rustc_optgroups() {
(group.apply)(&mut opts);
}
2018-03-06 05:29:03 +00:00
return opts;
}
fn mk_map<K: Ord, V>(entries: Vec<(K, V)>) -> BTreeMap<K, V> {
BTreeMap::from_iter(entries.into_iter())
}
fn mk_set<V: Ord>(entries: Vec<V>) -> BTreeSet<V> {
BTreeSet::from_iter(entries.into_iter())
}
// When the user supplies --test we should implicitly supply --cfg test
#[test]
fn test_switch_implies_cfg_test() {
syntax::with_globals(|| {
let matches = &match optgroups().parse(&["--test".to_string()]) {
Ok(m) => m,
Err(f) => panic!("test_switch_implies_cfg_test: {}", f),
};
let registry = errors::registry::Registry::new(&[]);
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
let sess = build_session(sessopts, None, registry);
let cfg = build_configuration(&sess, cfg);
assert!(cfg.contains(&(Symbol::intern("test"), None)));
});
}
// When the user supplies --test and --cfg test, don't implicitly add
// another --cfg test
#[test]
fn test_switch_implies_cfg_test_unless_cfg_test() {
syntax::with_globals(|| {
let matches = &match optgroups().parse(&["--test".to_string(),
"--cfg=test".to_string()]) {
Ok(m) => m,
Err(f) => panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f),
};
let registry = errors::registry::Registry::new(&[]);
let (sessopts, cfg) = build_session_options_and_crate_config(matches);
let sess = build_session(sessopts, None, registry);
let cfg = build_configuration(&sess, cfg);
let mut test_items = cfg.iter().filter(|&&(name, _)| name == "test");
assert!(test_items.next().is_some());
assert!(test_items.next().is_none());
});
}
#[test]
fn test_can_print_warnings() {
syntax::with_globals(|| {
2018-03-06 05:29:03 +00:00
let matches = optgroups().parse(&["-Awarnings".to_string()]).unwrap();
let registry = errors::registry::Registry::new(&[]);
let (sessopts, _) = build_session_options_and_crate_config(&matches);
let sess = build_session(sessopts, None, registry);
2017-11-20 18:03:20 +00:00
assert!(!sess.diagnostic().flags.can_emit_warnings);
});
syntax::with_globals(|| {
2018-03-06 05:29:03 +00:00
let matches = optgroups()
.parse(&["-Awarnings".to_string(), "-Dwarnings".to_string()])
.unwrap();
let registry = errors::registry::Registry::new(&[]);
let (sessopts, _) = build_session_options_and_crate_config(&matches);
let sess = build_session(sessopts, None, registry);
2017-11-20 18:03:20 +00:00
assert!(sess.diagnostic().flags.can_emit_warnings);
});
syntax::with_globals(|| {
2018-03-06 05:29:03 +00:00
let matches = optgroups().parse(&["-Adead_code".to_string()]).unwrap();
let registry = errors::registry::Registry::new(&[]);
let (sessopts, _) = build_session_options_and_crate_config(&matches);
let sess = build_session(sessopts, None, registry);
2017-11-20 18:03:20 +00:00
assert!(sess.diagnostic().flags.can_emit_warnings);
});
}
#[test]
fn test_output_types_tracking_hash_different_paths() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
2018-03-06 05:29:03 +00:00
v1.output_types =
OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("./some/thing")))]);
v2.output_types =
OutputTypes::new(&[(OutputType::Exe, Some(PathBuf::from("/some/thing")))]);
v3.output_types = OutputTypes::new(&[(OutputType::Exe, None)]);
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
}
#[test]
fn test_output_types_tracking_hash_different_construction_order() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
v1.output_types = OutputTypes::new(&[
(OutputType::Exe, Some(PathBuf::from("./some/thing"))),
(OutputType::Bitcode, Some(PathBuf::from("./some/thing.bc"))),
]);
v2.output_types = OutputTypes::new(&[
(OutputType::Bitcode, Some(PathBuf::from("./some/thing.bc"))),
(OutputType::Exe, Some(PathBuf::from("./some/thing"))),
]);
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
}
#[test]
fn test_externs_tracking_hash_different_construction_order() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
v1.externs = Externs::new(mk_map(vec![
2018-03-06 05:29:03 +00:00
(
String::from("a"),
mk_set(vec![String::from("b"), String::from("c")]),
),
(
String::from("d"),
mk_set(vec![String::from("e"), String::from("f")]),
),
]));
v2.externs = Externs::new(mk_map(vec![
2018-03-06 05:29:03 +00:00
(
String::from("d"),
mk_set(vec![String::from("e"), String::from("f")]),
),
(
String::from("a"),
mk_set(vec![String::from("b"), String::from("c")]),
),
]));
v3.externs = Externs::new(mk_map(vec![
2018-03-06 05:29:03 +00:00
(
String::from("a"),
mk_set(vec![String::from("b"), String::from("c")]),
),
(
String::from("d"),
mk_set(vec![String::from("f"), String::from("e")]),
),
]));
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
assert_eq!(v1.dep_tracking_hash(), v3.dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v3.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
}
#[test]
fn test_lints_tracking_hash_different_values() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
2018-03-06 05:29:03 +00:00
v1.lint_opts = vec![
(String::from("a"), lint::Allow),
(String::from("b"), lint::Warn),
(String::from("c"), lint::Deny),
(String::from("d"), lint::Forbid),
];
v2.lint_opts = vec![
(String::from("a"), lint::Allow),
(String::from("b"), lint::Warn),
(String::from("X"), lint::Deny),
(String::from("d"), lint::Forbid),
];
v3.lint_opts = vec![
(String::from("a"), lint::Allow),
(String::from("b"), lint::Warn),
(String::from("c"), lint::Forbid),
(String::from("d"), lint::Deny),
];
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
assert!(v2.dep_tracking_hash() != v3.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
}
#[test]
fn test_lints_tracking_hash_different_construction_order() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
2018-03-06 05:29:03 +00:00
v1.lint_opts = vec![
(String::from("a"), lint::Allow),
(String::from("b"), lint::Warn),
(String::from("c"), lint::Deny),
(String::from("d"), lint::Forbid),
];
2018-03-06 05:29:03 +00:00
v2.lint_opts = vec![
(String::from("a"), lint::Allow),
(String::from("c"), lint::Deny),
(String::from("b"), lint::Warn),
(String::from("d"), lint::Forbid),
];
assert_eq!(v1.dep_tracking_hash(), v2.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
}
#[test]
fn test_search_paths_tracking_hash_different_order() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
let mut v4 = super::basic_options();
// Reference
2018-03-06 05:29:03 +00:00
v1.search_paths
.add_path("native=abc", super::ErrorOutputType::Json(false));
v1.search_paths
.add_path("crate=def", super::ErrorOutputType::Json(false));
v1.search_paths
.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v1.search_paths
.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v1.search_paths
.add_path("all=mno", super::ErrorOutputType::Json(false));
v2.search_paths
.add_path("native=abc", super::ErrorOutputType::Json(false));
v2.search_paths
.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v2.search_paths
.add_path("crate=def", super::ErrorOutputType::Json(false));
v2.search_paths
.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v2.search_paths
.add_path("all=mno", super::ErrorOutputType::Json(false));
v3.search_paths
.add_path("crate=def", super::ErrorOutputType::Json(false));
v3.search_paths
.add_path("framework=jkl", super::ErrorOutputType::Json(false));
v3.search_paths
.add_path("native=abc", super::ErrorOutputType::Json(false));
v3.search_paths
.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v3.search_paths
.add_path("all=mno", super::ErrorOutputType::Json(false));
v4.search_paths
.add_path("all=mno", super::ErrorOutputType::Json(false));
v4.search_paths
.add_path("native=abc", super::ErrorOutputType::Json(false));
v4.search_paths
.add_path("crate=def", super::ErrorOutputType::Json(false));
v4.search_paths
.add_path("dependency=ghi", super::ErrorOutputType::Json(false));
v4.search_paths
.add_path("framework=jkl", super::ErrorOutputType::Json(false));
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
assert!(v1.dep_tracking_hash() == v4.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
}
#[test]
fn test_native_libs_tracking_hash_different_values() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
let mut v4 = super::basic_options();
// Reference
2018-03-06 05:29:03 +00:00
v1.libs = vec![
(String::from("a"), None, Some(cstore::NativeStatic)),
(String::from("b"), None, Some(cstore::NativeFramework)),
(String::from("c"), None, Some(cstore::NativeUnknown)),
];
// Change label
2018-03-06 05:29:03 +00:00
v2.libs = vec![
(String::from("a"), None, Some(cstore::NativeStatic)),
(String::from("X"), None, Some(cstore::NativeFramework)),
(String::from("c"), None, Some(cstore::NativeUnknown)),
];
// Change kind
2018-03-06 05:29:03 +00:00
v3.libs = vec![
(String::from("a"), None, Some(cstore::NativeStatic)),
(String::from("b"), None, Some(cstore::NativeStatic)),
(String::from("c"), None, Some(cstore::NativeUnknown)),
];
// Change new-name
2018-03-06 05:29:03 +00:00
v4.libs = vec![
(String::from("a"), None, Some(cstore::NativeStatic)),
(
String::from("b"),
Some(String::from("X")),
Some(cstore::NativeFramework),
),
(String::from("c"), None, Some(cstore::NativeUnknown)),
];
assert!(v1.dep_tracking_hash() != v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v3.dep_tracking_hash());
assert!(v1.dep_tracking_hash() != v4.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
assert_eq!(v4.dep_tracking_hash(), v4.clone().dep_tracking_hash());
}
#[test]
fn test_native_libs_tracking_hash_different_order() {
let mut v1 = super::basic_options();
let mut v2 = super::basic_options();
let mut v3 = super::basic_options();
// Reference
2018-03-06 05:29:03 +00:00
v1.libs = vec![
(String::from("a"), None, Some(cstore::NativeStatic)),
(String::from("b"), None, Some(cstore::NativeFramework)),
(String::from("c"), None, Some(cstore::NativeUnknown)),
];
v2.libs = vec![
(String::from("b"), None, Some(cstore::NativeFramework)),
(String::from("a"), None, Some(cstore::NativeStatic)),
(String::from("c"), None, Some(cstore::NativeUnknown)),
];
v3.libs = vec![
(String::from("c"), None, Some(cstore::NativeUnknown)),
(String::from("a"), None, Some(cstore::NativeStatic)),
(String::from("b"), None, Some(cstore::NativeFramework)),
];
assert!(v1.dep_tracking_hash() == v2.dep_tracking_hash());
assert!(v1.dep_tracking_hash() == v3.dep_tracking_hash());
assert!(v2.dep_tracking_hash() == v3.dep_tracking_hash());
// Check clone
assert_eq!(v1.dep_tracking_hash(), v1.clone().dep_tracking_hash());
assert_eq!(v2.dep_tracking_hash(), v2.clone().dep_tracking_hash());
assert_eq!(v3.dep_tracking_hash(), v3.clone().dep_tracking_hash());
}
#[test]
fn test_codegen_options_tracking_hash() {
let reference = super::basic_options();
let mut opts = super::basic_options();
// Make sure the changing an [UNTRACKED] option leaves the hash unchanged
opts.cg.ar = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.linker = Some(PathBuf::from("linker"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.link_args = Some(vec![String::from("abc"), String::from("def")]);
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.link_dead_code = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.rpath = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.extra_filename = String::from("extra-filename");
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2017-09-25 19:26:25 +00:00
opts.cg.codegen_units = Some(42);
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2018-03-06 05:29:03 +00:00
opts.cg.remark = super::SomePasses(vec![String::from("pass1"), String::from("pass2")]);
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.save_temps = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.cg.incremental = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
// Make sure changing a [TRACKED] option changes the hash
opts = reference.clone();
opts.cg.lto = Lto::Fat;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.target_cpu = Some(String::from("abc"));
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.target_feature = String::from("all the features, all of them");
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.passes = vec![String::from("1"), String::from("2")];
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.llvm_args = vec![String::from("1"), String::from("2")];
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.overflow_checks = Some(true);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_prepopulate_passes = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_vectorize_loops = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_vectorize_slp = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.soft_float = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.prefer_dynamic = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_integrated_as = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.no_redzone = Some(true);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.relocation_model = Some(String::from("relocation model"));
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.code_model = Some(String::from("code model"));
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.tls_model = Some(String::from("tls model"));
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.pgo_gen = Some(String::from("abc"));
assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.pgo_use = String::from("abc");
assert_ne!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.metadata = vec![String::from("A"), String::from("B")];
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.debuginfo = Some(0xdeadbeef);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.debuginfo = Some(0xba5eba11);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.debug_assertions = Some(true);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.inline_threshold = Some(0xf007ba11);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.cg.panic = Some(PanicStrategy::Abort);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
}
#[test]
fn test_debugging_options_tracking_hash() {
let reference = super::basic_options();
let mut opts = super::basic_options();
// Make sure the changing an [UNTRACKED] option leaves the hash unchanged
opts.debugging_opts.verbose = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.time_passes = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.count_llvm_insns = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.time_llvm_passes = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.input_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.trans_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.borrowck_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.meta_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_link_args = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_llvm_passes = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.ast_json = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.ast_json_noexpand = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.ls = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.save_analysis = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.flowgraph_print_loans = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.flowgraph_print_moves = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.flowgraph_print_assigns = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.flowgraph_print_all = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_region_graph = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.parse_only = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.incremental = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.dump_dep_graph = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.query_dep_graph = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.no_analysis = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.unstable_options = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.trace_macros = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.keep_hygiene_data = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.keep_ast = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.print_trans_items = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.dump_mir = Some(String::from("abc"));
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
2018-01-15 00:09:39 +00:00
opts.debugging_opts.dump_mir_dir = String::from("abc");
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.dump_mir_graphviz = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
// Make sure changing a [TRACKED] option changes the hash
opts = reference.clone();
opts.debugging_opts.asm_comments = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.no_verify = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.no_landing_pads = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.fewer_names = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.no_trans = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.treat_err_as_bug = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.continue_parse_after_error = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.extra_plugins = vec![String::from("plugin1"), String::from("plugin2")];
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.force_overflow_checks = Some(true);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.enable_nonzeroing_move_hints = true;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.show_span = Some(String::from("abc"));
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.mir_opt_level = 3;
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
opts = reference.clone();
opts.debugging_opts.relro_level = Some(RelroLevel::Full);
assert!(reference.dep_tracking_hash() != opts.dep_tracking_hash());
}
}