]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | //! Contains infrastructure for configuring the compiler, including parsing |
e1599b0c | 2 | //! command-line options. |
83c7162d | 3 | |
dfeec247 XL |
4 | pub use crate::options::*; |
5 | ||
dfeec247 | 6 | use crate::search_paths::SearchPath; |
17df50a5 | 7 | use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; |
60c5eb7d | 8 | use crate::{early_error, early_warn, Session}; |
04454e1e | 9 | use crate::{lint, HashStableContext}; |
1a4d82fc | 10 | |
5e7ed085 | 11 | use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
e1599b0c | 12 | |
04454e1e | 13 | use rustc_data_structures::stable_hasher::ToStableHashKey; |
1b1a35ee | 14 | use rustc_target::abi::{Align, TargetDataLayout}; |
f2b60f7d FG |
15 | use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo}; |
16 | use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS}; | |
1a4d82fc | 17 | |
5099ac24 | 18 | use crate::parse::{CrateCheckConfig, CrateConfig}; |
dfeec247 | 19 | use rustc_feature::UnstableFeatures; |
cdc7bbd5 | 20 | use rustc_span::edition::{Edition, DEFAULT_EDITION, EDITION_NAME_LIST, LATEST_STABLE_EDITION}; |
dfeec247 XL |
21 | use rustc_span::source_map::{FileName, FilePathMapping}; |
22 | use rustc_span::symbol::{sym, Symbol}; | |
94222f64 | 23 | use rustc_span::RealFileName; |
ba9703b0 | 24 | use rustc_span::SourceFileHashAlgorithm; |
1a4d82fc | 25 | |
60c5eb7d | 26 | use rustc_errors::emitter::HumanReadableErrorType; |
ba9703b0 | 27 | use rustc_errors::{ColorConfig, HandlerFlags}; |
3157f602 | 28 | |
e1599b0c XL |
29 | use std::collections::btree_map::{ |
30 | Iter as BTreeMapIter, Keys as BTreeMapKeysIter, Values as BTreeMapValuesIter, | |
31 | }; | |
dfeec247 | 32 | use std::collections::{BTreeMap, BTreeSet}; |
e1599b0c | 33 | use std::fmt; |
136023e0 | 34 | use std::hash::Hash; |
60c5eb7d | 35 | use std::iter::{self, FromIterator}; |
0531ce1d | 36 | use std::path::{Path, PathBuf}; |
dfeec247 | 37 | use std::str::{self, FromStr}; |
1a4d82fc | 38 | |
f2b60f7d FG |
39 | pub mod sigpipe; |
40 | ||
3c0e092e | 41 | /// The different settings that the `-C strip` flag can have. |
f9f354fc XL |
42 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] |
43 | pub enum Strip { | |
44 | /// Do not strip at all. | |
45 | None, | |
46 | ||
47 | /// Strip debuginfo. | |
48 | Debuginfo, | |
49 | ||
50 | /// Strip all symbols. | |
51 | Symbols, | |
52 | } | |
53 | ||
3dfed10e | 54 | /// The different settings that the `-C control-flow-guard` flag can have. |
74b04a01 XL |
55 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] |
56 | pub enum CFGuard { | |
57 | /// Do not emit Control Flow Guard metadata or checks. | |
58 | Disabled, | |
59 | ||
60 | /// Emit Control Flow Guard metadata but no checks. | |
61 | NoChecks, | |
62 | ||
63 | /// Emit Control Flow Guard metadata and checks. | |
64 | Checks, | |
65 | } | |
66 | ||
5099ac24 FG |
67 | /// The different settings that the `-Z cf-protection` flag can have. |
68 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] | |
69 | pub enum CFProtection { | |
70 | /// Do not enable control-flow protection | |
71 | None, | |
72 | ||
73 | /// Emit control-flow protection for branches (enables indirect branch tracking). | |
74 | Branch, | |
75 | ||
76 | /// Emit control-flow protection for returns. | |
77 | Return, | |
78 | ||
79 | /// Emit control-flow protection for both branches and returns. | |
80 | Full, | |
81 | } | |
82 | ||
04454e1e | 83 | #[derive(Clone, Copy, Debug, PartialEq, Hash, HashStable_Generic)] |
1a4d82fc | 84 | pub enum OptLevel { |
0531ce1d XL |
85 | No, // -O0 |
86 | Less, // -O1 | |
87 | Default, // -O2 | |
a7813a04 | 88 | Aggressive, // -O3 |
0531ce1d XL |
89 | Size, // -Os |
90 | SizeMin, // -Oz | |
1a4d82fc JJ |
91 | } |
92 | ||
b7449926 XL |
93 | /// This is what the `LtoCli` values get mapped to after resolving defaults and |
94 | /// and taking other command line options into account. | |
cdc7bbd5 XL |
95 | /// |
96 | /// Note that linker plugin-based LTO is a different mechanism entirely. | |
e74abb32 | 97 | #[derive(Clone, PartialEq)] |
2c00a5a8 | 98 | pub enum Lto { |
cdc7bbd5 | 99 | /// Don't do any LTO whatsoever. |
2c00a5a8 XL |
100 | No, |
101 | ||
cdc7bbd5 | 102 | /// Do a full-crate-graph (inter-crate) LTO with ThinLTO. |
2c00a5a8 XL |
103 | Thin, |
104 | ||
cdc7bbd5 XL |
105 | /// Do a local ThinLTO (intra-crate, over the CodeGen Units of the local crate only). This is |
106 | /// only relevant if multiple CGUs are used. | |
2c00a5a8 XL |
107 | ThinLocal, |
108 | ||
cdc7bbd5 | 109 | /// Do a full-crate-graph (inter-crate) LTO with "fat" LTO. |
2c00a5a8 XL |
110 | Fat, |
111 | } | |
112 | ||
b7449926 XL |
113 | /// The different settings that the `-C lto` flag can have. |
114 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] | |
115 | pub enum LtoCli { | |
116 | /// `-C lto=no` | |
117 | No, | |
118 | /// `-C lto=yes` | |
119 | Yes, | |
120 | /// `-C lto` | |
121 | NoParam, | |
122 | /// `-C lto=thin` | |
123 | Thin, | |
124 | /// `-C lto=fat` | |
125 | Fat, | |
126 | /// No `-C lto` flag passed | |
127 | Unspecified, | |
128 | } | |
129 | ||
1b1a35ee XL |
130 | /// The different settings that the `-Z dump_mir_spanview` flag can have. `Statement` generates a |
131 | /// document highlighting each span of every statement (including terminators). `Terminator` and | |
132 | /// `Block` highlight a single span per `BasicBlock`: the span of the block's `Terminator`, or a | |
133 | /// computed span for the block, representing the entire range, covering the block's terminator and | |
134 | /// all of its statements. | |
135 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] | |
136 | pub enum MirSpanview { | |
137 | /// Default `-Z dump_mir_spanview` or `-Z dump_mir_spanview=statement` | |
138 | Statement, | |
139 | /// `-Z dump_mir_spanview=terminator` | |
140 | Terminator, | |
141 | /// `-Z dump_mir_spanview=block` | |
142 | Block, | |
143 | } | |
144 | ||
5099ac24 | 145 | /// The different settings that the `-C instrument-coverage` flag can have. |
cdc7bbd5 | 146 | /// |
5099ac24 | 147 | /// Coverage instrumentation now supports combining `-C instrument-coverage` |
cdc7bbd5 XL |
148 | /// with compiler and linker optimization (enabled with `-O` or `-C opt-level=1` |
149 | /// and higher). Nevertheless, there are many variables, depending on options | |
150 | /// selected, code structure, and enabled attributes. If errors are encountered, | |
151 | /// either while compiling or when generating `llvm-cov show` reports, consider | |
152 | /// lowering the optimization level, including or excluding `-C link-dead-code`, | |
5099ac24 FG |
153 | /// or using `-Zunstable-options -C instrument-coverage=except-unused-functions` |
154 | /// or `-Zunstable-options -C instrument-coverage=except-unused-generics`. | |
cdc7bbd5 XL |
155 | /// |
156 | /// Note that `ExceptUnusedFunctions` means: When `mapgen.rs` generates the | |
157 | /// coverage map, it will not attempt to generate synthetic functions for unused | |
158 | /// (and not code-generated) functions (whether they are generic or not). As a | |
159 | /// result, non-codegenned functions will not be included in the coverage map, | |
160 | /// and will not appear, as covered or uncovered, in coverage reports. | |
161 | /// | |
162 | /// `ExceptUnusedGenerics` will add synthetic functions to the coverage map, | |
163 | /// unless the function has type parameters. | |
164 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] | |
165 | pub enum InstrumentCoverage { | |
5099ac24 | 166 | /// Default `-C instrument-coverage` or `-C instrument-coverage=statement` |
cdc7bbd5 | 167 | All, |
5099ac24 | 168 | /// `-Zunstable-options -C instrument-coverage=except-unused-generics` |
cdc7bbd5 | 169 | ExceptUnusedGenerics, |
5099ac24 | 170 | /// `-Zunstable-options -C instrument-coverage=except-unused-functions` |
cdc7bbd5 | 171 | ExceptUnusedFunctions, |
5099ac24 | 172 | /// `-C instrument-coverage=off` (or `no`, etc.) |
cdc7bbd5 XL |
173 | Off, |
174 | } | |
175 | ||
176 | #[derive(Clone, PartialEq, Hash, Debug)] | |
9fa01778 | 177 | pub enum LinkerPluginLto { |
94b46f34 | 178 | LinkerPlugin(PathBuf), |
8faf50e0 | 179 | LinkerPluginAuto, |
dfeec247 | 180 | Disabled, |
94b46f34 XL |
181 | } |
182 | ||
3c0e092e XL |
183 | /// Used with `-Z assert-incr-state`. |
184 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] | |
185 | pub enum IncrementalStateAssertion { | |
186 | /// Found and loaded an existing session directory. | |
187 | /// | |
188 | /// Note that this says nothing about whether any particular query | |
189 | /// will be found to be red or green. | |
190 | Loaded, | |
191 | /// Did not load an existing session directory. | |
192 | NotLoaded, | |
193 | } | |
194 | ||
9fa01778 | 195 | impl LinkerPluginLto { |
8faf50e0 | 196 | pub fn enabled(&self) -> bool { |
94b46f34 | 197 | match *self { |
dfeec247 | 198 | LinkerPluginLto::LinkerPlugin(_) | LinkerPluginLto::LinkerPluginAuto => true, |
9fa01778 | 199 | LinkerPluginLto::Disabled => false, |
94b46f34 XL |
200 | } |
201 | } | |
202 | } | |
203 | ||
3c0e092e XL |
204 | /// The different settings that can be enabled via the `-Z location-detail` flag. |
205 | #[derive(Clone, PartialEq, Hash, Debug)] | |
206 | pub struct LocationDetail { | |
207 | pub file: bool, | |
208 | pub line: bool, | |
209 | pub column: bool, | |
210 | } | |
211 | ||
212 | impl LocationDetail { | |
213 | pub fn all() -> Self { | |
214 | Self { file: true, line: true, column: true } | |
215 | } | |
216 | } | |
217 | ||
cdc7bbd5 | 218 | #[derive(Clone, PartialEq, Hash, Debug)] |
dc9dc135 | 219 | pub enum SwitchWithOptPath { |
48663c56 XL |
220 | Enabled(Option<PathBuf>), |
221 | Disabled, | |
222 | } | |
223 | ||
dc9dc135 | 224 | impl SwitchWithOptPath { |
48663c56 XL |
225 | pub fn enabled(&self) -> bool { |
226 | match *self { | |
dc9dc135 XL |
227 | SwitchWithOptPath::Enabled(_) => true, |
228 | SwitchWithOptPath::Disabled => false, | |
48663c56 XL |
229 | } |
230 | } | |
231 | } | |
232 | ||
04454e1e | 233 | #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable_Generic)] |
3dfed10e | 234 | #[derive(Encodable, Decodable)] |
dc9dc135 XL |
235 | pub enum SymbolManglingVersion { |
236 | Legacy, | |
237 | V0, | |
238 | } | |
239 | ||
fc512014 | 240 | #[derive(Clone, Copy, Debug, PartialEq, Hash)] |
b7449926 XL |
241 | pub enum DebugInfo { |
242 | None, | |
243 | Limited, | |
244 | Full, | |
1a4d82fc JJ |
245 | } |
246 | ||
a2a8927a XL |
247 | /// Split debug-information is enabled by `-C split-debuginfo`, this enum is only used if split |
248 | /// debug-information is enabled (in either `Packed` or `Unpacked` modes), and the platform | |
249 | /// uses DWARF for debug-information. | |
250 | /// | |
251 | /// Some debug-information requires link-time relocation and some does not. LLVM can partition | |
252 | /// the debuginfo into sections depending on whether or not it requires link-time relocation. Split | |
253 | /// DWARF provides a mechanism which allows the linker to skip the sections which don't require | |
254 | /// link-time relocation - either by putting those sections in DWARF object files, or by keeping | |
255 | /// them in the object file in such a way that the linker will skip them. | |
256 | #[derive(Clone, Copy, Debug, PartialEq, Hash)] | |
257 | pub enum SplitDwarfKind { | |
258 | /// Sections which do not require relocation are written into object file but ignored by the | |
259 | /// linker. | |
260 | Single, | |
261 | /// Sections which do not require relocation are written into a DWARF object (`.dwo`) file | |
262 | /// which is ignored by the linker. | |
263 | Split, | |
264 | } | |
265 | ||
266 | impl FromStr for SplitDwarfKind { | |
267 | type Err = (); | |
268 | ||
269 | fn from_str(s: &str) -> Result<Self, ()> { | |
270 | Ok(match s { | |
271 | "single" => SplitDwarfKind::Single, | |
272 | "split" => SplitDwarfKind::Split, | |
273 | _ => return Err(()), | |
274 | }) | |
275 | } | |
276 | } | |
277 | ||
04454e1e | 278 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord, HashStable_Generic)] |
3dfed10e | 279 | #[derive(Encodable, Decodable)] |
1a4d82fc | 280 | pub enum OutputType { |
b039eaaf SL |
281 | Bitcode, |
282 | Assembly, | |
283 | LlvmAssembly, | |
cc61c64b | 284 | Mir, |
32a655c1 | 285 | Metadata, |
b039eaaf SL |
286 | Object, |
287 | Exe, | |
288 | DepInfo, | |
1a4d82fc JJ |
289 | } |
290 | ||
04454e1e FG |
291 | impl<HCX: HashStableContext> ToStableHashKey<HCX> for OutputType { |
292 | type KeyType = Self; | |
293 | ||
294 | fn to_stable_hash_key(&self, _: &HCX) -> Self::KeyType { | |
295 | *self | |
296 | } | |
297 | } | |
ea8adc8c | 298 | |
92a42be0 SL |
299 | impl OutputType { |
300 | fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool { | |
301 | match *self { | |
48663c56 | 302 | OutputType::Exe | OutputType::DepInfo | OutputType::Metadata => true, |
0531ce1d XL |
303 | OutputType::Bitcode |
304 | | OutputType::Assembly | |
305 | | OutputType::LlvmAssembly | |
306 | | OutputType::Mir | |
48663c56 | 307 | | OutputType::Object => false, |
92a42be0 SL |
308 | } |
309 | } | |
310 | ||
311 | fn shorthand(&self) -> &'static str { | |
312 | match *self { | |
313 | OutputType::Bitcode => "llvm-bc", | |
314 | OutputType::Assembly => "asm", | |
315 | OutputType::LlvmAssembly => "llvm-ir", | |
cc61c64b | 316 | OutputType::Mir => "mir", |
92a42be0 | 317 | OutputType::Object => "obj", |
32a655c1 | 318 | OutputType::Metadata => "metadata", |
92a42be0 SL |
319 | OutputType::Exe => "link", |
320 | OutputType::DepInfo => "dep-info", | |
321 | } | |
322 | } | |
5bcae85e | 323 | |
abe05a73 XL |
324 | fn from_shorthand(shorthand: &str) -> Option<Self> { |
325 | Some(match shorthand { | |
0531ce1d XL |
326 | "asm" => OutputType::Assembly, |
327 | "llvm-ir" => OutputType::LlvmAssembly, | |
328 | "mir" => OutputType::Mir, | |
329 | "llvm-bc" => OutputType::Bitcode, | |
330 | "obj" => OutputType::Object, | |
331 | "metadata" => OutputType::Metadata, | |
332 | "link" => OutputType::Exe, | |
333 | "dep-info" => OutputType::DepInfo, | |
abe05a73 XL |
334 | _ => return None, |
335 | }) | |
336 | } | |
337 | ||
338 | fn shorthands_display() -> String { | |
339 | format!( | |
340 | "`{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`, `{}`", | |
341 | OutputType::Bitcode.shorthand(), | |
342 | OutputType::Assembly.shorthand(), | |
343 | OutputType::LlvmAssembly.shorthand(), | |
344 | OutputType::Mir.shorthand(), | |
345 | OutputType::Object.shorthand(), | |
346 | OutputType::Metadata.shorthand(), | |
347 | OutputType::Exe.shorthand(), | |
348 | OutputType::DepInfo.shorthand(), | |
349 | ) | |
350 | } | |
351 | ||
5bcae85e SL |
352 | pub fn extension(&self) -> &'static str { |
353 | match *self { | |
354 | OutputType::Bitcode => "bc", | |
355 | OutputType::Assembly => "s", | |
356 | OutputType::LlvmAssembly => "ll", | |
cc61c64b | 357 | OutputType::Mir => "mir", |
5bcae85e | 358 | OutputType::Object => "o", |
32a655c1 | 359 | OutputType::Metadata => "rmeta", |
5bcae85e SL |
360 | OutputType::DepInfo => "d", |
361 | OutputType::Exe => "", | |
362 | } | |
363 | } | |
92a42be0 SL |
364 | } |
365 | ||
dc9dc135 | 366 | /// The type of diagnostics output to generate. |
476ff2be SL |
367 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
368 | pub enum ErrorOutputType { | |
dc9dc135 | 369 | /// Output meant for the consumption of humans. |
48663c56 | 370 | HumanReadable(HumanReadableErrorType), |
dc9dc135 | 371 | /// Output that's consumed by other tools such as `rustfix` or the `RLS`. |
48663c56 | 372 | Json { |
dc9dc135 | 373 | /// Render the JSON in a human readable way (with indents and newlines). |
48663c56 | 374 | pretty: bool, |
dc9dc135 XL |
375 | /// The JSON output includes a `rendered` field that includes the rendered |
376 | /// human output. | |
48663c56 XL |
377 | json_rendered: HumanReadableErrorType, |
378 | }, | |
476ff2be SL |
379 | } |
380 | ||
381 | impl Default for ErrorOutputType { | |
e1599b0c XL |
382 | fn default() -> Self { |
383 | Self::HumanReadable(HumanReadableErrorType::Default(ColorConfig::Auto)) | |
476ff2be SL |
384 | } |
385 | } | |
386 | ||
1b1a35ee | 387 | /// Parameter to control path trimming. |
3c0e092e | 388 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] |
1b1a35ee XL |
389 | pub enum TrimmedDefPaths { |
390 | /// `try_print_trimmed_def_path` never prints a trimmed path and never calls the expensive query | |
3c0e092e | 391 | #[default] |
1b1a35ee XL |
392 | Never, |
393 | /// `try_print_trimmed_def_path` calls the expensive query, the query doesn't call `delay_good_path_bug` | |
394 | Always, | |
395 | /// `try_print_trimmed_def_path` calls the expensive query, the query calls `delay_good_path_bug` | |
396 | GoodPath, | |
397 | } | |
398 | ||
e1599b0c XL |
399 | /// Use tree-based collections to cheaply get a deterministic `Hash` implementation. |
400 | /// *Do not* switch `BTreeMap` out for an unsorted container type! That would break | |
136023e0 XL |
401 | /// dependency tracking for command-line arguments. Also only hash keys, since tracking |
402 | /// should only depend on the output types, not the paths they're written to. | |
04454e1e | 403 | #[derive(Clone, Debug, Hash, HashStable_Generic)] |
5bcae85e SL |
404 | pub struct OutputTypes(BTreeMap<OutputType, Option<PathBuf>>); |
405 | ||
406 | impl OutputTypes { | |
407 | pub fn new(entries: &[(OutputType, Option<PathBuf>)]) -> OutputTypes { | |
dfeec247 | 408 | OutputTypes(BTreeMap::from_iter(entries.iter().map(|&(k, ref v)| (k, v.clone())))) |
5bcae85e SL |
409 | } |
410 | ||
411 | pub fn get(&self, key: &OutputType) -> Option<&Option<PathBuf>> { | |
412 | self.0.get(key) | |
413 | } | |
414 | ||
415 | pub fn contains_key(&self, key: &OutputType) -> bool { | |
416 | self.0.contains_key(key) | |
417 | } | |
418 | ||
416331ca | 419 | pub fn keys(&self) -> BTreeMapKeysIter<'_, OutputType, Option<PathBuf>> { |
5bcae85e SL |
420 | self.0.keys() |
421 | } | |
422 | ||
416331ca | 423 | pub fn values(&self) -> BTreeMapValuesIter<'_, OutputType, Option<PathBuf>> { |
5bcae85e SL |
424 | self.0.values() |
425 | } | |
32a655c1 | 426 | |
83c7162d XL |
427 | pub fn len(&self) -> usize { |
428 | self.0.len() | |
429 | } | |
430 | ||
a2a8927a | 431 | /// Returns `true` if any of the output types require codegen or linking. |
94b46f34 | 432 | pub fn should_codegen(&self) -> bool { |
32a655c1 | 433 | self.0.keys().any(|k| match *k { |
0531ce1d XL |
434 | OutputType::Bitcode |
435 | | OutputType::Assembly | |
436 | | OutputType::LlvmAssembly | |
437 | | OutputType::Mir | |
438 | | OutputType::Object | |
439 | | OutputType::Exe => true, | |
440 | OutputType::Metadata | OutputType::DepInfo => false, | |
32a655c1 SL |
441 | }) |
442 | } | |
5869c6ff | 443 | |
a2a8927a | 444 | /// Returns `true` if any of the output types require linking. |
5869c6ff XL |
445 | pub fn should_link(&self) -> bool { |
446 | self.0.keys().any(|k| match *k { | |
447 | OutputType::Bitcode | |
448 | | OutputType::Assembly | |
449 | | OutputType::LlvmAssembly | |
450 | | OutputType::Mir | |
451 | | OutputType::Metadata | |
452 | | OutputType::Object | |
453 | | OutputType::DepInfo => false, | |
454 | OutputType::Exe => true, | |
455 | }) | |
456 | } | |
5bcae85e SL |
457 | } |
458 | ||
e1599b0c XL |
459 | /// Use tree-based collections to cheaply get a deterministic `Hash` implementation. |
460 | /// *Do not* switch `BTreeMap` or `BTreeSet` out for an unsorted container type! That | |
461 | /// would break dependency tracking for command-line arguments. | |
e74abb32 | 462 | #[derive(Clone)] |
48663c56 XL |
463 | pub struct Externs(BTreeMap<String, ExternEntry>); |
464 | ||
60c5eb7d | 465 | #[derive(Clone, Debug)] |
48663c56 | 466 | pub struct ExternEntry { |
60c5eb7d XL |
467 | pub location: ExternLocation, |
468 | /// Indicates this is a "private" dependency for the | |
469 | /// `exported_private_dependencies` lint. | |
470 | /// | |
471 | /// This can be set with the `priv` option like | |
472 | /// `--extern priv:name=foo.rlib`. | |
473 | pub is_private_dep: bool, | |
474 | /// Add the extern entry to the extern prelude. | |
475 | /// | |
476 | /// This can be disabled with the `noprelude` option like | |
477 | /// `--extern noprelude:name`. | |
478 | pub add_prelude: bool, | |
04454e1e FG |
479 | /// The extern entry shouldn't be considered for unused dependency warnings. |
480 | /// | |
481 | /// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to | |
482 | /// suppress `unused-crate-dependencies` warnings. | |
483 | pub nounused_dep: bool, | |
60c5eb7d XL |
484 | } |
485 | ||
486 | #[derive(Clone, Debug)] | |
487 | pub enum ExternLocation { | |
488 | /// Indicates to look for the library in the search paths. | |
489 | /// | |
490 | /// Added via `--extern name`. | |
491 | FoundInLibrarySearchDirectories, | |
492 | /// The locations where this extern entry must be found. | |
493 | /// | |
494 | /// The `CrateLoader` is responsible for loading these and figuring out | |
495 | /// which one to use. | |
496 | /// | |
497 | /// Added via `--extern prelude_name=some_file.rlib` | |
5869c6ff | 498 | ExactPaths(BTreeSet<CanonicalizedPath>), |
48663c56 | 499 | } |
5bcae85e SL |
500 | |
501 | impl Externs { | |
cdc7bbd5 | 502 | /// Used for testing. |
48663c56 | 503 | pub fn new(data: BTreeMap<String, ExternEntry>) -> Externs { |
5bcae85e SL |
504 | Externs(data) |
505 | } | |
506 | ||
48663c56 | 507 | pub fn get(&self, key: &str) -> Option<&ExternEntry> { |
5bcae85e SL |
508 | self.0.get(key) |
509 | } | |
510 | ||
416331ca | 511 | pub fn iter(&self) -> BTreeMapIter<'_, String, ExternEntry> { |
5bcae85e SL |
512 | self.0.iter() |
513 | } | |
cdc7bbd5 XL |
514 | |
515 | pub fn len(&self) -> usize { | |
516 | self.0.len() | |
517 | } | |
1a4d82fc JJ |
518 | } |
519 | ||
60c5eb7d XL |
520 | impl ExternEntry { |
521 | fn new(location: ExternLocation) -> ExternEntry { | |
04454e1e | 522 | ExternEntry { location, is_private_dep: false, add_prelude: false, nounused_dep: false } |
60c5eb7d XL |
523 | } |
524 | ||
5869c6ff | 525 | pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> { |
60c5eb7d XL |
526 | match &self.location { |
527 | ExternLocation::ExactPaths(set) => Some(set.iter()), | |
528 | _ => None, | |
529 | } | |
530 | } | |
531 | } | |
48663c56 | 532 | |
7cac9316 | 533 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
1a4d82fc JJ |
534 | pub enum PrintRequest { |
535 | FileNames, | |
536 | Sysroot, | |
74b04a01 | 537 | TargetLibdir, |
1a4d82fc | 538 | CrateName, |
7453a54e SL |
539 | Cfg, |
540 | TargetList, | |
5bcae85e SL |
541 | TargetCPUs, |
542 | TargetFeatures, | |
543 | RelocationModels, | |
544 | CodeModels, | |
abe05a73 | 545 | TlsModels, |
476ff2be | 546 | TargetSpec, |
ea8adc8c | 547 | NativeStaticLibs, |
3c0e092e | 548 | StackProtectorStrategies, |
5099ac24 | 549 | LinkArgs, |
1a4d82fc JJ |
550 | } |
551 | ||
552 | pub enum Input { | |
e1599b0c | 553 | /// Load source code from a file. |
c34b1796 | 554 | File(PathBuf), |
e1599b0c | 555 | /// Load source code from a string. |
54a0048b | 556 | Str { |
e1599b0c | 557 | /// A string that is shown in place of a filename. |
ff7c6d11 | 558 | name: FileName, |
e1599b0c | 559 | /// An anonymous string containing the source code. |
54a0048b SL |
560 | input: String, |
561 | }, | |
1a4d82fc JJ |
562 | } |
563 | ||
564 | impl Input { | |
0bf4aa26 | 565 | pub fn filestem(&self) -> &str { |
1a4d82fc | 566 | match *self { |
0bf4aa26 XL |
567 | Input::File(ref ifile) => ifile.file_stem().unwrap().to_str().unwrap(), |
568 | Input::Str { .. } => "rust_out", | |
1a4d82fc JJ |
569 | } |
570 | } | |
94b46f34 | 571 | |
532ac7d7 XL |
572 | pub fn source_name(&self) -> FileName { |
573 | match *self { | |
574 | Input::File(ref ifile) => ifile.clone().into(), | |
575 | Input::Str { ref name, .. } => name.clone(), | |
576 | } | |
577 | } | |
1a4d82fc JJ |
578 | } |
579 | ||
04454e1e | 580 | #[derive(Clone, Hash, Debug, HashStable_Generic)] |
1a4d82fc | 581 | pub struct OutputFilenames { |
c34b1796 | 582 | pub out_directory: PathBuf, |
dfeec247 | 583 | filestem: String, |
c34b1796 | 584 | pub single_output_file: Option<PathBuf>, |
3c0e092e | 585 | pub temps_directory: Option<PathBuf>, |
5bcae85e | 586 | pub outputs: OutputTypes, |
1a4d82fc JJ |
587 | } |
588 | ||
74b04a01 | 589 | pub const RLINK_EXT: &str = "rlink"; |
abe05a73 | 590 | pub const RUST_CGU_EXT: &str = "rcgu"; |
fc512014 | 591 | pub const DWARF_OBJECT_EXT: &str = "dwo"; |
5bcae85e | 592 | |
1a4d82fc | 593 | impl OutputFilenames { |
dfeec247 XL |
594 | pub fn new( |
595 | out_directory: PathBuf, | |
596 | out_filestem: String, | |
597 | single_output_file: Option<PathBuf>, | |
3c0e092e | 598 | temps_directory: Option<PathBuf>, |
dfeec247 XL |
599 | extra: String, |
600 | outputs: OutputTypes, | |
601 | ) -> Self { | |
602 | OutputFilenames { | |
603 | out_directory, | |
604 | single_output_file, | |
3c0e092e | 605 | temps_directory, |
dfeec247 | 606 | outputs, |
5e7ed085 | 607 | filestem: format!("{out_filestem}{extra}"), |
dfeec247 XL |
608 | } |
609 | } | |
610 | ||
c34b1796 | 611 | pub fn path(&self, flavor: OutputType) -> PathBuf { |
0531ce1d XL |
612 | self.outputs |
613 | .get(&flavor) | |
614 | .and_then(|p| p.to_owned()) | |
b039eaaf | 615 | .or_else(|| self.single_output_file.clone()) |
3c0e092e XL |
616 | .unwrap_or_else(|| self.output_path(flavor)) |
617 | } | |
618 | ||
619 | /// Gets the output path where a compilation artifact of the given type | |
620 | /// should be placed on disk. | |
621 | pub fn output_path(&self, flavor: OutputType) -> PathBuf { | |
622 | let extension = flavor.extension(); | |
623 | self.with_directory_and_extension(&self.out_directory, &extension) | |
5bcae85e SL |
624 | } |
625 | ||
9fa01778 | 626 | /// Gets the path where a compilation artifact of the given type for the |
5bcae85e SL |
627 | /// given codegen unit should be placed on disk. If codegen_unit_name is |
628 | /// None, a path distinct from those of any codegen unit will be generated. | |
0531ce1d | 629 | pub fn temp_path(&self, flavor: OutputType, codegen_unit_name: Option<&str>) -> PathBuf { |
5bcae85e SL |
630 | let extension = flavor.extension(); |
631 | self.temp_path_ext(extension, codegen_unit_name) | |
1a4d82fc JJ |
632 | } |
633 | ||
fc512014 XL |
634 | /// Like `temp_path`, but specifically for dwarf objects. |
635 | pub fn temp_path_dwo(&self, codegen_unit_name: Option<&str>) -> PathBuf { | |
636 | self.temp_path_ext(DWARF_OBJECT_EXT, codegen_unit_name) | |
637 | } | |
638 | ||
639 | /// Like `temp_path`, but also supports things where there is no corresponding | |
9fa01778 | 640 | /// OutputType, like noopt-bitcode or lto-bitcode. |
0531ce1d | 641 | pub fn temp_path_ext(&self, ext: &str, codegen_unit_name: Option<&str>) -> PathBuf { |
5bcae85e SL |
642 | let mut extension = String::new(); |
643 | ||
644 | if let Some(codegen_unit_name) = codegen_unit_name { | |
ea8adc8c | 645 | extension.push_str(codegen_unit_name); |
1a4d82fc | 646 | } |
5bcae85e SL |
647 | |
648 | if !ext.is_empty() { | |
649 | if !extension.is_empty() { | |
1b1a35ee | 650 | extension.push('.'); |
ea8adc8c | 651 | extension.push_str(RUST_CGU_EXT); |
1b1a35ee | 652 | extension.push('.'); |
5bcae85e SL |
653 | } |
654 | ||
655 | extension.push_str(ext); | |
656 | } | |
657 | ||
3c0e092e XL |
658 | let temps_directory = self.temps_directory.as_ref().unwrap_or(&self.out_directory); |
659 | ||
660 | self.with_directory_and_extension(&temps_directory, &extension) | |
1a4d82fc JJ |
661 | } |
662 | ||
c34b1796 | 663 | pub fn with_extension(&self, extension: &str) -> PathBuf { |
3c0e092e XL |
664 | self.with_directory_and_extension(&self.out_directory, extension) |
665 | } | |
666 | ||
667 | fn with_directory_and_extension(&self, directory: &PathBuf, extension: &str) -> PathBuf { | |
668 | let mut path = directory.join(&self.filestem); | |
dfeec247 XL |
669 | path.set_extension(extension); |
670 | path | |
1a4d82fc | 671 | } |
fc512014 | 672 | |
fc512014 XL |
673 | /// Returns the path for the Split DWARF file - this can differ depending on which Split DWARF |
674 | /// mode is being used, which is the logic that this function is intended to encapsulate. | |
675 | pub fn split_dwarf_path( | |
676 | &self, | |
5869c6ff | 677 | split_debuginfo_kind: SplitDebuginfo, |
a2a8927a | 678 | split_dwarf_kind: SplitDwarfKind, |
fc512014 XL |
679 | cgu_name: Option<&str>, |
680 | ) -> Option<PathBuf> { | |
681 | let obj_out = self.temp_path(OutputType::Object, cgu_name); | |
682 | let dwo_out = self.temp_path_dwo(cgu_name); | |
a2a8927a XL |
683 | match (split_debuginfo_kind, split_dwarf_kind) { |
684 | (SplitDebuginfo::Off, SplitDwarfKind::Single | SplitDwarfKind::Split) => None, | |
fc512014 XL |
685 | // Single mode doesn't change how DWARF is emitted, but does add Split DWARF attributes |
686 | // (pointing at the path which is being determined here). Use the path to the current | |
687 | // object file. | |
a2a8927a XL |
688 | (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Single) => { |
689 | Some(obj_out) | |
690 | } | |
fc512014 | 691 | // Split mode emits the DWARF into a different file, use that path. |
a2a8927a XL |
692 | (SplitDebuginfo::Packed | SplitDebuginfo::Unpacked, SplitDwarfKind::Split) => { |
693 | Some(dwo_out) | |
694 | } | |
fc512014 XL |
695 | } |
696 | } | |
1a4d82fc JJ |
697 | } |
698 | ||
699 | pub fn host_triple() -> &'static str { | |
700 | // Get the host triple out of the build environment. This ensures that our | |
701 | // idea of the host triple is the same as for the set of libraries we've | |
702 | // actually built. We can't just take LLVM's host triple because they | |
703 | // normalize all ix86 architectures to i386. | |
704 | // | |
705 | // Instead of grabbing the host triple (for the current host), we grab (at | |
706 | // compile time) the target triple that this rustc is built with and | |
707 | // calling that (at runtime) the host triple. | |
0531ce1d | 708 | (option_env!("CFG_COMPILER_HOST_TRIPLE")).expect("CFG_COMPILER_HOST_TRIPLE") |
1a4d82fc JJ |
709 | } |
710 | ||
b7449926 XL |
711 | impl Default for Options { |
712 | fn default() -> Options { | |
713 | Options { | |
3c0e092e | 714 | assert_incr_state: None, |
b7449926 XL |
715 | crate_types: Vec::new(), |
716 | optimize: OptLevel::No, | |
717 | debuginfo: DebugInfo::None, | |
718 | lint_opts: Vec::new(), | |
719 | lint_cap: None, | |
720 | describe_lints: false, | |
721 | output_types: OutputTypes(BTreeMap::new()), | |
0731742a | 722 | search_paths: vec![], |
b7449926 XL |
723 | maybe_sysroot: None, |
724 | target_triple: TargetTriple::from_triple(host_triple()), | |
725 | test: false, | |
726 | incremental: None, | |
064997fb | 727 | unstable_opts: Default::default(), |
b7449926 | 728 | prints: Vec::new(), |
17df50a5 | 729 | cg: Default::default(), |
b7449926 | 730 | error_format: ErrorOutputType::default(), |
064997fb | 731 | diagnostic_width: None, |
b7449926 XL |
732 | externs: Externs(BTreeMap::new()), |
733 | crate_name: None, | |
b7449926 XL |
734 | libs: Vec::new(), |
735 | unstable_features: UnstableFeatures::Disallow, | |
736 | debug_assertions: true, | |
737 | actually_rustdoc: false, | |
1b1a35ee | 738 | trimmed_def_paths: TrimmedDefPaths::default(), |
b7449926 XL |
739 | cli_forced_codegen_units: None, |
740 | cli_forced_thinlto_off: false, | |
741 | remap_path_prefix: Vec::new(), | |
cdc7bbd5 | 742 | real_rust_source_base_dir: None, |
b7449926 | 743 | edition: DEFAULT_EDITION, |
416331ca | 744 | json_artifact_notifications: false, |
04454e1e | 745 | json_unused_externs: JsonUnusedExterns::No, |
a2a8927a | 746 | json_future_incompat: false, |
60c5eb7d | 747 | pretty: None, |
94222f64 | 748 | working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()), |
b7449926 | 749 | } |
1a4d82fc JJ |
750 | } |
751 | } | |
752 | ||
54a0048b | 753 | impl Options { |
9fa01778 | 754 | /// Returns `true` if there is a reason to build the dep graph. |
54a0048b | 755 | pub fn build_dep_graph(&self) -> bool { |
dfeec247 | 756 | self.incremental.is_some() |
064997fb FG |
757 | || self.unstable_opts.dump_dep_graph |
758 | || self.unstable_opts.query_dep_graph | |
54a0048b | 759 | } |
5bcae85e | 760 | |
7cac9316 | 761 | pub fn file_path_mapping(&self) -> FilePathMapping { |
0531ce1d | 762 | FilePathMapping::new(self.remap_path_prefix.clone()) |
7cac9316 | 763 | } |
ff7c6d11 | 764 | |
e1599b0c | 765 | /// Returns `true` if there will be an output file generated. |
ff7c6d11 | 766 | pub fn will_create_output_file(&self) -> bool { |
064997fb FG |
767 | !self.unstable_opts.parse_only && // The file is just being parsed |
768 | !self.unstable_opts.ls // The file is just being queried | |
ff7c6d11 | 769 | } |
b7449926 XL |
770 | |
771 | #[inline] | |
772 | pub fn share_generics(&self) -> bool { | |
064997fb | 773 | match self.unstable_opts.share_generics { |
b7449926 | 774 | Some(setting) => setting, |
dfeec247 XL |
775 | None => match self.optimize { |
776 | OptLevel::No | OptLevel::Less | OptLevel::Size | OptLevel::SizeMin => true, | |
777 | OptLevel::Default | OptLevel::Aggressive => false, | |
778 | }, | |
779 | } | |
780 | } | |
a2a8927a XL |
781 | |
782 | pub fn get_symbol_mangling_version(&self) -> SymbolManglingVersion { | |
783 | self.cg.symbol_mangling_version.unwrap_or(SymbolManglingVersion::Legacy) | |
784 | } | |
dfeec247 XL |
785 | } |
786 | ||
064997fb | 787 | impl UnstableOptions { |
dfeec247 XL |
788 | pub fn diagnostic_handler_flags(&self, can_emit_warnings: bool) -> HandlerFlags { |
789 | HandlerFlags { | |
790 | can_emit_warnings, | |
791 | treat_err_as_bug: self.treat_err_as_bug, | |
792 | dont_buffer_diagnostics: self.dont_buffer_diagnostics, | |
793 | report_delayed_bugs: self.report_delayed_bugs, | |
74b04a01 | 794 | macro_backtrace: self.macro_backtrace, |
ba9703b0 | 795 | deduplicate_diagnostics: self.deduplicate_diagnostics, |
b7449926 XL |
796 | } |
797 | } | |
54a0048b SL |
798 | } |
799 | ||
9fa01778 | 800 | // The type of entry function, so users can have their own entry functions |
04454e1e | 801 | #[derive(Copy, Clone, PartialEq, Hash, Debug, HashStable_Generic)] |
1a4d82fc | 802 | pub enum EntryFnType { |
f2b60f7d FG |
803 | Main { |
804 | /// Specifies what to do with `SIGPIPE` before calling `fn main()`. | |
805 | /// | |
806 | /// What values that are valid and what they mean must be in sync | |
807 | /// across rustc and libstd, but we don't want it public in libstd, | |
808 | /// so we take a bit of an unusual approach with simple constants | |
809 | /// and an `include!()`. | |
810 | sigpipe: u8, | |
811 | }, | |
b7449926 | 812 | Start, |
1a4d82fc JJ |
813 | } |
814 | ||
3dfed10e | 815 | #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug, Encodable, Decodable)] |
04454e1e | 816 | #[derive(HashStable_Generic)] |
1a4d82fc | 817 | pub enum CrateType { |
b7449926 XL |
818 | Executable, |
819 | Dylib, | |
820 | Rlib, | |
821 | Staticlib, | |
822 | Cdylib, | |
823 | ProcMacro, | |
1a4d82fc JJ |
824 | } |
825 | ||
a2a8927a XL |
826 | impl CrateType { |
827 | /// When generated, is this crate type an archive? | |
828 | pub fn is_archive(&self) -> bool { | |
829 | match *self { | |
830 | CrateType::Rlib | CrateType::Staticlib => true, | |
831 | CrateType::Executable | CrateType::Dylib | CrateType::Cdylib | CrateType::ProcMacro => { | |
832 | false | |
833 | } | |
834 | } | |
835 | } | |
836 | } | |
837 | ||
cdc7bbd5 | 838 | #[derive(Clone, Hash, Debug, PartialEq, Eq)] |
1a4d82fc | 839 | pub enum Passes { |
b7449926 XL |
840 | Some(Vec<String>), |
841 | All, | |
1a4d82fc JJ |
842 | } |
843 | ||
844 | impl Passes { | |
845 | pub fn is_empty(&self) -> bool { | |
846 | match *self { | |
b7449926 XL |
847 | Passes::Some(ref v) => v.is_empty(), |
848 | Passes::All => false, | |
1a4d82fc JJ |
849 | } |
850 | } | |
a2a8927a XL |
851 | |
852 | pub fn extend(&mut self, passes: impl IntoIterator<Item = String>) { | |
853 | match *self { | |
854 | Passes::Some(ref mut v) => v.extend(passes), | |
855 | Passes::All => {} | |
856 | } | |
857 | } | |
1a4d82fc JJ |
858 | } |
859 | ||
5099ac24 FG |
860 | #[derive(Clone, Copy, Hash, Debug, PartialEq)] |
861 | pub enum PAuthKey { | |
862 | A, | |
863 | B, | |
864 | } | |
865 | ||
866 | #[derive(Clone, Copy, Hash, Debug, PartialEq)] | |
867 | pub struct PacRet { | |
868 | pub leaf: bool, | |
869 | pub key: PAuthKey, | |
870 | } | |
871 | ||
872 | #[derive(Clone, Copy, Hash, Debug, PartialEq)] | |
873 | pub struct BranchProtection { | |
874 | pub bti: bool, | |
875 | pub pac_ret: Option<PacRet>, | |
876 | } | |
877 | ||
878 | impl Default for BranchProtection { | |
879 | fn default() -> Self { | |
880 | BranchProtection { bti: false, pac_ret: None } | |
881 | } | |
882 | } | |
883 | ||
e74abb32 | 884 | pub const fn default_lib_output() -> CrateType { |
b7449926 | 885 | CrateType::Rlib |
1a4d82fc JJ |
886 | } |
887 | ||
cdc7bbd5 | 888 | fn default_configuration(sess: &Session) -> CrateConfig { |
5099ac24 | 889 | // NOTE: This should be kept in sync with `CrateCheckConfig::fill_well_known` below. |
29967ef6 XL |
890 | let end = &sess.target.endian; |
891 | let arch = &sess.target.arch; | |
892 | let wordsz = sess.target.pointer_width.to_string(); | |
893 | let os = &sess.target.os; | |
894 | let env = &sess.target.env; | |
136023e0 | 895 | let abi = &sess.target.abi; |
29967ef6 XL |
896 | let vendor = &sess.target.vendor; |
897 | let min_atomic_width = sess.target.min_atomic_width(); | |
898 | let max_atomic_width = sess.target.max_atomic_width(); | |
899 | let atomic_cas = sess.target.atomic_cas; | |
900 | let layout = TargetDataLayout::parse(&sess.target).unwrap_or_else(|err| { | |
f2b60f7d | 901 | sess.emit_fatal(err); |
1b1a35ee | 902 | }); |
1a4d82fc | 903 | |
f2b60f7d | 904 | let mut ret = CrateConfig::default(); |
136023e0 | 905 | ret.reserve(7); // the minimum number of insertions |
476ff2be | 906 | // Target bindings. |
3dfed10e | 907 | ret.insert((sym::target_os, Some(Symbol::intern(os)))); |
5e7ed085 | 908 | for fam in sess.target.families.as_ref() { |
3dfed10e XL |
909 | ret.insert((sym::target_family, Some(Symbol::intern(fam)))); |
910 | if fam == "windows" { | |
911 | ret.insert((sym::windows, None)); | |
912 | } else if fam == "unix" { | |
913 | ret.insert((sym::unix, None)); | |
32a655c1 SL |
914 | } |
915 | } | |
3dfed10e | 916 | ret.insert((sym::target_arch, Some(Symbol::intern(arch)))); |
5869c6ff | 917 | ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str())))); |
29967ef6 | 918 | ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz)))); |
3dfed10e | 919 | ret.insert((sym::target_env, Some(Symbol::intern(env)))); |
136023e0 | 920 | ret.insert((sym::target_abi, Some(Symbol::intern(abi)))); |
3dfed10e | 921 | ret.insert((sym::target_vendor, Some(Symbol::intern(vendor)))); |
a2a8927a | 922 | if sess.target.has_thread_local { |
dc9dc135 | 923 | ret.insert((sym::target_thread_local, None)); |
9cc50fc6 | 924 | } |
136023e0 | 925 | for (i, align) in [ |
1b1a35ee XL |
926 | (8, layout.i8_align.abi), |
927 | (16, layout.i16_align.abi), | |
928 | (32, layout.i32_align.abi), | |
929 | (64, layout.i64_align.abi), | |
930 | (128, layout.i128_align.abi), | |
931 | ] { | |
32a655c1 | 932 | if i >= min_atomic_width && i <= max_atomic_width { |
1b1a35ee | 933 | let mut insert_atomic = |s, align: Align| { |
dfeec247 | 934 | ret.insert((sym::target_has_atomic_load_store, Some(Symbol::intern(s)))); |
e74abb32 | 935 | if atomic_cas { |
dfeec247 | 936 | ret.insert((sym::target_has_atomic, Some(Symbol::intern(s)))); |
e74abb32 | 937 | } |
1b1a35ee XL |
938 | if align.bits() == i { |
939 | ret.insert((sym::target_has_atomic_equal_alignment, Some(Symbol::intern(s)))); | |
940 | } | |
e74abb32 XL |
941 | }; |
942 | let s = i.to_string(); | |
1b1a35ee | 943 | insert_atomic(&s, align); |
29967ef6 | 944 | if s == wordsz { |
1b1a35ee | 945 | insert_atomic("ptr", layout.pointer_align.abi); |
a7813a04 XL |
946 | } |
947 | } | |
948 | } | |
f035d41b | 949 | |
29967ef6 XL |
950 | let panic_strategy = sess.panic_strategy(); |
951 | ret.insert((sym::panic, Some(panic_strategy.desc_symbol()))); | |
952 | ||
064997fb | 953 | for s in sess.opts.unstable_opts.sanitizer { |
60c5eb7d XL |
954 | let symbol = Symbol::intern(&s.to_string()); |
955 | ret.insert((sym::sanitize, Some(symbol))); | |
956 | } | |
f035d41b | 957 | |
c34b1796 | 958 | if sess.opts.debug_assertions { |
3dfed10e | 959 | ret.insert((sym::debug_assertions, None)); |
c34b1796 | 960 | } |
064997fb | 961 | // JUSTIFICATION: before wrapper fn is available |
f2b60f7d | 962 | #[allow(rustc::bad_opt_access)] |
b7449926 | 963 | if sess.opts.crate_types.contains(&CrateType::ProcMacro) { |
dc9dc135 | 964 | ret.insert((sym::proc_macro, None)); |
9e0c209e | 965 | } |
0bf4aa26 | 966 | ret |
1a4d82fc JJ |
967 | } |
968 | ||
e1599b0c | 969 | /// Converts the crate `cfg!` configuration from `String` to `Symbol`. |
532ac7d7 XL |
970 | /// `rustc_interface::interface::Config` accepts this in the compiler configuration, |
971 | /// but the symbol interner is not yet set up then, so we must convert it later. | |
60c5eb7d | 972 | pub fn to_crate_config(cfg: FxHashSet<(String, Option<String>)>) -> CrateConfig { |
dfeec247 | 973 | cfg.into_iter().map(|(a, b)| (Symbol::intern(&a), b.map(|b| Symbol::intern(&b)))).collect() |
532ac7d7 XL |
974 | } |
975 | ||
5099ac24 FG |
976 | /// The parsed `--check-cfg` options |
977 | pub struct CheckCfg<T = String> { | |
5e7ed085 FG |
978 | /// The set of all `names()`, if None no name checking is performed |
979 | pub names_valid: Option<FxHashSet<T>>, | |
980 | /// Is well known values activated | |
981 | pub well_known_values: bool, | |
982 | /// The set of all `values()` | |
983 | pub values_valid: FxHashMap<T, FxHashSet<T>>, | |
5099ac24 FG |
984 | } |
985 | ||
986 | impl<T> Default for CheckCfg<T> { | |
987 | fn default() -> Self { | |
988 | CheckCfg { | |
5e7ed085 FG |
989 | names_valid: Default::default(), |
990 | values_valid: Default::default(), | |
991 | well_known_values: false, | |
5099ac24 FG |
992 | } |
993 | } | |
994 | } | |
995 | ||
996 | impl<T> CheckCfg<T> { | |
997 | fn map_data<O: Eq + Hash>(&self, f: impl Fn(&T) -> O) -> CheckCfg<O> { | |
998 | CheckCfg { | |
5e7ed085 FG |
999 | names_valid: self |
1000 | .names_valid | |
1001 | .as_ref() | |
1002 | .map(|names_valid| names_valid.iter().map(|a| f(a)).collect()), | |
1003 | values_valid: self | |
1004 | .values_valid | |
1005 | .iter() | |
1006 | .map(|(a, b)| (f(a), b.iter().map(|b| f(b)).collect())) | |
1007 | .collect(), | |
1008 | well_known_values: self.well_known_values, | |
5099ac24 FG |
1009 | } |
1010 | } | |
1011 | } | |
1012 | ||
1013 | /// Converts the crate `--check-cfg` options from `String` to `Symbol`. | |
1014 | /// `rustc_interface::interface::Config` accepts this in the compiler configuration, | |
1015 | /// but the symbol interner is not yet set up then, so we must convert it later. | |
1016 | pub fn to_crate_check_config(cfg: CheckCfg) -> CrateCheckConfig { | |
1017 | cfg.map_data(|s| Symbol::intern(s)) | |
1018 | } | |
1019 | ||
1020 | impl CrateCheckConfig { | |
1021 | /// Fills a `CrateCheckConfig` with well-known configuration names. | |
5e7ed085 FG |
1022 | fn fill_well_known_names(&mut self) { |
1023 | // NOTE: This should be kept in sync with `default_configuration` and | |
1024 | // `fill_well_known_values` | |
5099ac24 | 1025 | const WELL_KNOWN_NAMES: &[Symbol] = &[ |
5e7ed085 | 1026 | // rustc |
5099ac24 FG |
1027 | sym::unix, |
1028 | sym::windows, | |
1029 | sym::target_os, | |
1030 | sym::target_family, | |
1031 | sym::target_arch, | |
1032 | sym::target_endian, | |
1033 | sym::target_pointer_width, | |
1034 | sym::target_env, | |
1035 | sym::target_abi, | |
1036 | sym::target_vendor, | |
1037 | sym::target_thread_local, | |
1038 | sym::target_has_atomic_load_store, | |
1039 | sym::target_has_atomic, | |
1040 | sym::target_has_atomic_equal_alignment, | |
04454e1e | 1041 | sym::target_feature, |
5099ac24 FG |
1042 | sym::panic, |
1043 | sym::sanitize, | |
1044 | sym::debug_assertions, | |
1045 | sym::proc_macro, | |
1046 | sym::test, | |
5e7ed085 FG |
1047 | sym::feature, |
1048 | // rustdoc | |
5099ac24 FG |
1049 | sym::doc, |
1050 | sym::doctest, | |
5e7ed085 FG |
1051 | // miri |
1052 | sym::miri, | |
5099ac24 | 1053 | ]; |
5e7ed085 FG |
1054 | |
1055 | // We only insert well-known names if `names()` was activated | |
1056 | if let Some(names_valid) = &mut self.names_valid { | |
1057 | names_valid.extend(WELL_KNOWN_NAMES); | |
5099ac24 FG |
1058 | } |
1059 | } | |
1060 | ||
5e7ed085 FG |
1061 | /// Fills a `CrateCheckConfig` with well-known configuration values. |
1062 | fn fill_well_known_values(&mut self) { | |
1063 | if !self.well_known_values { | |
1064 | return; | |
1065 | } | |
1066 | ||
1067 | // NOTE: This should be kept in sync with `default_configuration` and | |
1068 | // `fill_well_known_names` | |
1069 | ||
1070 | let panic_values = &PanicStrategy::all(); | |
1071 | ||
1072 | let atomic_values = &[ | |
1073 | sym::ptr, | |
1074 | sym::integer(8usize), | |
1075 | sym::integer(16usize), | |
1076 | sym::integer(32usize), | |
1077 | sym::integer(64usize), | |
1078 | sym::integer(128usize), | |
1079 | ]; | |
1080 | ||
1081 | let sanitize_values = SanitizerSet::all() | |
1082 | .into_iter() | |
1083 | .map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap())); | |
1084 | ||
04454e1e FG |
1085 | // Unknown possible values: |
1086 | // - `feature` | |
1087 | // - `target_feature` | |
1088 | ||
5e7ed085 FG |
1089 | // No-values |
1090 | for name in [ | |
1091 | sym::doc, | |
1092 | sym::miri, | |
1093 | sym::unix, | |
1094 | sym::test, | |
1095 | sym::doctest, | |
1096 | sym::windows, | |
1097 | sym::proc_macro, | |
1098 | sym::debug_assertions, | |
1099 | sym::target_thread_local, | |
1100 | ] { | |
1101 | self.values_valid.entry(name).or_default(); | |
1102 | } | |
1103 | ||
1104 | // Pre-defined values | |
1105 | self.values_valid.entry(sym::panic).or_default().extend(panic_values); | |
1106 | self.values_valid.entry(sym::sanitize).or_default().extend(sanitize_values); | |
1107 | self.values_valid.entry(sym::target_has_atomic).or_default().extend(atomic_values); | |
1108 | self.values_valid | |
1109 | .entry(sym::target_has_atomic_load_store) | |
1110 | .or_default() | |
1111 | .extend(atomic_values); | |
1112 | self.values_valid | |
1113 | .entry(sym::target_has_atomic_equal_alignment) | |
1114 | .or_default() | |
1115 | .extend(atomic_values); | |
1116 | ||
1117 | // Target specific values | |
5e7ed085 | 1118 | { |
923072b8 FG |
1119 | const VALUES: [&Symbol; 8] = [ |
1120 | &sym::target_os, | |
1121 | &sym::target_family, | |
1122 | &sym::target_arch, | |
1123 | &sym::target_endian, | |
1124 | &sym::target_env, | |
1125 | &sym::target_abi, | |
1126 | &sym::target_vendor, | |
1127 | &sym::target_pointer_width, | |
1128 | ]; | |
1129 | ||
1130 | // Initialize (if not already initialized) | |
1131 | for &e in VALUES { | |
1132 | self.values_valid.entry(e).or_default(); | |
1133 | } | |
1134 | ||
1135 | // Get all values map at once otherwise it would be costly. | |
1136 | // (8 values * 220 targets ~= 1760 times, at the time of writing this comment). | |
1137 | let [ | |
1138 | values_target_os, | |
1139 | values_target_family, | |
1140 | values_target_arch, | |
1141 | values_target_endian, | |
1142 | values_target_env, | |
1143 | values_target_abi, | |
1144 | values_target_vendor, | |
1145 | values_target_pointer_width, | |
1146 | ] = self | |
1147 | .values_valid | |
1148 | .get_many_mut(VALUES) | |
1149 | .expect("unable to get all the check-cfg values buckets"); | |
1150 | ||
1151 | for target in TARGETS | |
1152 | .iter() | |
1153 | .map(|target| Target::expect_builtin(&TargetTriple::from_triple(target))) | |
1154 | { | |
1155 | values_target_os.insert(Symbol::intern(&target.options.os)); | |
1156 | values_target_family | |
1157 | .extend(target.options.families.iter().map(|family| Symbol::intern(family))); | |
1158 | values_target_arch.insert(Symbol::intern(&target.arch)); | |
1159 | values_target_endian.insert(Symbol::intern(&target.options.endian.as_str())); | |
1160 | values_target_env.insert(Symbol::intern(&target.options.env)); | |
1161 | values_target_abi.insert(Symbol::intern(&target.options.abi)); | |
1162 | values_target_vendor.insert(Symbol::intern(&target.options.vendor)); | |
1163 | values_target_pointer_width.insert(sym::integer(target.pointer_width)); | |
1164 | } | |
5e7ed085 FG |
1165 | } |
1166 | } | |
1167 | ||
1168 | pub fn fill_well_known(&mut self) { | |
1169 | self.fill_well_known_names(); | |
1170 | self.fill_well_known_values(); | |
1171 | } | |
5099ac24 FG |
1172 | } |
1173 | ||
60c5eb7d | 1174 | pub fn build_configuration(sess: &Session, mut user_cfg: CrateConfig) -> CrateConfig { |
1a4d82fc | 1175 | // Combine the configuration requested by the session (command line) with |
e1599b0c | 1176 | // some default and generated configuration items. |
1a4d82fc | 1177 | let default_cfg = default_configuration(sess); |
e1599b0c | 1178 | // If the user wants a test runner, then add the test cfg. |
1a4d82fc | 1179 | if sess.opts.test { |
dc9dc135 | 1180 | user_cfg.insert((sym::test, None)); |
1a4d82fc | 1181 | } |
476ff2be SL |
1182 | user_cfg.extend(default_cfg.iter().cloned()); |
1183 | user_cfg | |
1a4d82fc JJ |
1184 | } |
1185 | ||
17df50a5 XL |
1186 | pub(super) fn build_target_config( |
1187 | opts: &Options, | |
1188 | target_override: Option<Target>, | |
3c0e092e | 1189 | sysroot: &Path, |
17df50a5 | 1190 | ) -> Target { |
136023e0 XL |
1191 | let target_result = target_override.map_or_else( |
1192 | || Target::search(&opts.target_triple, sysroot), | |
1193 | |t| Ok((t, TargetWarnings::empty())), | |
1194 | ); | |
1195 | let (target, target_warnings) = target_result.unwrap_or_else(|e| { | |
ba9703b0 | 1196 | early_error( |
1b1a35ee | 1197 | opts.error_format, |
ba9703b0 XL |
1198 | &format!( |
1199 | "Error loading target specification: {}. \ | |
cdc7bbd5 | 1200 | Run `rustc --print target-list` for a list of built-in targets", |
ba9703b0 XL |
1201 | e |
1202 | ), | |
1203 | ) | |
0bf4aa26 | 1204 | }); |
136023e0 XL |
1205 | for warning in target_warnings.warning_messages() { |
1206 | early_warn(opts.error_format, &warning) | |
1207 | } | |
1a4d82fc | 1208 | |
29967ef6 XL |
1209 | if !matches!(target.pointer_width, 16 | 32 | 64) { |
1210 | early_error( | |
1b1a35ee | 1211 | opts.error_format, |
ba9703b0 | 1212 | &format!( |
dfeec247 | 1213 | "target specification was invalid: \ |
0531ce1d | 1214 | unrecognized target-pointer-width {}", |
29967ef6 | 1215 | target.pointer_width |
ba9703b0 | 1216 | ), |
29967ef6 XL |
1217 | ) |
1218 | } | |
1a4d82fc | 1219 | |
29967ef6 | 1220 | target |
1a4d82fc JJ |
1221 | } |
1222 | ||
85aaf69f | 1223 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
7453a54e SL |
1224 | pub enum OptionStability { |
1225 | Stable, | |
7453a54e SL |
1226 | Unstable, |
1227 | } | |
1a4d82fc | 1228 | |
1a4d82fc | 1229 | pub struct RustcOptGroup { |
0531ce1d | 1230 | pub apply: Box<dyn Fn(&mut getopts::Options) -> &mut getopts::Options>, |
041b39d2 | 1231 | pub name: &'static str, |
1a4d82fc JJ |
1232 | pub stability: OptionStability, |
1233 | } | |
1234 | ||
1235 | impl RustcOptGroup { | |
1236 | pub fn is_stable(&self) -> bool { | |
1237 | self.stability == OptionStability::Stable | |
1238 | } | |
1239 | ||
041b39d2 | 1240 | pub fn stable<F>(name: &'static str, f: F) -> RustcOptGroup |
0531ce1d XL |
1241 | where |
1242 | F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, | |
041b39d2 | 1243 | { |
dfeec247 | 1244 | RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Stable } |
1a4d82fc JJ |
1245 | } |
1246 | ||
041b39d2 | 1247 | pub fn unstable<F>(name: &'static str, f: F) -> RustcOptGroup |
0531ce1d XL |
1248 | where |
1249 | F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, | |
041b39d2 | 1250 | { |
dfeec247 | 1251 | RustcOptGroup { name, apply: Box::new(f), stability: OptionStability::Unstable } |
1a4d82fc JJ |
1252 | } |
1253 | } | |
1254 | ||
1255 | // The `opt` local module holds wrappers around the `getopts` API that | |
1256 | // adds extra rustc-specific metadata to each option; such metadata | |
1257 | // is exposed by . The public | |
1258 | // functions below ending with `_u` are the functions that return | |
0731742a | 1259 | // *unstable* options, i.e., options that are only enabled when the |
1a4d82fc JJ |
1260 | // user also passes the `-Z unstable-options` debugging flag. |
1261 | mod opt { | |
416331ca | 1262 | // The `fn flag*` etc below are written so that we can use them |
1a4d82fc JJ |
1263 | // in the future; do not warn about them not being used right now. |
1264 | #![allow(dead_code)] | |
1265 | ||
1a4d82fc JJ |
1266 | use super::RustcOptGroup; |
1267 | ||
c34b1796 | 1268 | pub type R = RustcOptGroup; |
041b39d2 XL |
1269 | pub type S = &'static str; |
1270 | ||
1271 | fn stable<F>(name: S, f: F) -> R | |
0531ce1d XL |
1272 | where |
1273 | F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, | |
041b39d2 XL |
1274 | { |
1275 | RustcOptGroup::stable(name, f) | |
1276 | } | |
1277 | ||
1278 | fn unstable<F>(name: S, f: F) -> R | |
0531ce1d XL |
1279 | where |
1280 | F: Fn(&mut getopts::Options) -> &mut getopts::Options + 'static, | |
041b39d2 XL |
1281 | { |
1282 | RustcOptGroup::unstable(name, f) | |
1283 | } | |
1a4d82fc | 1284 | |
041b39d2 | 1285 | fn longer(a: S, b: S) -> S { |
dfeec247 | 1286 | if a.len() > b.len() { a } else { b } |
041b39d2 | 1287 | } |
1a4d82fc | 1288 | |
7453a54e | 1289 | pub fn opt_s(a: S, b: S, c: S, d: S) -> R { |
041b39d2 | 1290 | stable(longer(a, b), move |opts| opts.optopt(a, b, c, d)) |
7453a54e SL |
1291 | } |
1292 | pub fn multi_s(a: S, b: S, c: S, d: S) -> R { | |
041b39d2 | 1293 | stable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) |
7453a54e SL |
1294 | } |
1295 | pub fn flag_s(a: S, b: S, c: S) -> R { | |
041b39d2 | 1296 | stable(longer(a, b), move |opts| opts.optflag(a, b, c)) |
7453a54e | 1297 | } |
7453a54e | 1298 | pub fn flagmulti_s(a: S, b: S, c: S) -> R { |
041b39d2 | 1299 | stable(longer(a, b), move |opts| opts.optflagmulti(a, b, c)) |
7453a54e | 1300 | } |
d9579d0f | 1301 | |
7453a54e | 1302 | pub fn opt(a: S, b: S, c: S, d: S) -> R { |
041b39d2 | 1303 | unstable(longer(a, b), move |opts| opts.optopt(a, b, c, d)) |
7453a54e SL |
1304 | } |
1305 | pub fn multi(a: S, b: S, c: S, d: S) -> R { | |
041b39d2 | 1306 | unstable(longer(a, b), move |opts| opts.optmulti(a, b, c, d)) |
7453a54e | 1307 | } |
1a4d82fc JJ |
1308 | } |
1309 | ||
1310 | /// Returns the "short" subset of the rustc command line options, | |
1311 | /// including metadata for each option, such as whether the option is | |
1312 | /// part of the stable long-term interface for rustc. | |
1313 | pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> { | |
1314 | vec![ | |
7453a54e SL |
1315 | opt::flag_s("h", "help", "Display this message"), |
1316 | opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"), | |
5099ac24 | 1317 | opt::multi("", "check-cfg", "Provide list of valid cfg options for checking", "SPEC"), |
0531ce1d XL |
1318 | opt::multi_s( |
1319 | "L", | |
1320 | "", | |
1321 | "Add a directory to the library search path. The | |
a7813a04 | 1322 | optional KIND can be one of dependency, crate, native, |
416331ca | 1323 | framework, or all (the default).", |
0531ce1d XL |
1324 | "[KIND=]PATH", |
1325 | ), | |
1326 | opt::multi_s( | |
1327 | "l", | |
1328 | "", | |
1329 | "Link the generated crate(s) to the specified native | |
a7813a04 | 1330 | library NAME. The optional KIND can be one of |
17df50a5 XL |
1331 | static, framework, or dylib (the default). |
1332 | Optional comma separated MODIFIERS (bundle|verbatim|whole-archive|as-needed) | |
1333 | may be specified each with a prefix of either '+' to | |
1334 | enable or '-' to disable.", | |
1335 | "[KIND[:MODIFIERS]=]NAME[:RENAME]", | |
0531ce1d | 1336 | ), |
e1599b0c | 1337 | make_crate_type_option(), |
dfeec247 | 1338 | opt::opt_s("", "crate-name", "Specify the name of the crate being built", "NAME"), |
532ac7d7 XL |
1339 | opt::opt_s( |
1340 | "", | |
1341 | "edition", | |
1342 | "Specify which edition of the compiler to use when compiling code.", | |
1343 | EDITION_NAME_LIST, | |
1344 | ), | |
0531ce1d XL |
1345 | opt::multi_s( |
1346 | "", | |
1347 | "emit", | |
1348 | "Comma separated list of types of output for \ | |
1349 | the compiler to emit", | |
1350 | "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info|mir]", | |
1351 | ), | |
1352 | opt::multi_s( | |
1353 | "", | |
1354 | "print", | |
48663c56 | 1355 | "Compiler information to print on stdout", |
74b04a01 | 1356 | "[crate-name|file-names|sysroot|target-libdir|cfg|target-list|\ |
3c0e092e | 1357 | target-cpus|target-features|relocation-models|code-models|\ |
5099ac24 FG |
1358 | tls-models|target-spec-json|native-static-libs|stack-protector-strategies|\ |
1359 | link-args]", | |
0531ce1d XL |
1360 | ), |
1361 | opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), | |
7453a54e SL |
1362 | opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), |
1363 | opt::opt_s("o", "", "Write output to <filename>", "FILENAME"), | |
0531ce1d XL |
1364 | opt::opt_s( |
1365 | "", | |
1366 | "out-dir", | |
1367 | "Write output to compiler-chosen filename \ | |
1368 | in <dir>", | |
1369 | "DIR", | |
1370 | ), | |
1371 | opt::opt_s( | |
1372 | "", | |
1373 | "explain", | |
1374 | "Provide a detailed explanation of an error \ | |
1375 | message", | |
1376 | "OPT", | |
1377 | ), | |
7453a54e | 1378 | opt::flag_s("", "test", "Build a test harness"), |
dfeec247 | 1379 | opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"), |
94222f64 XL |
1380 | opt::multi_s("A", "allow", "Set lint allowed", "LINT"), |
1381 | opt::multi_s("W", "warn", "Set lint warnings", "LINT"), | |
1382 | opt::multi_s("", "force-warn", "Set lint force-warn", "LINT"), | |
1383 | opt::multi_s("D", "deny", "Set lint denied", "LINT"), | |
1384 | opt::multi_s("F", "forbid", "Set lint forbidden", "LINT"), | |
0531ce1d XL |
1385 | opt::multi_s( |
1386 | "", | |
1387 | "cap-lints", | |
1388 | "Set the most restrictive lint level. \ | |
1389 | More restrictive lints are capped at this \ | |
1390 | level", | |
1391 | "LEVEL", | |
1392 | ), | |
7453a54e SL |
1393 | opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"), |
1394 | opt::flag_s("V", "version", "Print version info and exit"), | |
1395 | opt::flag_s("v", "verbose", "Use verbose output"), | |
1a4d82fc JJ |
1396 | ] |
1397 | } | |
1398 | ||
1399 | /// Returns all rustc command line options, including metadata for | |
1400 | /// each option, such as whether the option is part of the stable | |
1401 | /// long-term interface for rustc. | |
1402 | pub fn rustc_optgroups() -> Vec<RustcOptGroup> { | |
1403 | let mut opts = rustc_short_optgroups(); | |
064997fb | 1404 | // FIXME: none of these descriptions are actually used |
041b39d2 | 1405 | opts.extend(vec![ |
0531ce1d XL |
1406 | opt::multi_s( |
1407 | "", | |
1408 | "extern", | |
1409 | "Specify where an external rust library is located", | |
60c5eb7d | 1410 | "NAME[=PATH]", |
9fa01778 | 1411 | ), |
7453a54e | 1412 | opt::opt_s("", "sysroot", "Override the system root", "PATH"), |
064997fb | 1413 | opt::multi("Z", "", "Set unstable / perma-unstable options", "FLAG"), |
0531ce1d XL |
1414 | opt::opt_s( |
1415 | "", | |
1416 | "error-format", | |
1417 | "How errors and other messages are produced", | |
1418 | "human|json|short", | |
1419 | ), | |
dfeec247 | 1420 | opt::multi_s("", "json", "Configure the JSON output of the compiler", "CONFIG"), |
0531ce1d XL |
1421 | opt::opt_s( |
1422 | "", | |
1423 | "color", | |
1424 | "Configure coloring of output: | |
54a0048b SL |
1425 | auto = colorize, if output goes to a tty (default); |
1426 | always = always colorize output; | |
0531ce1d XL |
1427 | never = never colorize output", |
1428 | "auto|always|never", | |
1429 | ), | |
064997fb FG |
1430 | opt::opt_s( |
1431 | "", | |
1432 | "diagnostic-width", | |
1433 | "Inform rustc of the width of the output so that diagnostics can be truncated to fit", | |
1434 | "WIDTH", | |
1435 | ), | |
0531ce1d XL |
1436 | opt::multi_s( |
1437 | "", | |
1438 | "remap-path-prefix", | |
1439 | "Remap source names in all output (compiler messages and output files)", | |
1440 | "FROM=TO", | |
1441 | ), | |
1a4d82fc JJ |
1442 | ]); |
1443 | opts | |
1444 | } | |
1445 | ||
dfeec247 XL |
1446 | pub fn get_cmd_lint_options( |
1447 | matches: &getopts::Matches, | |
1448 | error_format: ErrorOutputType, | |
136023e0 | 1449 | ) -> (Vec<(String, lint::Level)>, bool, Option<lint::Level>) { |
74b04a01 | 1450 | let mut lint_opts_with_position = vec![]; |
8faf50e0 XL |
1451 | let mut describe_lints = false; |
1452 | ||
923072b8 | 1453 | for level in [lint::Allow, lint::Warn, lint::ForceWarn(None), lint::Deny, lint::Forbid] { |
136023e0 | 1454 | for (arg_pos, lint_name) in matches.opt_strs_pos(level.as_str()) { |
8faf50e0 XL |
1455 | if lint_name == "help" { |
1456 | describe_lints = true; | |
1457 | } else { | |
a2a8927a | 1458 | lint_opts_with_position.push((arg_pos, lint_name.replace('-', "_"), level)); |
8faf50e0 XL |
1459 | } |
1460 | } | |
1461 | } | |
1462 | ||
74b04a01 XL |
1463 | lint_opts_with_position.sort_by_key(|x| x.0); |
1464 | let lint_opts = lint_opts_with_position | |
1465 | .iter() | |
1466 | .cloned() | |
1467 | .map(|(_, lint_name, level)| (lint_name, level)) | |
1468 | .collect(); | |
1469 | ||
8faf50e0 XL |
1470 | let lint_cap = matches.opt_str("cap-lints").map(|cap| { |
1471 | lint::Level::from_str(&cap) | |
5e7ed085 | 1472 | .unwrap_or_else(|| early_error(error_format, &format!("unknown lint level: `{cap}`"))) |
8faf50e0 | 1473 | }); |
17df50a5 | 1474 | |
136023e0 | 1475 | (lint_opts, describe_lints, lint_cap) |
8faf50e0 XL |
1476 | } |
1477 | ||
e1599b0c | 1478 | /// Parses the `--color` flag. |
416331ca XL |
1479 | pub fn parse_color(matches: &getopts::Matches) -> ColorConfig { |
1480 | match matches.opt_str("color").as_ref().map(|s| &s[..]) { | |
0531ce1d | 1481 | Some("auto") => ColorConfig::Auto, |
9cc50fc6 | 1482 | Some("always") => ColorConfig::Always, |
0531ce1d | 1483 | Some("never") => ColorConfig::Never, |
e9174d1e | 1484 | |
9cc50fc6 | 1485 | None => ColorConfig::Auto, |
e9174d1e | 1486 | |
0531ce1d XL |
1487 | Some(arg) => early_error( |
1488 | ErrorOutputType::default(), | |
1489 | &format!( | |
e1599b0c | 1490 | "argument for `--color` must be auto, \ |
5e7ed085 | 1491 | always or never (instead was `{arg}`)" |
0531ce1d XL |
1492 | ), |
1493 | ), | |
416331ca XL |
1494 | } |
1495 | } | |
9cc50fc6 | 1496 | |
cdc7bbd5 XL |
1497 | /// Possible json config files |
1498 | pub struct JsonConfig { | |
1499 | pub json_rendered: HumanReadableErrorType, | |
1500 | pub json_artifact_notifications: bool, | |
04454e1e | 1501 | pub json_unused_externs: JsonUnusedExterns, |
a2a8927a | 1502 | pub json_future_incompat: bool, |
cdc7bbd5 XL |
1503 | } |
1504 | ||
04454e1e FG |
1505 | /// Report unused externs in event stream |
1506 | #[derive(Copy, Clone)] | |
1507 | pub enum JsonUnusedExterns { | |
1508 | /// Do not | |
1509 | No, | |
1510 | /// Report, but do not exit with failure status for deny/forbid | |
1511 | Silent, | |
1512 | /// Report, and also exit with failure status for deny/forbid | |
1513 | Loud, | |
1514 | } | |
1515 | ||
1516 | impl JsonUnusedExterns { | |
1517 | pub fn is_enabled(&self) -> bool { | |
1518 | match self { | |
1519 | JsonUnusedExterns::No => false, | |
1520 | JsonUnusedExterns::Loud | JsonUnusedExterns::Silent => true, | |
1521 | } | |
1522 | } | |
1523 | ||
1524 | pub fn is_loud(&self) -> bool { | |
1525 | match self { | |
1526 | JsonUnusedExterns::No | JsonUnusedExterns::Silent => false, | |
1527 | JsonUnusedExterns::Loud => true, | |
1528 | } | |
1529 | } | |
1530 | } | |
1531 | ||
416331ca XL |
1532 | /// Parse the `--json` flag. |
1533 | /// | |
1534 | /// The first value returned is how to render JSON diagnostics, and the second | |
1535 | /// is whether or not artifact notifications are enabled. | |
cdc7bbd5 | 1536 | pub fn parse_json(matches: &getopts::Matches) -> JsonConfig { |
416331ca XL |
1537 | let mut json_rendered: fn(ColorConfig) -> HumanReadableErrorType = |
1538 | HumanReadableErrorType::Default; | |
1539 | let mut json_color = ColorConfig::Never; | |
1540 | let mut json_artifact_notifications = false; | |
04454e1e | 1541 | let mut json_unused_externs = JsonUnusedExterns::No; |
a2a8927a | 1542 | let mut json_future_incompat = false; |
416331ca XL |
1543 | for option in matches.opt_strs("json") { |
1544 | // For now conservatively forbid `--color` with `--json` since `--json` | |
1545 | // won't actually be emitting any colors and anything colorized is | |
1546 | // embedded in a diagnostic message anyway. | |
1547 | if matches.opt_str("color").is_some() { | |
0bf4aa26 | 1548 | early_error( |
83c7162d | 1549 | ErrorOutputType::default(), |
416331ca XL |
1550 | "cannot specify the `--color` option with `--json`", |
1551 | ); | |
1552 | } | |
83c7162d | 1553 | |
416331ca XL |
1554 | for sub_option in option.split(',') { |
1555 | match sub_option { | |
1556 | "diagnostic-short" => json_rendered = HumanReadableErrorType::Short, | |
1557 | "diagnostic-rendered-ansi" => json_color = ColorConfig::Always, | |
1558 | "artifacts" => json_artifact_notifications = true, | |
04454e1e FG |
1559 | "unused-externs" => json_unused_externs = JsonUnusedExterns::Loud, |
1560 | "unused-externs-silent" => json_unused_externs = JsonUnusedExterns::Silent, | |
a2a8927a | 1561 | "future-incompat" => json_future_incompat = true, |
dfeec247 XL |
1562 | s => early_error( |
1563 | ErrorOutputType::default(), | |
5e7ed085 | 1564 | &format!("unknown `--json` option `{s}`"), |
dfeec247 | 1565 | ), |
416331ca XL |
1566 | } |
1567 | } | |
83c7162d | 1568 | } |
cdc7bbd5 XL |
1569 | |
1570 | JsonConfig { | |
1571 | json_rendered: json_rendered(json_color), | |
1572 | json_artifact_notifications, | |
1573 | json_unused_externs, | |
a2a8927a | 1574 | json_future_incompat, |
cdc7bbd5 | 1575 | } |
416331ca | 1576 | } |
83c7162d | 1577 | |
e1599b0c | 1578 | /// Parses the `--error-format` flag. |
416331ca XL |
1579 | pub fn parse_error_format( |
1580 | matches: &getopts::Matches, | |
1581 | color: ColorConfig, | |
1582 | json_rendered: HumanReadableErrorType, | |
1583 | ) -> ErrorOutputType { | |
e1599b0c | 1584 | // We need the `opts_present` check because the driver will send us Matches |
9cc50fc6 | 1585 | // with only stable options if no unstable options are used. Since error-format |
e1599b0c XL |
1586 | // is unstable, it will not be present. We have to use `opts_present` not |
1587 | // `opt_present` because the latter will panic. | |
9cc50fc6 SL |
1588 | let error_format = if matches.opts_present(&["error-format".to_owned()]) { |
1589 | match matches.opt_str("error-format").as_ref().map(|s| &s[..]) { | |
dfeec247 XL |
1590 | None | Some("human") => { |
1591 | ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) | |
1592 | } | |
dc9dc135 XL |
1593 | Some("human-annotate-rs") => { |
1594 | ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(color)) | |
dfeec247 | 1595 | } |
48663c56 XL |
1596 | Some("json") => ErrorOutputType::Json { pretty: false, json_rendered }, |
1597 | Some("pretty-json") => ErrorOutputType::Json { pretty: true, json_rendered }, | |
1598 | Some("short") => ErrorOutputType::HumanReadable(HumanReadableErrorType::Short(color)), | |
9cc50fc6 | 1599 | |
0531ce1d | 1600 | Some(arg) => early_error( |
48663c56 | 1601 | ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)), |
0531ce1d | 1602 | &format!( |
e1599b0c | 1603 | "argument for `--error-format` must be `human`, `json` or \ |
5e7ed085 | 1604 | `short` (instead was `{arg}`)" |
0531ce1d XL |
1605 | ), |
1606 | ), | |
e9174d1e | 1607 | } |
9cc50fc6 | 1608 | } else { |
48663c56 | 1609 | ErrorOutputType::HumanReadable(HumanReadableErrorType::Default(color)) |
e9174d1e SL |
1610 | }; |
1611 | ||
416331ca XL |
1612 | match error_format { |
1613 | ErrorOutputType::Json { .. } => {} | |
1614 | ||
1615 | // Conservatively require that the `--json` argument is coupled with | |
1616 | // `--error-format=json`. This means that `--json` is specified we | |
1617 | // should actually be emitting JSON blobs. | |
74b04a01 | 1618 | _ if !matches.opt_strs("json").is_empty() => { |
416331ca XL |
1619 | early_error( |
1620 | ErrorOutputType::default(), | |
1621 | "using `--json` requires also using `--error-format=json`", | |
1622 | ); | |
1623 | } | |
1624 | ||
1625 | _ => {} | |
1626 | } | |
1627 | ||
ba9703b0 | 1628 | error_format |
416331ca XL |
1629 | } |
1630 | ||
5869c6ff | 1631 | pub fn parse_crate_edition(matches: &getopts::Matches) -> Edition { |
416331ca | 1632 | let edition = match matches.opt_str("edition") { |
dfeec247 | 1633 | Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| { |
416331ca XL |
1634 | early_error( |
1635 | ErrorOutputType::default(), | |
1636 | &format!( | |
e1599b0c | 1637 | "argument for `--edition` must be one of: \ |
5e7ed085 | 1638 | {EDITION_NAME_LIST}. (instead was `{arg}`)" |
416331ca | 1639 | ), |
dfeec247 XL |
1640 | ) |
1641 | }), | |
416331ca XL |
1642 | None => DEFAULT_EDITION, |
1643 | }; | |
1644 | ||
5869c6ff | 1645 | if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) { |
cdc7bbd5 XL |
1646 | let is_nightly = nightly_options::match_is_nightly_build(matches); |
1647 | let msg = if !is_nightly { | |
1648 | format!( | |
1649 | "the crate requires edition {}, but the latest edition supported by this Rust version is {}", | |
1650 | edition, LATEST_STABLE_EDITION | |
1651 | ) | |
1652 | } else { | |
5e7ed085 | 1653 | format!("edition {edition} is unstable and only available with -Z unstable-options") |
cdc7bbd5 XL |
1654 | }; |
1655 | early_error(ErrorOutputType::default(), &msg) | |
416331ca XL |
1656 | } |
1657 | ||
e74abb32 XL |
1658 | edition |
1659 | } | |
abe05a73 | 1660 | |
064997fb FG |
1661 | fn check_error_format_stability( |
1662 | unstable_opts: &UnstableOptions, | |
e74abb32 XL |
1663 | error_format: ErrorOutputType, |
1664 | json_rendered: HumanReadableErrorType, | |
1665 | ) { | |
064997fb | 1666 | if !unstable_opts.unstable_options { |
48663c56 XL |
1667 | if let ErrorOutputType::Json { pretty: true, json_rendered } = error_format { |
1668 | early_error( | |
1669 | ErrorOutputType::Json { pretty: false, json_rendered }, | |
e1599b0c | 1670 | "`--error-format=pretty-json` is unstable", |
48663c56 XL |
1671 | ); |
1672 | } | |
dc9dc135 | 1673 | if let ErrorOutputType::HumanReadable(HumanReadableErrorType::AnnotateSnippet(_)) = |
dfeec247 XL |
1674 | error_format |
1675 | { | |
dc9dc135 XL |
1676 | early_error( |
1677 | ErrorOutputType::Json { pretty: false, json_rendered }, | |
e1599b0c | 1678 | "`--error-format=human-annotate-rs` is unstable", |
dc9dc135 XL |
1679 | ); |
1680 | } | |
abe05a73 | 1681 | } |
e74abb32 | 1682 | } |
1a4d82fc | 1683 | |
e74abb32 | 1684 | fn parse_output_types( |
064997fb | 1685 | unstable_opts: &UnstableOptions, |
e74abb32 XL |
1686 | matches: &getopts::Matches, |
1687 | error_format: ErrorOutputType, | |
1688 | ) -> OutputTypes { | |
5bcae85e | 1689 | let mut output_types = BTreeMap::new(); |
064997fb | 1690 | if !unstable_opts.parse_only { |
b039eaaf SL |
1691 | for list in matches.opt_strs("emit") { |
1692 | for output_type in list.split(',') { | |
fc512014 XL |
1693 | let (shorthand, path) = match output_type.split_once('=') { |
1694 | None => (output_type, None), | |
1695 | Some((shorthand, path)) => (shorthand, Some(PathBuf::from(path))), | |
1696 | }; | |
dfeec247 | 1697 | let output_type = OutputType::from_shorthand(shorthand).unwrap_or_else(|| { |
0bf4aa26 | 1698 | early_error( |
0531ce1d XL |
1699 | error_format, |
1700 | &format!( | |
5e7ed085 FG |
1701 | "unknown emission type: `{shorthand}` - expected one of: {display}", |
1702 | display = OutputType::shorthands_display(), | |
0531ce1d | 1703 | ), |
dfeec247 XL |
1704 | ) |
1705 | }); | |
b039eaaf | 1706 | output_types.insert(output_type, path); |
1a4d82fc JJ |
1707 | } |
1708 | } | |
1709 | }; | |
7cac9316 | 1710 | if output_types.is_empty() { |
b039eaaf | 1711 | output_types.insert(OutputType::Exe, None); |
1a4d82fc | 1712 | } |
e74abb32 XL |
1713 | OutputTypes(output_types) |
1714 | } | |
1a4d82fc | 1715 | |
e74abb32 XL |
1716 | fn should_override_cgus_and_disable_thinlto( |
1717 | output_types: &OutputTypes, | |
1718 | matches: &getopts::Matches, | |
1719 | error_format: ErrorOutputType, | |
1720 | mut codegen_units: Option<usize>, | |
1721 | ) -> (bool, Option<usize>) { | |
2c00a5a8 | 1722 | let mut disable_thinlto = false; |
e1599b0c | 1723 | // Issue #30063: if user requests LLVM-related output to one |
92a42be0 | 1724 | // particular path, disable codegen-units. |
dfeec247 XL |
1725 | let incompatible: Vec<_> = output_types |
1726 | .0 | |
0531ce1d | 1727 | .iter() |
ea8adc8c | 1728 | .map(|ot_path| ot_path.0) |
0531ce1d | 1729 | .filter(|ot| !ot.is_compatible_with_codegen_units_and_single_output_file()) |
ea8adc8c XL |
1730 | .map(|ot| ot.shorthand()) |
1731 | .collect(); | |
1732 | if !incompatible.is_empty() { | |
1733 | match codegen_units { | |
1734 | Some(n) if n > 1 => { | |
1735 | if matches.opt_present("o") { | |
1736 | for ot in &incompatible { | |
0531ce1d XL |
1737 | early_warn( |
1738 | error_format, | |
1739 | &format!( | |
5e7ed085 | 1740 | "`--emit={ot}` with `-o` incompatible with \ |
e1599b0c | 1741 | `-C codegen-units=N` for N > 1", |
0531ce1d XL |
1742 | ), |
1743 | ); | |
ea8adc8c XL |
1744 | } |
1745 | early_warn(error_format, "resetting to default -C codegen-units=1"); | |
1746 | codegen_units = Some(1); | |
2c00a5a8 | 1747 | disable_thinlto = true; |
ea8adc8c | 1748 | } |
92a42be0 | 1749 | } |
ff7c6d11 XL |
1750 | _ => { |
1751 | codegen_units = Some(1); | |
2c00a5a8 | 1752 | disable_thinlto = true; |
ff7c6d11 | 1753 | } |
92a42be0 SL |
1754 | } |
1755 | } | |
1756 | ||
e74abb32 | 1757 | if codegen_units == Some(0) { |
dfeec247 | 1758 | early_error(error_format, "value for codegen units must be a positive non-zero integer"); |
ff7c6d11 XL |
1759 | } |
1760 | ||
e74abb32 XL |
1761 | (disable_thinlto, codegen_units) |
1762 | } | |
1763 | ||
064997fb FG |
1764 | fn check_thread_count(unstable_opts: &UnstableOptions, error_format: ErrorOutputType) { |
1765 | if unstable_opts.threads == 0 { | |
dfeec247 | 1766 | early_error(error_format, "value for threads must be a positive non-zero integer"); |
83c7162d XL |
1767 | } |
1768 | ||
064997fb | 1769 | if unstable_opts.threads > 1 && unstable_opts.fuel.is_some() { |
dfeec247 | 1770 | early_error(error_format, "optimization fuel is incompatible with multiple threads"); |
54a0048b | 1771 | } |
e74abb32 | 1772 | } |
54a0048b | 1773 | |
e74abb32 XL |
1774 | fn collect_print_requests( |
1775 | cg: &mut CodegenOptions, | |
064997fb | 1776 | unstable_opts: &mut UnstableOptions, |
e74abb32 | 1777 | matches: &getopts::Matches, |
e74abb32 XL |
1778 | error_format: ErrorOutputType, |
1779 | ) -> Vec<PrintRequest> { | |
5bcae85e SL |
1780 | let mut prints = Vec::<PrintRequest>::new(); |
1781 | if cg.target_cpu.as_ref().map_or(false, |s| s == "help") { | |
1782 | prints.push(PrintRequest::TargetCPUs); | |
1783 | cg.target_cpu = None; | |
1784 | }; | |
1785 | if cg.target_feature == "help" { | |
1786 | prints.push(PrintRequest::TargetFeatures); | |
b7449926 | 1787 | cg.target_feature = String::new(); |
5bcae85e | 1788 | } |
5bcae85e | 1789 | |
e74abb32 XL |
1790 | prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { |
1791 | "crate-name" => PrintRequest::CrateName, | |
1792 | "file-names" => PrintRequest::FileNames, | |
1793 | "sysroot" => PrintRequest::Sysroot, | |
74b04a01 | 1794 | "target-libdir" => PrintRequest::TargetLibdir, |
e74abb32 XL |
1795 | "cfg" => PrintRequest::Cfg, |
1796 | "target-list" => PrintRequest::TargetList, | |
1797 | "target-cpus" => PrintRequest::TargetCPUs, | |
1798 | "target-features" => PrintRequest::TargetFeatures, | |
1799 | "relocation-models" => PrintRequest::RelocationModels, | |
1800 | "code-models" => PrintRequest::CodeModels, | |
1801 | "tls-models" => PrintRequest::TlsModels, | |
1802 | "native-static-libs" => PrintRequest::NativeStaticLibs, | |
3c0e092e | 1803 | "stack-protector-strategies" => PrintRequest::StackProtectorStrategies, |
e74abb32 | 1804 | "target-spec-json" => { |
064997fb | 1805 | if unstable_opts.unstable_options { |
e74abb32 XL |
1806 | PrintRequest::TargetSpec |
1807 | } else { | |
1808 | early_error( | |
1809 | error_format, | |
1810 | "the `-Z unstable-options` flag must also be passed to \ | |
1811 | enable the target-spec-json print option", | |
1812 | ); | |
1813 | } | |
1814 | } | |
5099ac24 | 1815 | "link-args" => PrintRequest::LinkArgs, |
5e7ed085 | 1816 | req => early_error(error_format, &format!("unknown print request `{req}`")), |
e74abb32 | 1817 | })); |
1a4d82fc | 1818 | |
e74abb32 XL |
1819 | prints |
1820 | } | |
1821 | ||
17df50a5 XL |
1822 | pub fn parse_target_triple( |
1823 | matches: &getopts::Matches, | |
1824 | error_format: ErrorOutputType, | |
1825 | ) -> TargetTriple { | |
e74abb32 XL |
1826 | match matches.opt_str("target") { |
1827 | Some(target) if target.ends_with(".json") => { | |
0531ce1d | 1828 | let path = Path::new(&target); |
dfeec247 | 1829 | TargetTriple::from_path(&path).unwrap_or_else(|_| { |
5e7ed085 | 1830 | early_error(error_format, &format!("target file {path:?} does not exist")) |
dfeec247 | 1831 | }) |
e74abb32 | 1832 | } |
6a06907d | 1833 | Some(target) => TargetTriple::TargetTriple(target), |
e74abb32 XL |
1834 | _ => TargetTriple::from_triple(host_triple()), |
1835 | } | |
1836 | } | |
1837 | ||
1838 | fn parse_opt_level( | |
1839 | matches: &getopts::Matches, | |
1840 | cg: &CodegenOptions, | |
1841 | error_format: ErrorOutputType, | |
1842 | ) -> OptLevel { | |
1843 | // The `-O` and `-C opt-level` flags specify the same setting, so we want to be able | |
1844 | // to use them interchangeably. However, because they're technically different flags, | |
1845 | // we need to work out manually which should take precedence if both are supplied (i.e. | |
1846 | // the rightmost flag). We do this by finding the (rightmost) position of both flags and | |
1847 | // comparing them. Note that if a flag is not found, its position will be `None`, which | |
1848 | // always compared less than `Some(_)`. | |
1849 | let max_o = matches.opt_positions("O").into_iter().max(); | |
dfeec247 XL |
1850 | let max_c = matches |
1851 | .opt_strs_pos("C") | |
1852 | .into_iter() | |
fc512014 XL |
1853 | .flat_map(|(i, s)| { |
1854 | // NB: This can match a string without `=`. | |
1855 | if let Some("opt-level") = s.splitn(2, '=').next() { Some(i) } else { None } | |
1856 | }) | |
dfeec247 | 1857 | .max(); |
e74abb32 XL |
1858 | if max_o > max_c { |
1859 | OptLevel::Default | |
0531ce1d | 1860 | } else { |
ba9703b0 XL |
1861 | match cg.opt_level.as_ref() { |
1862 | "0" => OptLevel::No, | |
1863 | "1" => OptLevel::Less, | |
1864 | "2" => OptLevel::Default, | |
1865 | "3" => OptLevel::Aggressive, | |
1866 | "s" => OptLevel::Size, | |
1867 | "z" => OptLevel::SizeMin, | |
1868 | arg => { | |
e74abb32 XL |
1869 | early_error( |
1870 | error_format, | |
1871 | &format!( | |
1872 | "optimization level needs to be \ | |
5e7ed085 | 1873 | between 0-3, s or z (instead was `{arg}`)" |
e74abb32 XL |
1874 | ), |
1875 | ); | |
1a4d82fc JJ |
1876 | } |
1877 | } | |
e74abb32 XL |
1878 | } |
1879 | } | |
1880 | ||
1881 | fn select_debuginfo( | |
1882 | matches: &getopts::Matches, | |
1883 | cg: &CodegenOptions, | |
1884 | error_format: ErrorOutputType, | |
1885 | ) -> DebugInfo { | |
48663c56 | 1886 | let max_g = matches.opt_positions("g").into_iter().max(); |
dfeec247 XL |
1887 | let max_c = matches |
1888 | .opt_strs_pos("C") | |
1889 | .into_iter() | |
fc512014 XL |
1890 | .flat_map(|(i, s)| { |
1891 | // NB: This can match a string without `=`. | |
1892 | if let Some("debuginfo") = s.splitn(2, '=').next() { Some(i) } else { None } | |
1893 | }) | |
dfeec247 | 1894 | .max(); |
e74abb32 | 1895 | if max_g > max_c { |
b7449926 | 1896 | DebugInfo::Full |
1a4d82fc JJ |
1897 | } else { |
1898 | match cg.debuginfo { | |
ba9703b0 XL |
1899 | 0 => DebugInfo::None, |
1900 | 1 => DebugInfo::Limited, | |
1901 | 2 => DebugInfo::Full, | |
1902 | arg => { | |
0531ce1d XL |
1903 | early_error( |
1904 | error_format, | |
1905 | &format!( | |
1906 | "debug info level needs to be between \ | |
5e7ed085 | 1907 | 0-2 (instead was `{arg}`)" |
0531ce1d XL |
1908 | ), |
1909 | ); | |
1a4d82fc JJ |
1910 | } |
1911 | } | |
1a4d82fc | 1912 | } |
e74abb32 | 1913 | } |
1a4d82fc | 1914 | |
923072b8 | 1915 | pub(crate) fn parse_assert_incr_state( |
3c0e092e XL |
1916 | opt_assertion: &Option<String>, |
1917 | error_format: ErrorOutputType, | |
1918 | ) -> Option<IncrementalStateAssertion> { | |
1919 | match opt_assertion { | |
1920 | Some(s) if s.as_str() == "loaded" => Some(IncrementalStateAssertion::Loaded), | |
1921 | Some(s) if s.as_str() == "not-loaded" => Some(IncrementalStateAssertion::NotLoaded), | |
5e7ed085 FG |
1922 | Some(s) => { |
1923 | early_error(error_format, &format!("unexpected incremental state assertion value: {s}")) | |
1924 | } | |
3c0e092e XL |
1925 | None => None, |
1926 | } | |
1927 | } | |
1928 | ||
94222f64 XL |
1929 | fn parse_native_lib_kind( |
1930 | matches: &getopts::Matches, | |
1931 | kind: &str, | |
1932 | error_format: ErrorOutputType, | |
1933 | ) -> (NativeLibKind, Option<bool>) { | |
94222f64 XL |
1934 | let (kind, modifiers) = match kind.split_once(':') { |
1935 | None => (kind, None), | |
1936 | Some((kind, modifiers)) => (kind, Some(modifiers)), | |
1937 | }; | |
1938 | ||
1939 | let kind = match kind { | |
923072b8 | 1940 | "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, |
17df50a5 XL |
1941 | "dylib" => NativeLibKind::Dylib { as_needed: None }, |
1942 | "framework" => NativeLibKind::Framework { as_needed: None }, | |
064997fb FG |
1943 | "link-arg" => { |
1944 | if !nightly_options::is_unstable_enabled(matches) { | |
1945 | let why = if nightly_options::match_is_nightly_build(matches) { | |
1946 | " and only accepted on the nightly compiler" | |
1947 | } else { | |
1948 | ", the `-Z unstable-options` flag must also be passed to use it" | |
1949 | }; | |
1950 | early_error(error_format, &format!("library kind `link-arg` is unstable{why}")) | |
1951 | } | |
1952 | NativeLibKind::LinkArg | |
1953 | } | |
923072b8 | 1954 | _ => early_error( |
17df50a5 | 1955 | error_format, |
064997fb FG |
1956 | &format!( |
1957 | "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg" | |
1958 | ), | |
17df50a5 | 1959 | ), |
94222f64 XL |
1960 | }; |
1961 | match modifiers { | |
1962 | None => (kind, None), | |
5e7ed085 | 1963 | Some(modifiers) => parse_native_lib_modifiers(kind, modifiers, error_format, matches), |
17df50a5 XL |
1964 | } |
1965 | } | |
1966 | ||
1967 | fn parse_native_lib_modifiers( | |
17df50a5 XL |
1968 | mut kind: NativeLibKind, |
1969 | modifiers: &str, | |
e74abb32 | 1970 | error_format: ErrorOutputType, |
5e7ed085 | 1971 | matches: &getopts::Matches, |
17df50a5 XL |
1972 | ) -> (NativeLibKind, Option<bool>) { |
1973 | let mut verbatim = None; | |
1974 | for modifier in modifiers.split(',') { | |
a2a8927a | 1975 | let (modifier, value) = match modifier.strip_prefix(&['+', '-']) { |
17df50a5 XL |
1976 | Some(m) => (m, modifier.starts_with('+')), |
1977 | None => early_error( | |
1978 | error_format, | |
1979 | "invalid linking modifier syntax, expected '+' or '-' prefix \ | |
923072b8 | 1980 | before one of: bundle, verbatim, whole-archive, as-needed", |
17df50a5 XL |
1981 | ), |
1982 | }; | |
1983 | ||
923072b8 FG |
1984 | let report_unstable_modifier = || { |
1985 | if !nightly_options::is_unstable_enabled(matches) { | |
1986 | let why = if nightly_options::match_is_nightly_build(matches) { | |
1987 | " and only accepted on the nightly compiler" | |
1988 | } else { | |
1989 | ", the `-Z unstable-options` flag must also be passed to use it" | |
1990 | }; | |
1991 | early_error( | |
1992 | error_format, | |
1993 | &format!("linking modifier `{modifier}` is unstable{why}"), | |
1994 | ) | |
1995 | } | |
1996 | }; | |
1997 | let assign_modifier = |dst: &mut Option<bool>| { | |
1998 | if dst.is_some() { | |
1999 | let msg = format!("multiple `{modifier}` modifiers in a single `-l` option"); | |
2000 | early_error(error_format, &msg) | |
2001 | } else { | |
2002 | *dst = Some(value); | |
17df50a5 | 2003 | } |
923072b8 FG |
2004 | }; |
2005 | match (modifier, &mut kind) { | |
2006 | ("bundle", NativeLibKind::Static { bundle, .. }) => assign_modifier(bundle), | |
17df50a5 XL |
2007 | ("bundle", _) => early_error( |
2008 | error_format, | |
923072b8 | 2009 | "linking modifier `bundle` is only compatible with `static` linking kind", |
17df50a5 XL |
2010 | ), |
2011 | ||
5e7ed085 | 2012 | ("verbatim", _) => { |
923072b8 FG |
2013 | report_unstable_modifier(); |
2014 | assign_modifier(&mut verbatim) | |
5e7ed085 | 2015 | } |
17df50a5 XL |
2016 | |
2017 | ("whole-archive", NativeLibKind::Static { whole_archive, .. }) => { | |
923072b8 | 2018 | assign_modifier(whole_archive) |
17df50a5 XL |
2019 | } |
2020 | ("whole-archive", _) => early_error( | |
2021 | error_format, | |
923072b8 | 2022 | "linking modifier `whole-archive` is only compatible with `static` linking kind", |
17df50a5 XL |
2023 | ), |
2024 | ||
2025 | ("as-needed", NativeLibKind::Dylib { as_needed }) | |
2026 | | ("as-needed", NativeLibKind::Framework { as_needed }) => { | |
923072b8 FG |
2027 | report_unstable_modifier(); |
2028 | assign_modifier(as_needed) | |
17df50a5 XL |
2029 | } |
2030 | ("as-needed", _) => early_error( | |
2031 | error_format, | |
923072b8 FG |
2032 | "linking modifier `as-needed` is only compatible with \ |
2033 | `dylib` and `framework` linking kinds", | |
17df50a5 XL |
2034 | ), |
2035 | ||
5e7ed085 FG |
2036 | // Note: this error also excludes the case with empty modifier |
2037 | // string, like `modifiers = ""`. | |
17df50a5 XL |
2038 | _ => early_error( |
2039 | error_format, | |
2040 | &format!( | |
923072b8 FG |
2041 | "unknown linking modifier `{modifier}`, expected one \ |
2042 | of: bundle, verbatim, whole-archive, as-needed" | |
17df50a5 XL |
2043 | ), |
2044 | ), | |
2045 | } | |
2046 | } | |
2047 | ||
2048 | (kind, verbatim) | |
2049 | } | |
2050 | ||
2051 | fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec<NativeLib> { | |
e74abb32 | 2052 | matches |
0531ce1d XL |
2053 | .opt_strs("l") |
2054 | .into_iter() | |
2055 | .map(|s| { | |
17df50a5 | 2056 | // Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]", |
064997fb | 2057 | // where KIND is one of "dylib", "framework", "static", "link-arg" and |
17df50a5 XL |
2058 | // where MODIFIERS are a comma separated list of supported modifiers |
2059 | // (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed | |
2060 | // with either + or - to indicate whether it is enabled or disabled. | |
2061 | // The last value specified for a given modifier wins. | |
2062 | let (name, kind, verbatim) = match s.split_once('=') { | |
2063 | None => (s, NativeLibKind::Unspecified, None), | |
fc512014 | 2064 | Some((kind, name)) => { |
94222f64 | 2065 | let (kind, verbatim) = parse_native_lib_kind(matches, kind, error_format); |
17df50a5 | 2066 | (name.to_string(), kind, verbatim) |
0531ce1d XL |
2067 | } |
2068 | }; | |
17df50a5 | 2069 | |
fc512014 XL |
2070 | let (name, new_name) = match name.split_once(':') { |
2071 | None => (name, None), | |
2072 | Some((name, new_name)) => (name.to_string(), Some(new_name.to_owned())), | |
2073 | }; | |
923072b8 FG |
2074 | if name.is_empty() { |
2075 | early_error(error_format, "library name must not be empty"); | |
2076 | } | |
17df50a5 | 2077 | NativeLib { name, new_name, kind, verbatim } |
0531ce1d | 2078 | }) |
e74abb32 XL |
2079 | .collect() |
2080 | } | |
1a4d82fc | 2081 | |
60c5eb7d | 2082 | pub fn parse_externs( |
e74abb32 | 2083 | matches: &getopts::Matches, |
064997fb | 2084 | unstable_opts: &UnstableOptions, |
e74abb32 | 2085 | error_format: ErrorOutputType, |
e74abb32 | 2086 | ) -> Externs { |
064997fb | 2087 | let is_unstable_enabled = unstable_opts.unstable_options; |
48663c56 | 2088 | let mut externs: BTreeMap<String, ExternEntry> = BTreeMap::new(); |
60c5eb7d | 2089 | for arg in matches.opt_strs("extern") { |
fc512014 XL |
2090 | let (name, path) = match arg.split_once('=') { |
2091 | None => (arg, None), | |
5869c6ff | 2092 | Some((name, path)) => (name.to_string(), Some(Path::new(path))), |
fc512014 XL |
2093 | }; |
2094 | let (options, name) = match name.split_once(':') { | |
2095 | None => (None, name), | |
2096 | Some((opts, name)) => (Some(opts), name.to_string()), | |
1a4d82fc JJ |
2097 | }; |
2098 | ||
5869c6ff XL |
2099 | let path = path.map(|p| CanonicalizedPath::new(p)); |
2100 | ||
60c5eb7d | 2101 | let entry = externs.entry(name.to_owned()); |
48663c56 | 2102 | |
60c5eb7d | 2103 | use std::collections::btree_map::Entry; |
48663c56 | 2104 | |
60c5eb7d XL |
2105 | let entry = if let Some(path) = path { |
2106 | // --extern prelude_name=some_file.rlib | |
2107 | match entry { | |
2108 | Entry::Vacant(vacant) => { | |
2109 | let files = BTreeSet::from_iter(iter::once(path)); | |
2110 | vacant.insert(ExternEntry::new(ExternLocation::ExactPaths(files))) | |
2111 | } | |
2112 | Entry::Occupied(occupied) => { | |
2113 | let ext_ent = occupied.into_mut(); | |
2114 | match ext_ent { | |
2115 | ExternEntry { location: ExternLocation::ExactPaths(files), .. } => { | |
2116 | files.insert(path); | |
2117 | } | |
2118 | ExternEntry { | |
2119 | location: location @ ExternLocation::FoundInLibrarySearchDirectories, | |
2120 | .. | |
2121 | } => { | |
2122 | // Exact paths take precedence over search directories. | |
2123 | let files = BTreeSet::from_iter(iter::once(path)); | |
2124 | *location = ExternLocation::ExactPaths(files); | |
2125 | } | |
2126 | } | |
2127 | ext_ent | |
2128 | } | |
2129 | } | |
2130 | } else { | |
2131 | // --extern prelude_name | |
2132 | match entry { | |
2133 | Entry::Vacant(vacant) => { | |
2134 | vacant.insert(ExternEntry::new(ExternLocation::FoundInLibrarySearchDirectories)) | |
2135 | } | |
2136 | Entry::Occupied(occupied) => { | |
2137 | // Ignore if already specified. | |
2138 | occupied.into_mut() | |
2139 | } | |
2140 | } | |
2141 | }; | |
2142 | ||
2143 | let mut is_private_dep = false; | |
2144 | let mut add_prelude = true; | |
04454e1e | 2145 | let mut nounused_dep = false; |
60c5eb7d XL |
2146 | if let Some(opts) = options { |
2147 | if !is_unstable_enabled { | |
2148 | early_error( | |
2149 | error_format, | |
2150 | "the `-Z unstable-options` flag must also be passed to \ | |
2151 | enable `--extern options", | |
2152 | ); | |
2153 | } | |
2154 | for opt in opts.split(',') { | |
2155 | match opt { | |
2156 | "priv" => is_private_dep = true, | |
2157 | "noprelude" => { | |
2158 | if let ExternLocation::ExactPaths(_) = &entry.location { | |
2159 | add_prelude = false; | |
2160 | } else { | |
2161 | early_error( | |
2162 | error_format, | |
2163 | "the `noprelude` --extern option requires a file path", | |
2164 | ); | |
2165 | } | |
2166 | } | |
04454e1e | 2167 | "nounused" => nounused_dep = true, |
5e7ed085 | 2168 | _ => early_error(error_format, &format!("unknown --extern option `{opt}`")), |
60c5eb7d XL |
2169 | } |
2170 | } | |
2171 | } | |
48663c56 | 2172 | |
60c5eb7d XL |
2173 | // Crates start out being not private, and go to being private `priv` |
2174 | // is specified. | |
2175 | entry.is_private_dep |= is_private_dep; | |
04454e1e FG |
2176 | // likewise `nounused` |
2177 | entry.nounused_dep |= nounused_dep; | |
60c5eb7d XL |
2178 | // If any flag is missing `noprelude`, then add to the prelude. |
2179 | entry.add_prelude |= add_prelude; | |
1a4d82fc | 2180 | } |
e74abb32 XL |
2181 | Externs(externs) |
2182 | } | |
1a4d82fc | 2183 | |
e74abb32 XL |
2184 | fn parse_remap_path_prefix( |
2185 | matches: &getopts::Matches, | |
064997fb | 2186 | unstable_opts: &UnstableOptions, |
dfeec247 | 2187 | error_format: ErrorOutputType, |
e74abb32 | 2188 | ) -> Vec<(PathBuf, PathBuf)> { |
c295e0f8 | 2189 | let mut mapping: Vec<(PathBuf, PathBuf)> = matches |
0531ce1d XL |
2190 | .opt_strs("remap-path-prefix") |
2191 | .into_iter() | |
fc512014 XL |
2192 | .map(|remap| match remap.rsplit_once('=') { |
2193 | None => early_error( | |
2194 | error_format, | |
2195 | "--remap-path-prefix must contain '=' between FROM and TO", | |
2196 | ), | |
2197 | Some((from, to)) => (PathBuf::from(from), PathBuf::from(to)), | |
0531ce1d | 2198 | }) |
c295e0f8 | 2199 | .collect(); |
064997fb | 2200 | match &unstable_opts.remap_cwd_prefix { |
c295e0f8 XL |
2201 | Some(to) => match std::env::current_dir() { |
2202 | Ok(cwd) => mapping.push((cwd, to.clone())), | |
2203 | Err(_) => (), | |
2204 | }, | |
2205 | None => (), | |
2206 | }; | |
2207 | mapping | |
e74abb32 | 2208 | } |
0531ce1d | 2209 | |
064997fb | 2210 | // JUSTIFICATION: before wrapper fn is available |
f2b60f7d | 2211 | #[allow(rustc::bad_opt_access)] |
e74abb32 XL |
2212 | pub fn build_session_options(matches: &getopts::Matches) -> Options { |
2213 | let color = parse_color(matches); | |
2214 | ||
2215 | let edition = parse_crate_edition(matches); | |
2216 | ||
a2a8927a XL |
2217 | let JsonConfig { |
2218 | json_rendered, | |
2219 | json_artifact_notifications, | |
2220 | json_unused_externs, | |
2221 | json_future_incompat, | |
2222 | } = parse_json(matches); | |
e74abb32 XL |
2223 | |
2224 | let error_format = parse_error_format(matches, color, json_rendered); | |
2225 | ||
064997fb FG |
2226 | let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| { |
2227 | early_error(error_format, "`--diagnostic-width` must be an positive integer"); | |
2228 | }); | |
2229 | ||
e74abb32 XL |
2230 | let unparsed_crate_types = matches.opt_strs("crate-type"); |
2231 | let crate_types = parse_crate_types_from_list(unparsed_crate_types) | |
a2a8927a | 2232 | .unwrap_or_else(|e| early_error(error_format, &e)); |
e74abb32 | 2233 | |
064997fb | 2234 | let mut unstable_opts = UnstableOptions::build(matches, error_format); |
94222f64 | 2235 | let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format); |
e74abb32 | 2236 | |
064997fb | 2237 | check_error_format_stability(&unstable_opts, error_format, json_rendered); |
e74abb32 | 2238 | |
064997fb | 2239 | if !unstable_opts.unstable_options && json_unused_externs.is_enabled() { |
cdc7bbd5 XL |
2240 | early_error( |
2241 | error_format, | |
2242 | "the `-Z unstable-options` flag must also be passed to enable \ | |
2243 | the flag `--json=unused-externs`", | |
2244 | ); | |
2245 | } | |
2246 | ||
064997fb | 2247 | let output_types = parse_output_types(&unstable_opts, matches, error_format); |
e74abb32 | 2248 | |
17df50a5 | 2249 | let mut cg = CodegenOptions::build(matches, error_format); |
ba9703b0 | 2250 | let (disable_thinlto, mut codegen_units) = should_override_cgus_and_disable_thinlto( |
e74abb32 XL |
2251 | &output_types, |
2252 | matches, | |
2253 | error_format, | |
2254 | cg.codegen_units, | |
2255 | ); | |
2256 | ||
064997fb | 2257 | check_thread_count(&unstable_opts, error_format); |
e74abb32 | 2258 | |
5099ac24 | 2259 | let incremental = cg.incremental.as_ref().map(PathBuf::from); |
e74abb32 | 2260 | |
064997fb | 2261 | let assert_incr_state = parse_assert_incr_state(&unstable_opts.assert_incr_state, error_format); |
3c0e092e | 2262 | |
064997fb | 2263 | if unstable_opts.profile && incremental.is_some() { |
e74abb32 | 2264 | early_error( |
0531ce1d | 2265 | error_format, |
e74abb32 XL |
2266 | "can't instrument with gcov profiling when compiling incrementally", |
2267 | ); | |
2268 | } | |
064997fb | 2269 | if unstable_opts.profile { |
ba9703b0 XL |
2270 | match codegen_units { |
2271 | Some(1) => {} | |
2272 | None => codegen_units = Some(1), | |
2273 | Some(_) => early_error( | |
2274 | error_format, | |
2275 | "can't instrument with gcov profiling with multiple codegen units", | |
2276 | ), | |
2277 | } | |
2278 | } | |
e74abb32 XL |
2279 | |
2280 | if cg.profile_generate.enabled() && cg.profile_use.is_some() { | |
2281 | early_error( | |
2282 | error_format, | |
2283 | "options `-C profile-generate` and `-C profile-use` are exclusive", | |
2284 | ); | |
2285 | } | |
2286 | ||
064997fb | 2287 | if unstable_opts.profile_sample_use.is_some() |
c295e0f8 XL |
2288 | && (cg.profile_generate.enabled() || cg.profile_use.is_some()) |
2289 | { | |
2290 | early_error( | |
2291 | error_format, | |
2292 | "option `-Z profile-sample-use` cannot be used with `-C profile-generate` or `-C profile-use`", | |
2293 | ); | |
2294 | } | |
2295 | ||
a2a8927a XL |
2296 | // Handle both `-Z symbol-mangling-version` and `-C symbol-mangling-version`; the latter takes |
2297 | // precedence. | |
064997fb | 2298 | match (cg.symbol_mangling_version, unstable_opts.symbol_mangling_version) { |
a2a8927a XL |
2299 | (Some(smv_c), Some(smv_z)) if smv_c != smv_z => { |
2300 | early_error( | |
2301 | error_format, | |
2302 | "incompatible values passed for `-C symbol-mangling-version` \ | |
2303 | and `-Z symbol-mangling-version`", | |
2304 | ); | |
2305 | } | |
2306 | (Some(SymbolManglingVersion::V0), _) => {} | |
064997fb | 2307 | (Some(_), _) if !unstable_opts.unstable_options => { |
a2a8927a XL |
2308 | early_error( |
2309 | error_format, | |
2310 | "`-C symbol-mangling-version=legacy` requires `-Z unstable-options`", | |
2311 | ); | |
2312 | } | |
2313 | (None, None) => {} | |
2314 | (None, smv) => { | |
2315 | early_warn( | |
2316 | error_format, | |
2317 | "`-Z symbol-mangling-version` is deprecated; use `-C symbol-mangling-version`", | |
2318 | ); | |
2319 | cg.symbol_mangling_version = smv; | |
2320 | } | |
2321 | _ => {} | |
2322 | } | |
2323 | ||
5099ac24 FG |
2324 | // Handle both `-Z instrument-coverage` and `-C instrument-coverage`; the latter takes |
2325 | // precedence. | |
064997fb | 2326 | match (cg.instrument_coverage, unstable_opts.instrument_coverage) { |
5099ac24 FG |
2327 | (Some(ic_c), Some(ic_z)) if ic_c != ic_z => { |
2328 | early_error( | |
2329 | error_format, | |
2330 | "incompatible values passed for `-C instrument-coverage` \ | |
2331 | and `-Z instrument-coverage`", | |
2332 | ); | |
2333 | } | |
2334 | (Some(InstrumentCoverage::Off | InstrumentCoverage::All), _) => {} | |
064997fb | 2335 | (Some(_), _) if !unstable_opts.unstable_options => { |
5099ac24 FG |
2336 | early_error( |
2337 | error_format, | |
2338 | "`-C instrument-coverage=except-*` requires `-Z unstable-options`", | |
2339 | ); | |
2340 | } | |
2341 | (None, None) => {} | |
2342 | (None, ic) => { | |
2343 | early_warn( | |
2344 | error_format, | |
2345 | "`-Z instrument-coverage` is deprecated; use `-C instrument-coverage`", | |
2346 | ); | |
2347 | cg.instrument_coverage = ic; | |
2348 | } | |
2349 | _ => {} | |
2350 | } | |
2351 | ||
2352 | if cg.instrument_coverage.is_some() && cg.instrument_coverage != Some(InstrumentCoverage::Off) { | |
3dfed10e XL |
2353 | if cg.profile_generate.enabled() || cg.profile_use.is_some() { |
2354 | early_error( | |
2355 | error_format, | |
5099ac24 | 2356 | "option `-C instrument-coverage` is not compatible with either `-C profile-use` \ |
3dfed10e XL |
2357 | or `-C profile-generate`", |
2358 | ); | |
2359 | } | |
2360 | ||
5099ac24 | 2361 | // `-C instrument-coverage` implies `-C symbol-mangling-version=v0` - to ensure consistent |
1b1a35ee XL |
2362 | // and reversible name mangling. Note, LLVM coverage tools can analyze coverage over |
2363 | // multiple runs, including some changes to source code; so mangled names must be consistent | |
2364 | // across compilations. | |
a2a8927a XL |
2365 | match cg.symbol_mangling_version { |
2366 | None => cg.symbol_mangling_version = Some(SymbolManglingVersion::V0), | |
fc512014 XL |
2367 | Some(SymbolManglingVersion::Legacy) => { |
2368 | early_warn( | |
2369 | error_format, | |
5099ac24 | 2370 | "-C instrument-coverage requires symbol mangling version `v0`, \ |
a2a8927a | 2371 | but `-C symbol-mangling-version=legacy` was specified", |
fc512014 XL |
2372 | ); |
2373 | } | |
2374 | Some(SymbolManglingVersion::V0) => {} | |
2375 | } | |
1b1a35ee XL |
2376 | } |
2377 | ||
2378 | if let Ok(graphviz_font) = std::env::var("RUSTC_GRAPHVIZ_FONT") { | |
064997fb | 2379 | unstable_opts.graphviz_font = graphviz_font; |
3dfed10e XL |
2380 | } |
2381 | ||
f9f354fc XL |
2382 | if !cg.embed_bitcode { |
2383 | match cg.lto { | |
2384 | LtoCli::No | LtoCli::Unspecified => {} | |
2385 | LtoCli::Yes | LtoCli::NoParam | LtoCli::Thin | LtoCli::Fat => early_error( | |
2386 | error_format, | |
2387 | "options `-C embed-bitcode=no` and `-C lto` are incompatible", | |
2388 | ), | |
2389 | } | |
2390 | } | |
2391 | ||
064997fb | 2392 | let prints = collect_print_requests(&mut cg, &mut unstable_opts, matches, error_format); |
e74abb32 XL |
2393 | |
2394 | let cg = cg; | |
2395 | ||
2396 | let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); | |
2397 | let target_triple = parse_target_triple(matches, error_format); | |
2398 | let opt_level = parse_opt_level(matches, &cg, error_format); | |
2399 | // The `-g` and `-C debuginfo` flags specify the same setting, so we want to be able | |
2400 | // to use them interchangeably. See the note above (regarding `-O` and `-C opt-level`) | |
2401 | // for more details. | |
2402 | let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); | |
2403 | let debuginfo = select_debuginfo(matches, &cg, error_format); | |
2404 | ||
2405 | let mut search_paths = vec![]; | |
2406 | for s in &matches.opt_strs("L") { | |
a2a8927a | 2407 | search_paths.push(SearchPath::from_cli_opt(&s, error_format)); |
e74abb32 XL |
2408 | } |
2409 | ||
2410 | let libs = parse_libs(matches, error_format); | |
2411 | ||
2412 | let test = matches.opt_present("test"); | |
2413 | ||
e74abb32 | 2414 | if !cg.remark.is_empty() && debuginfo == DebugInfo::None { |
dfeec247 | 2415 | early_warn(error_format, "-C remark requires \"-C debuginfo=n\" to show source locations"); |
e74abb32 XL |
2416 | } |
2417 | ||
064997fb | 2418 | let externs = parse_externs(matches, &unstable_opts, error_format); |
e74abb32 XL |
2419 | |
2420 | let crate_name = matches.opt_str("crate-name"); | |
2421 | ||
064997fb | 2422 | let remap_path_prefix = parse_remap_path_prefix(matches, &unstable_opts, error_format); |
e74abb32 | 2423 | |
064997fb | 2424 | let pretty = parse_pretty(&unstable_opts, error_format); |
60c5eb7d | 2425 | |
cdc7bbd5 XL |
2426 | // Try to find a directory containing the Rust `src`, for more details see |
2427 | // the doc comment on the `real_rust_source_base_dir` field. | |
2428 | let tmp_buf; | |
2429 | let sysroot = match &sysroot_opt { | |
2430 | Some(s) => s, | |
2431 | None => { | |
2432 | tmp_buf = crate::filesearch::get_or_default_sysroot(); | |
2433 | &tmp_buf | |
2434 | } | |
2435 | }; | |
2436 | let real_rust_source_base_dir = { | |
2437 | // This is the location used by the `rust-src` `rustup` component. | |
2438 | let mut candidate = sysroot.join("lib/rustlib/src/rust"); | |
2439 | if let Ok(metadata) = candidate.symlink_metadata() { | |
2440 | // Replace the symlink rustbuild creates, with its destination. | |
2441 | // We could try to use `fs::canonicalize` instead, but that might | |
2442 | // produce unnecessarily verbose path. | |
2443 | if metadata.file_type().is_symlink() { | |
2444 | if let Ok(symlink_dest) = std::fs::read_link(&candidate) { | |
2445 | candidate = symlink_dest; | |
2446 | } | |
2447 | } | |
2448 | } | |
2449 | ||
2450 | // Only use this directory if it has a file we can expect to always find. | |
2451 | if candidate.join("library/std/src/lib.rs").is_file() { Some(candidate) } else { None } | |
2452 | }; | |
2453 | ||
94222f64 | 2454 | let working_dir = std::env::current_dir().unwrap_or_else(|e| { |
5e7ed085 | 2455 | early_error(error_format, &format!("Current directory is invalid: {e}")); |
94222f64 XL |
2456 | }); |
2457 | ||
2458 | let (path, remapped) = | |
2459 | FilePathMapping::new(remap_path_prefix.clone()).map_prefix(working_dir.clone()); | |
2460 | let working_dir = if remapped { | |
2461 | RealFileName::Remapped { local_path: Some(working_dir), virtual_name: path } | |
2462 | } else { | |
2463 | RealFileName::LocalPath(path) | |
2464 | }; | |
2465 | ||
e74abb32 | 2466 | Options { |
3c0e092e | 2467 | assert_incr_state, |
e74abb32 XL |
2468 | crate_types, |
2469 | optimize: opt_level, | |
2470 | debuginfo, | |
2471 | lint_opts, | |
2472 | lint_cap, | |
2473 | describe_lints, | |
2474 | output_types, | |
2475 | search_paths, | |
2476 | maybe_sysroot: sysroot_opt, | |
2477 | target_triple, | |
2478 | test, | |
2479 | incremental, | |
064997fb | 2480 | unstable_opts, |
e74abb32 | 2481 | prints, |
e74abb32 XL |
2482 | cg, |
2483 | error_format, | |
064997fb | 2484 | diagnostic_width, |
e74abb32 | 2485 | externs, |
fc512014 | 2486 | unstable_features: UnstableFeatures::from_environment(crate_name.as_deref()), |
e74abb32 | 2487 | crate_name, |
e74abb32 | 2488 | libs, |
e74abb32 XL |
2489 | debug_assertions, |
2490 | actually_rustdoc: false, | |
1b1a35ee | 2491 | trimmed_def_paths: TrimmedDefPaths::default(), |
e74abb32 XL |
2492 | cli_forced_codegen_units: codegen_units, |
2493 | cli_forced_thinlto_off: disable_thinlto, | |
2494 | remap_path_prefix, | |
cdc7bbd5 | 2495 | real_rust_source_base_dir, |
e74abb32 XL |
2496 | edition, |
2497 | json_artifact_notifications, | |
cdc7bbd5 | 2498 | json_unused_externs, |
a2a8927a | 2499 | json_future_incompat, |
60c5eb7d | 2500 | pretty, |
94222f64 XL |
2501 | working_dir, |
2502 | } | |
2503 | } | |
2504 | ||
064997fb | 2505 | fn parse_pretty(unstable_opts: &UnstableOptions, efmt: ErrorOutputType) -> Option<PpMode> { |
94222f64 XL |
2506 | use PpMode::*; |
2507 | ||
064997fb | 2508 | let first = match unstable_opts.unpretty.as_deref()? { |
94222f64 XL |
2509 | "normal" => Source(PpSourceMode::Normal), |
2510 | "identified" => Source(PpSourceMode::Identified), | |
94222f64 XL |
2511 | "expanded" => Source(PpSourceMode::Expanded), |
2512 | "expanded,identified" => Source(PpSourceMode::ExpandedIdentified), | |
2513 | "expanded,hygiene" => Source(PpSourceMode::ExpandedHygiene), | |
2514 | "ast-tree" => AstTree(PpAstTreeMode::Normal), | |
2515 | "ast-tree,expanded" => AstTree(PpAstTreeMode::Expanded), | |
2516 | "hir" => Hir(PpHirMode::Normal), | |
2517 | "hir,identified" => Hir(PpHirMode::Identified), | |
2518 | "hir,typed" => Hir(PpHirMode::Typed), | |
2519 | "hir-tree" => HirTree, | |
2520 | "thir-tree" => ThirTree, | |
2521 | "mir" => Mir, | |
2522 | "mir-cfg" => MirCFG, | |
2523 | name => early_error( | |
2524 | efmt, | |
2525 | &format!( | |
5e7ed085 FG |
2526 | "argument to `unpretty` must be one of `normal`, `identified`, \ |
2527 | `expanded`, `expanded,identified`, `expanded,hygiene`, \ | |
94222f64 | 2528 | `ast-tree`, `ast-tree,expanded`, `hir`, `hir,identified`, \ |
5e7ed085 | 2529 | `hir,typed`, `hir-tree`, `thir-tree`, `mir` or `mir-cfg`; got {name}" |
94222f64 XL |
2530 | ), |
2531 | ), | |
2532 | }; | |
f2b60f7d | 2533 | debug!("got unpretty option: {first:?}"); |
94222f64 | 2534 | Some(first) |
85aaf69f SL |
2535 | } |
2536 | ||
e1599b0c XL |
2537 | pub fn make_crate_type_option() -> RustcOptGroup { |
2538 | opt::multi_s( | |
2539 | "", | |
2540 | "crate-type", | |
2541 | "Comma separated list of types of crates | |
2542 | for the compiler to emit", | |
2543 | "[bin|lib|rlib|dylib|cdylib|staticlib|proc-macro]", | |
2544 | ) | |
2545 | } | |
2546 | ||
0531ce1d | 2547 | pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> { |
1a4d82fc | 2548 | let mut crate_types: Vec<CrateType> = Vec::new(); |
85aaf69f | 2549 | for unparsed_crate_type in &list_list { |
1a4d82fc JJ |
2550 | for part in unparsed_crate_type.split(',') { |
2551 | let new_part = match part { | |
0531ce1d | 2552 | "lib" => default_lib_output(), |
b7449926 XL |
2553 | "rlib" => CrateType::Rlib, |
2554 | "staticlib" => CrateType::Staticlib, | |
2555 | "dylib" => CrateType::Dylib, | |
2556 | "cdylib" => CrateType::Cdylib, | |
2557 | "bin" => CrateType::Executable, | |
2558 | "proc-macro" => CrateType::ProcMacro, | |
5e7ed085 | 2559 | _ => return Err(format!("unknown crate type: `{part}`")), |
1a4d82fc | 2560 | }; |
85aaf69f SL |
2561 | if !crate_types.contains(&new_part) { |
2562 | crate_types.push(new_part) | |
2563 | } | |
1a4d82fc JJ |
2564 | } |
2565 | } | |
2566 | ||
7cac9316 | 2567 | Ok(crate_types) |
1a4d82fc JJ |
2568 | } |
2569 | ||
54a0048b | 2570 | pub mod nightly_options { |
9e0c209e | 2571 | use super::{ErrorOutputType, OptionStability, RustcOptGroup}; |
60c5eb7d | 2572 | use crate::early_error; |
dfeec247 | 2573 | use rustc_feature::UnstableFeatures; |
54a0048b SL |
2574 | |
2575 | pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool { | |
fc512014 XL |
2576 | match_is_nightly_build(matches) |
2577 | && matches.opt_strs("Z").iter().any(|x| *x == "unstable-options") | |
2578 | } | |
2579 | ||
2580 | pub fn match_is_nightly_build(matches: &getopts::Matches) -> bool { | |
2581 | is_nightly_build(matches.opt_str("crate-name").as_deref()) | |
54a0048b SL |
2582 | } |
2583 | ||
fc512014 XL |
2584 | pub fn is_nightly_build(krate: Option<&str>) -> bool { |
2585 | UnstableFeatures::from_environment(krate).is_nightly_build() | |
54a0048b SL |
2586 | } |
2587 | ||
2588 | pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) { | |
dfeec247 | 2589 | let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options"); |
fc512014 | 2590 | let really_allows_unstable_options = match_is_nightly_build(matches); |
54a0048b SL |
2591 | |
2592 | for opt in flags.iter() { | |
2593 | if opt.stability == OptionStability::Stable { | |
0531ce1d | 2594 | continue; |
54a0048b | 2595 | } |
041b39d2 | 2596 | if !matches.opt_present(opt.name) { |
0531ce1d | 2597 | continue; |
54a0048b | 2598 | } |
041b39d2 | 2599 | if opt.name != "Z" && !has_z_unstable_option { |
0531ce1d XL |
2600 | early_error( |
2601 | ErrorOutputType::default(), | |
2602 | &format!( | |
2603 | "the `-Z unstable-options` flag must also be passed to enable \ | |
2604 | the flag `{}`", | |
2605 | opt.name | |
2606 | ), | |
2607 | ); | |
54a0048b SL |
2608 | } |
2609 | if really_allows_unstable_options { | |
0531ce1d | 2610 | continue; |
54a0048b SL |
2611 | } |
2612 | match opt.stability { | |
2613 | OptionStability::Unstable => { | |
0531ce1d XL |
2614 | let msg = format!( |
2615 | "the option `{}` is only accepted on the \ | |
2616 | nightly compiler", | |
2617 | opt.name | |
2618 | ); | |
54a0048b SL |
2619 | early_error(ErrorOutputType::default(), &msg); |
2620 | } | |
54a0048b SL |
2621 | OptionStability::Stable => {} |
2622 | } | |
2623 | } | |
2624 | } | |
2625 | } | |
2626 | ||
85aaf69f | 2627 | impl fmt::Display for CrateType { |
0bf4aa26 | 2628 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
1a4d82fc | 2629 | match *self { |
b7449926 XL |
2630 | CrateType::Executable => "bin".fmt(f), |
2631 | CrateType::Dylib => "dylib".fmt(f), | |
2632 | CrateType::Rlib => "rlib".fmt(f), | |
2633 | CrateType::Staticlib => "staticlib".fmt(f), | |
2634 | CrateType::Cdylib => "cdylib".fmt(f), | |
2635 | CrateType::ProcMacro => "proc-macro".fmt(f), | |
1a4d82fc JJ |
2636 | } |
2637 | } | |
2638 | } | |
2639 | ||
60c5eb7d XL |
2640 | #[derive(Copy, Clone, PartialEq, Debug)] |
2641 | pub enum PpSourceMode { | |
94222f64 | 2642 | /// `-Zunpretty=normal` |
6a06907d | 2643 | Normal, |
94222f64 | 2644 | /// `-Zunpretty=expanded` |
6a06907d | 2645 | Expanded, |
94222f64 | 2646 | /// `-Zunpretty=identified` |
6a06907d | 2647 | Identified, |
94222f64 | 2648 | /// `-Zunpretty=expanded,identified` |
6a06907d | 2649 | ExpandedIdentified, |
94222f64 | 2650 | /// `-Zunpretty=expanded,hygiene` |
6a06907d XL |
2651 | ExpandedHygiene, |
2652 | } | |
2653 | ||
2654 | #[derive(Copy, Clone, PartialEq, Debug)] | |
2655 | pub enum PpAstTreeMode { | |
2656 | /// `-Zunpretty=ast` | |
2657 | Normal, | |
2658 | /// `-Zunpretty=ast,expanded` | |
2659 | Expanded, | |
2660 | } | |
2661 | ||
2662 | #[derive(Copy, Clone, PartialEq, Debug)] | |
2663 | pub enum PpHirMode { | |
2664 | /// `-Zunpretty=hir` | |
2665 | Normal, | |
2666 | /// `-Zunpretty=hir,identified` | |
2667 | Identified, | |
2668 | /// `-Zunpretty=hir,typed` | |
2669 | Typed, | |
60c5eb7d XL |
2670 | } |
2671 | ||
2672 | #[derive(Copy, Clone, PartialEq, Debug)] | |
2673 | pub enum PpMode { | |
6a06907d | 2674 | /// Options that print the source code, i.e. |
5e7ed085 | 2675 | /// `-Zunpretty=normal` and `-Zunpretty=expanded` |
6a06907d XL |
2676 | Source(PpSourceMode), |
2677 | AstTree(PpAstTreeMode), | |
2678 | /// Options that print the HIR, i.e. `-Zunpretty=hir` | |
2679 | Hir(PpHirMode), | |
2680 | /// `-Zunpretty=hir-tree` | |
2681 | HirTree, | |
2682 | /// `-Zunpretty=thir-tree` | |
2683 | ThirTree, | |
2684 | /// `-Zunpretty=mir` | |
2685 | Mir, | |
2686 | /// `-Zunpretty=mir-cfg` | |
2687 | MirCFG, | |
60c5eb7d XL |
2688 | } |
2689 | ||
2690 | impl PpMode { | |
2691 | pub fn needs_ast_map(&self) -> bool { | |
2692 | use PpMode::*; | |
2693 | use PpSourceMode::*; | |
2694 | match *self { | |
6a06907d XL |
2695 | Source(Normal | Identified) | AstTree(PpAstTreeMode::Normal) => false, |
2696 | ||
5e7ed085 | 2697 | Source(Expanded | ExpandedIdentified | ExpandedHygiene) |
6a06907d XL |
2698 | | AstTree(PpAstTreeMode::Expanded) |
2699 | | Hir(_) | |
2700 | | HirTree | |
2701 | | ThirTree | |
2702 | | Mir | |
2703 | | MirCFG => true, | |
60c5eb7d XL |
2704 | } |
2705 | } | |
064997fb FG |
2706 | pub fn needs_hir(&self) -> bool { |
2707 | use PpMode::*; | |
2708 | match *self { | |
2709 | Source(_) | AstTree(_) => false, | |
2710 | ||
2711 | Hir(_) | HirTree | ThirTree | Mir | MirCFG => true, | |
2712 | } | |
2713 | } | |
60c5eb7d XL |
2714 | |
2715 | pub fn needs_analysis(&self) -> bool { | |
2716 | use PpMode::*; | |
cdc7bbd5 | 2717 | matches!(*self, Mir | MirCFG | ThirTree) |
60c5eb7d XL |
2718 | } |
2719 | } | |
2720 | ||
a1dfa0c6 | 2721 | /// Command-line arguments passed to the compiler have to be incorporated with |
5bcae85e SL |
2722 | /// the dependency tracking system for incremental compilation. This module |
2723 | /// provides some utilities to make this more convenient. | |
2724 | /// | |
a1dfa0c6 | 2725 | /// The values of all command-line arguments that are relevant for dependency |
5bcae85e SL |
2726 | /// tracking are hashed into a single value that determines whether the |
2727 | /// incremental compilation cache can be re-used or not. This hashing is done | |
e1599b0c XL |
2728 | /// via the `DepTrackingHash` trait defined below, since the standard `Hash` |
2729 | /// implementation might not be suitable (e.g., arguments are stored in a `Vec`, | |
5bcae85e SL |
2730 | /// the hash of which is order dependent, but we might not want the order of |
2731 | /// arguments to make a difference for the hash). | |
2732 | /// | |
e1599b0c | 2733 | /// However, since the value provided by `Hash::hash` often *is* suitable, |
5bcae85e | 2734 | /// especially for primitive types, there is the |
e1599b0c XL |
2735 | /// `impl_dep_tracking_hash_via_hash!()` macro that allows to simply reuse the |
2736 | /// `Hash` implementation for `DepTrackingHash`. It's important though that | |
5bcae85e | 2737 | /// we have an opt-in scheme here, so one is hopefully forced to think about |
a1dfa0c6 | 2738 | /// how the hash should be calculated when adding a new command-line argument. |
923072b8 | 2739 | pub(crate) mod dep_tracking { |
dfeec247 | 2740 | use super::{ |
5099ac24 | 2741 | BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, ErrorOutputType, |
5e7ed085 | 2742 | InstrumentCoverage, LdImpl, LinkerPluginLto, LocationDetail, LtoCli, OomStrategy, OptLevel, |
064997fb FG |
2743 | OutputType, OutputTypes, Passes, SourceFileHashAlgorithm, SplitDwarfKind, |
2744 | SwitchWithOptPath, SymbolManglingVersion, TrimmedDefPaths, | |
dfeec247 | 2745 | }; |
9fa01778 | 2746 | use crate::lint; |
5869c6ff | 2747 | use crate::options::WasiExecModel; |
17df50a5 | 2748 | use crate::utils::{NativeLib, NativeLibKind}; |
04454e1e | 2749 | use rustc_errors::LanguageIdentifier; |
dfeec247 XL |
2750 | use rustc_feature::UnstableFeatures; |
2751 | use rustc_span::edition::Edition; | |
94222f64 | 2752 | use rustc_span::RealFileName; |
f9f354fc | 2753 | use rustc_target::spec::{CodeModel, MergeFunctions, PanicStrategy, RelocModel}; |
3c0e092e XL |
2754 | use rustc_target::spec::{ |
2755 | RelroLevel, SanitizerSet, SplitDebuginfo, StackProtector, TargetTriple, TlsModel, | |
2756 | }; | |
dfeec247 | 2757 | use std::collections::hash_map::DefaultHasher; |
5bcae85e | 2758 | use std::collections::BTreeMap; |
9e0c209e | 2759 | use std::hash::Hash; |
6a06907d | 2760 | use std::num::NonZeroUsize; |
5bcae85e | 2761 | use std::path::PathBuf; |
5bcae85e SL |
2762 | |
2763 | pub trait DepTrackingHash { | |
136023e0 XL |
2764 | fn hash( |
2765 | &self, | |
2766 | hasher: &mut DefaultHasher, | |
2767 | error_format: ErrorOutputType, | |
2768 | for_crate_hash: bool, | |
2769 | ); | |
5bcae85e SL |
2770 | } |
2771 | ||
2772 | macro_rules! impl_dep_tracking_hash_via_hash { | |
17df50a5 | 2773 | ($($t:ty),+ $(,)?) => {$( |
5bcae85e | 2774 | impl DepTrackingHash for $t { |
136023e0 | 2775 | fn hash(&self, hasher: &mut DefaultHasher, _: ErrorOutputType, _for_crate_hash: bool) { |
5bcae85e SL |
2776 | Hash::hash(self, hasher); |
2777 | } | |
2778 | } | |
17df50a5 | 2779 | )+}; |
5bcae85e SL |
2780 | } |
2781 | ||
17df50a5 | 2782 | impl<T: DepTrackingHash> DepTrackingHash for Option<T> { |
136023e0 XL |
2783 | fn hash( |
2784 | &self, | |
2785 | hasher: &mut DefaultHasher, | |
2786 | error_format: ErrorOutputType, | |
2787 | for_crate_hash: bool, | |
2788 | ) { | |
17df50a5 XL |
2789 | match self { |
2790 | Some(x) => { | |
2791 | Hash::hash(&1, hasher); | |
136023e0 | 2792 | DepTrackingHash::hash(x, hasher, error_format, for_crate_hash); |
5bcae85e | 2793 | } |
17df50a5 | 2794 | None => Hash::hash(&0, hasher), |
5bcae85e | 2795 | } |
17df50a5 | 2796 | } |
5bcae85e SL |
2797 | } |
2798 | ||
17df50a5 XL |
2799 | impl_dep_tracking_hash_via_hash!( |
2800 | bool, | |
2801 | usize, | |
2802 | NonZeroUsize, | |
2803 | u64, | |
2804 | String, | |
2805 | PathBuf, | |
2806 | lint::Level, | |
2807 | WasiExecModel, | |
2808 | u32, | |
2809 | RelocModel, | |
2810 | CodeModel, | |
2811 | TlsModel, | |
2812 | InstrumentCoverage, | |
2813 | CrateType, | |
2814 | MergeFunctions, | |
2815 | PanicStrategy, | |
2816 | RelroLevel, | |
2817 | Passes, | |
2818 | OptLevel, | |
2819 | LtoCli, | |
2820 | DebugInfo, | |
2821 | UnstableFeatures, | |
17df50a5 XL |
2822 | NativeLib, |
2823 | NativeLibKind, | |
2824 | SanitizerSet, | |
2825 | CFGuard, | |
5099ac24 | 2826 | CFProtection, |
17df50a5 XL |
2827 | TargetTriple, |
2828 | Edition, | |
2829 | LinkerPluginLto, | |
2830 | SplitDebuginfo, | |
064997fb | 2831 | SplitDwarfKind, |
3c0e092e | 2832 | StackProtector, |
17df50a5 XL |
2833 | SwitchWithOptPath, |
2834 | SymbolManglingVersion, | |
2835 | SourceFileHashAlgorithm, | |
2836 | TrimmedDefPaths, | |
2837 | Option<LdImpl>, | |
136023e0 | 2838 | OutputType, |
94222f64 | 2839 | RealFileName, |
3c0e092e | 2840 | LocationDetail, |
5099ac24 | 2841 | BranchProtection, |
5e7ed085 | 2842 | OomStrategy, |
04454e1e | 2843 | LanguageIdentifier, |
17df50a5 | 2844 | ); |
5bcae85e SL |
2845 | |
2846 | impl<T1, T2> DepTrackingHash for (T1, T2) | |
0531ce1d XL |
2847 | where |
2848 | T1: DepTrackingHash, | |
2849 | T2: DepTrackingHash, | |
5bcae85e | 2850 | { |
136023e0 XL |
2851 | fn hash( |
2852 | &self, | |
2853 | hasher: &mut DefaultHasher, | |
2854 | error_format: ErrorOutputType, | |
2855 | for_crate_hash: bool, | |
2856 | ) { | |
5bcae85e | 2857 | Hash::hash(&0, hasher); |
136023e0 | 2858 | DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash); |
5bcae85e | 2859 | Hash::hash(&1, hasher); |
136023e0 | 2860 | DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash); |
5bcae85e SL |
2861 | } |
2862 | } | |
2863 | ||
476ff2be | 2864 | impl<T1, T2, T3> DepTrackingHash for (T1, T2, T3) |
0531ce1d XL |
2865 | where |
2866 | T1: DepTrackingHash, | |
2867 | T2: DepTrackingHash, | |
2868 | T3: DepTrackingHash, | |
476ff2be | 2869 | { |
136023e0 XL |
2870 | fn hash( |
2871 | &self, | |
2872 | hasher: &mut DefaultHasher, | |
2873 | error_format: ErrorOutputType, | |
2874 | for_crate_hash: bool, | |
2875 | ) { | |
476ff2be | 2876 | Hash::hash(&0, hasher); |
136023e0 | 2877 | DepTrackingHash::hash(&self.0, hasher, error_format, for_crate_hash); |
476ff2be | 2878 | Hash::hash(&1, hasher); |
136023e0 | 2879 | DepTrackingHash::hash(&self.1, hasher, error_format, for_crate_hash); |
476ff2be | 2880 | Hash::hash(&2, hasher); |
136023e0 | 2881 | DepTrackingHash::hash(&self.2, hasher, error_format, for_crate_hash); |
476ff2be SL |
2882 | } |
2883 | } | |
2884 | ||
17df50a5 | 2885 | impl<T: DepTrackingHash> DepTrackingHash for Vec<T> { |
136023e0 XL |
2886 | fn hash( |
2887 | &self, | |
2888 | hasher: &mut DefaultHasher, | |
2889 | error_format: ErrorOutputType, | |
2890 | for_crate_hash: bool, | |
2891 | ) { | |
17df50a5 XL |
2892 | Hash::hash(&self.len(), hasher); |
2893 | for (index, elem) in self.iter().enumerate() { | |
2894 | Hash::hash(&index, hasher); | |
136023e0 XL |
2895 | DepTrackingHash::hash(elem, hasher, error_format, for_crate_hash); |
2896 | } | |
2897 | } | |
2898 | } | |
2899 | ||
2900 | impl DepTrackingHash for OutputTypes { | |
2901 | fn hash( | |
2902 | &self, | |
2903 | hasher: &mut DefaultHasher, | |
2904 | error_format: ErrorOutputType, | |
2905 | for_crate_hash: bool, | |
2906 | ) { | |
2907 | Hash::hash(&self.0.len(), hasher); | |
2908 | for (key, val) in &self.0 { | |
2909 | DepTrackingHash::hash(key, hasher, error_format, for_crate_hash); | |
2910 | if !for_crate_hash { | |
2911 | DepTrackingHash::hash(val, hasher, error_format, for_crate_hash); | |
2912 | } | |
17df50a5 XL |
2913 | } |
2914 | } | |
2915 | } | |
2916 | ||
5bcae85e | 2917 | // This is a stable hash because BTreeMap is a sorted container |
923072b8 | 2918 | pub(crate) fn stable_hash( |
0531ce1d XL |
2919 | sub_hashes: BTreeMap<&'static str, &dyn DepTrackingHash>, |
2920 | hasher: &mut DefaultHasher, | |
2921 | error_format: ErrorOutputType, | |
136023e0 | 2922 | for_crate_hash: bool, |
0531ce1d | 2923 | ) { |
5bcae85e SL |
2924 | for (key, sub_hash) in sub_hashes { |
2925 | // Using Hash::hash() instead of DepTrackingHash::hash() is fine for | |
2926 | // the keys, as they are just plain strings | |
2927 | Hash::hash(&key.len(), hasher); | |
2928 | Hash::hash(key, hasher); | |
136023e0 | 2929 | sub_hash.hash(hasher, error_format, for_crate_hash); |
5bcae85e SL |
2930 | } |
2931 | } | |
2932 | } | |
5e7ed085 FG |
2933 | |
2934 | /// Default behavior to use in out-of-memory situations. | |
2935 | #[derive(Clone, Copy, PartialEq, Hash, Debug, Encodable, Decodable, HashStable_Generic)] | |
2936 | pub enum OomStrategy { | |
2937 | /// Generate a panic that can be caught by `catch_unwind`. | |
2938 | Panic, | |
2939 | ||
2940 | /// Abort the process immediately. | |
2941 | Abort, | |
2942 | } | |
2943 | ||
2944 | impl OomStrategy { | |
2945 | pub const SYMBOL: &'static str = "__rust_alloc_error_handler_should_panic"; | |
2946 | ||
2947 | pub fn should_panic(self) -> u8 { | |
2948 | match self { | |
2949 | OomStrategy::Panic => 1, | |
2950 | OomStrategy::Abort => 0, | |
2951 | } | |
2952 | } | |
2953 | } | |
064997fb FG |
2954 | |
2955 | /// How to run proc-macro code when building this crate | |
2956 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] | |
2957 | pub enum ProcMacroExecutionStrategy { | |
2958 | /// Run the proc-macro code on the same thread as the server. | |
2959 | SameThread, | |
2960 | ||
2961 | /// Run the proc-macro code on a different thread. | |
2962 | CrossThread, | |
2963 | } |