]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! Contains infrastructure for configuring the compiler, including parsing | |
12 | //! command line options. | |
13 | ||
14 | pub use self::EntryFnType::*; | |
15 | pub use self::CrateType::*; | |
16 | pub use self::Passes::*; | |
1a4d82fc JJ |
17 | pub use self::DebugInfoLevel::*; |
18 | ||
19 | use session::{early_error, early_warn, Session}; | |
20 | use session::search_paths::SearchPaths; | |
21 | ||
22 | use rustc_back::target::Target; | |
23 | use lint; | |
92a42be0 | 24 | use middle::cstore; |
1a4d82fc | 25 | |
b039eaaf | 26 | use syntax::ast::{self, IntTy, UintTy}; |
1a4d82fc JJ |
27 | use syntax::attr; |
28 | use syntax::attr::AttrMetaMethods; | |
9cc50fc6 | 29 | use syntax::errors::{ColorConfig, Handler}; |
1a4d82fc | 30 | use syntax::parse; |
7453a54e | 31 | use syntax::parse::lexer::Reader; |
1a4d82fc | 32 | use syntax::parse::token::InternedString; |
62682a34 | 33 | use syntax::feature_gate::UnstableFeatures; |
1a4d82fc | 34 | |
85aaf69f | 35 | use getopts; |
1a4d82fc | 36 | use std::collections::HashMap; |
85aaf69f | 37 | use std::env; |
1a4d82fc | 38 | use std::fmt; |
c34b1796 | 39 | use std::path::PathBuf; |
1a4d82fc | 40 | |
1a4d82fc JJ |
41 | pub struct Config { |
42 | pub target: Target, | |
43 | pub int_type: IntTy, | |
44 | pub uint_type: UintTy, | |
45 | } | |
46 | ||
47 | #[derive(Clone, Copy, PartialEq)] | |
48 | pub enum OptLevel { | |
49 | No, // -O0 | |
50 | Less, // -O1 | |
51 | Default, // -O2 | |
52 | Aggressive // -O3 | |
53 | } | |
54 | ||
55 | #[derive(Clone, Copy, PartialEq)] | |
56 | pub enum DebugInfoLevel { | |
57 | NoDebugInfo, | |
58 | LimitedDebugInfo, | |
59 | FullDebugInfo, | |
60 | } | |
61 | ||
b039eaaf | 62 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
1a4d82fc | 63 | pub enum OutputType { |
b039eaaf SL |
64 | Bitcode, |
65 | Assembly, | |
66 | LlvmAssembly, | |
67 | Object, | |
68 | Exe, | |
69 | DepInfo, | |
1a4d82fc JJ |
70 | } |
71 | ||
9cc50fc6 SL |
72 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] |
73 | pub enum ErrorOutputType { | |
74 | HumanReadable(ColorConfig), | |
75 | Json, | |
76 | } | |
77 | ||
78 | impl Default for ErrorOutputType { | |
79 | fn default() -> ErrorOutputType { | |
80 | ErrorOutputType::HumanReadable(ColorConfig::Auto) | |
81 | } | |
82 | } | |
83 | ||
92a42be0 SL |
84 | impl OutputType { |
85 | fn is_compatible_with_codegen_units_and_single_output_file(&self) -> bool { | |
86 | match *self { | |
87 | OutputType::Exe | | |
88 | OutputType::DepInfo => true, | |
89 | OutputType::Bitcode | | |
90 | OutputType::Assembly | | |
91 | OutputType::LlvmAssembly | | |
92 | OutputType::Object => false, | |
93 | } | |
94 | } | |
95 | ||
96 | fn shorthand(&self) -> &'static str { | |
97 | match *self { | |
98 | OutputType::Bitcode => "llvm-bc", | |
99 | OutputType::Assembly => "asm", | |
100 | OutputType::LlvmAssembly => "llvm-ir", | |
101 | OutputType::Object => "obj", | |
102 | OutputType::Exe => "link", | |
103 | OutputType::DepInfo => "dep-info", | |
104 | } | |
105 | } | |
106 | } | |
107 | ||
1a4d82fc JJ |
108 | #[derive(Clone)] |
109 | pub struct Options { | |
110 | // The crate config requested for the session, which may be combined | |
111 | // with additional crate configurations during the compile process | |
112 | pub crate_types: Vec<CrateType>, | |
113 | ||
114 | pub gc: bool, | |
115 | pub optimize: OptLevel, | |
c34b1796 | 116 | pub debug_assertions: bool, |
1a4d82fc JJ |
117 | pub debuginfo: DebugInfoLevel, |
118 | pub lint_opts: Vec<(String, lint::Level)>, | |
c1a9b12d | 119 | pub lint_cap: Option<lint::Level>, |
1a4d82fc | 120 | pub describe_lints: bool, |
b039eaaf | 121 | pub output_types: HashMap<OutputType, Option<PathBuf>>, |
1a4d82fc JJ |
122 | // This was mutable for rustpkg, which updates search paths based on the |
123 | // parsed code. It remains mutable in case its replacements wants to use | |
124 | // this. | |
125 | pub search_paths: SearchPaths, | |
126 | pub libs: Vec<(String, cstore::NativeLibraryKind)>, | |
c34b1796 | 127 | pub maybe_sysroot: Option<PathBuf>, |
1a4d82fc JJ |
128 | pub target_triple: String, |
129 | // User-specified cfg meta items. The compiler itself will add additional | |
130 | // items to the crate config, and during parsing the entire crate config | |
131 | // will be added to the crate AST node. This should not be used for | |
132 | // anything except building the full crate config prior to parsing. | |
133 | pub cfg: ast::CrateConfig, | |
134 | pub test: bool, | |
135 | pub parse_only: bool, | |
136 | pub no_trans: bool, | |
9cc50fc6 | 137 | pub error_format: ErrorOutputType, |
c34b1796 | 138 | pub treat_err_as_bug: bool, |
7453a54e SL |
139 | pub continue_parse_after_error: bool, |
140 | pub mir_opt_level: usize, | |
141 | ||
54a0048b SL |
142 | /// if Some, enable incremental compilation, using the given |
143 | /// directory to store intermediate results | |
144 | pub incremental: Option<PathBuf>, | |
7453a54e | 145 | |
1a4d82fc JJ |
146 | pub no_analysis: bool, |
147 | pub debugging_opts: DebuggingOptions, | |
1a4d82fc JJ |
148 | pub prints: Vec<PrintRequest>, |
149 | pub cg: CodegenOptions, | |
1a4d82fc JJ |
150 | pub externs: HashMap<String, Vec<String>>, |
151 | pub crate_name: Option<String>, | |
152 | /// An optional name to use as the crate for std during std injection, | |
153 | /// written `extern crate std = "name"`. Default to "std". Used by | |
154 | /// out-of-tree drivers. | |
155 | pub alt_std_name: Option<String>, | |
156 | /// Indicates how the compiler should treat unstable features | |
157 | pub unstable_features: UnstableFeatures | |
158 | } | |
159 | ||
1a4d82fc | 160 | #[derive(Clone, PartialEq, Eq)] |
1a4d82fc JJ |
161 | pub enum PrintRequest { |
162 | FileNames, | |
163 | Sysroot, | |
164 | CrateName, | |
7453a54e SL |
165 | Cfg, |
166 | TargetList, | |
1a4d82fc JJ |
167 | } |
168 | ||
169 | pub enum Input { | |
170 | /// Load source from file | |
c34b1796 | 171 | File(PathBuf), |
54a0048b SL |
172 | Str { |
173 | /// String that is shown in place of a filename | |
174 | name: String, | |
175 | /// Anonymous source string | |
176 | input: String, | |
177 | }, | |
1a4d82fc JJ |
178 | } |
179 | ||
180 | impl Input { | |
181 | pub fn filestem(&self) -> String { | |
182 | match *self { | |
c34b1796 AL |
183 | Input::File(ref ifile) => ifile.file_stem().unwrap() |
184 | .to_str().unwrap().to_string(), | |
54a0048b | 185 | Input::Str { .. } => "rust_out".to_string(), |
1a4d82fc JJ |
186 | } |
187 | } | |
188 | } | |
189 | ||
190 | #[derive(Clone)] | |
191 | pub struct OutputFilenames { | |
c34b1796 | 192 | pub out_directory: PathBuf, |
1a4d82fc | 193 | pub out_filestem: String, |
c34b1796 | 194 | pub single_output_file: Option<PathBuf>, |
1a4d82fc | 195 | pub extra: String, |
b039eaaf | 196 | pub outputs: HashMap<OutputType, Option<PathBuf>>, |
1a4d82fc JJ |
197 | } |
198 | ||
199 | impl OutputFilenames { | |
c34b1796 | 200 | pub fn path(&self, flavor: OutputType) -> PathBuf { |
b039eaaf SL |
201 | self.outputs.get(&flavor).and_then(|p| p.to_owned()) |
202 | .or_else(|| self.single_output_file.clone()) | |
203 | .unwrap_or_else(|| self.temp_path(flavor)) | |
1a4d82fc JJ |
204 | } |
205 | ||
c34b1796 AL |
206 | pub fn temp_path(&self, flavor: OutputType) -> PathBuf { |
207 | let base = self.out_directory.join(&self.filestem()); | |
1a4d82fc | 208 | match flavor { |
b039eaaf SL |
209 | OutputType::Bitcode => base.with_extension("bc"), |
210 | OutputType::Assembly => base.with_extension("s"), | |
211 | OutputType::LlvmAssembly => base.with_extension("ll"), | |
212 | OutputType::Object => base.with_extension("o"), | |
213 | OutputType::DepInfo => base.with_extension("d"), | |
214 | OutputType::Exe => base, | |
1a4d82fc JJ |
215 | } |
216 | } | |
217 | ||
c34b1796 AL |
218 | pub fn with_extension(&self, extension: &str) -> PathBuf { |
219 | self.out_directory.join(&self.filestem()).with_extension(extension) | |
1a4d82fc JJ |
220 | } |
221 | ||
222 | pub fn filestem(&self) -> String { | |
223 | format!("{}{}", self.out_filestem, self.extra) | |
224 | } | |
225 | } | |
226 | ||
227 | pub fn host_triple() -> &'static str { | |
228 | // Get the host triple out of the build environment. This ensures that our | |
229 | // idea of the host triple is the same as for the set of libraries we've | |
230 | // actually built. We can't just take LLVM's host triple because they | |
231 | // normalize all ix86 architectures to i386. | |
232 | // | |
233 | // Instead of grabbing the host triple (for the current host), we grab (at | |
234 | // compile time) the target triple that this rustc is built with and | |
235 | // calling that (at runtime) the host triple. | |
236 | (option_env!("CFG_COMPILER_HOST_TRIPLE")). | |
237 | expect("CFG_COMPILER_HOST_TRIPLE") | |
238 | } | |
239 | ||
240 | /// Some reasonable defaults | |
241 | pub fn basic_options() -> Options { | |
242 | Options { | |
243 | crate_types: Vec::new(), | |
244 | gc: false, | |
9cc50fc6 | 245 | optimize: OptLevel::No, |
1a4d82fc JJ |
246 | debuginfo: NoDebugInfo, |
247 | lint_opts: Vec::new(), | |
c1a9b12d | 248 | lint_cap: None, |
1a4d82fc | 249 | describe_lints: false, |
b039eaaf | 250 | output_types: HashMap::new(), |
1a4d82fc JJ |
251 | search_paths: SearchPaths::new(), |
252 | maybe_sysroot: None, | |
253 | target_triple: host_triple().to_string(), | |
254 | cfg: Vec::new(), | |
255 | test: false, | |
256 | parse_only: false, | |
257 | no_trans: false, | |
c34b1796 | 258 | treat_err_as_bug: false, |
7453a54e SL |
259 | continue_parse_after_error: false, |
260 | mir_opt_level: 1, | |
54a0048b | 261 | incremental: None, |
1a4d82fc JJ |
262 | no_analysis: false, |
263 | debugging_opts: basic_debugging_options(), | |
1a4d82fc JJ |
264 | prints: Vec::new(), |
265 | cg: basic_codegen_options(), | |
9cc50fc6 | 266 | error_format: ErrorOutputType::default(), |
1a4d82fc JJ |
267 | externs: HashMap::new(), |
268 | crate_name: None, | |
269 | alt_std_name: None, | |
270 | libs: Vec::new(), | |
c34b1796 AL |
271 | unstable_features: UnstableFeatures::Disallow, |
272 | debug_assertions: true, | |
1a4d82fc JJ |
273 | } |
274 | } | |
275 | ||
54a0048b SL |
276 | impl Options { |
277 | /// True if there is a reason to build the dep graph. | |
278 | pub fn build_dep_graph(&self) -> bool { | |
279 | self.incremental.is_some() || | |
280 | self.debugging_opts.dump_dep_graph || | |
281 | self.debugging_opts.query_dep_graph | |
282 | } | |
283 | } | |
284 | ||
1a4d82fc JJ |
285 | // The type of entry function, so |
286 | // users can have their own entry | |
287 | // functions that don't start a | |
288 | // scheduler | |
c34b1796 | 289 | #[derive(Copy, Clone, PartialEq)] |
1a4d82fc JJ |
290 | pub enum EntryFnType { |
291 | EntryMain, | |
292 | EntryStart, | |
293 | EntryNone, | |
294 | } | |
295 | ||
85aaf69f | 296 | #[derive(Copy, PartialEq, PartialOrd, Clone, Ord, Eq, Hash, Debug)] |
1a4d82fc JJ |
297 | pub enum CrateType { |
298 | CrateTypeExecutable, | |
299 | CrateTypeDylib, | |
300 | CrateTypeRlib, | |
301 | CrateTypeStaticlib, | |
302 | } | |
303 | ||
1a4d82fc JJ |
304 | #[derive(Clone)] |
305 | pub enum Passes { | |
306 | SomePasses(Vec<String>), | |
307 | AllPasses, | |
308 | } | |
309 | ||
310 | impl Passes { | |
311 | pub fn is_empty(&self) -> bool { | |
312 | match *self { | |
313 | SomePasses(ref v) => v.is_empty(), | |
314 | AllPasses => false, | |
315 | } | |
316 | } | |
317 | } | |
318 | ||
319 | /// Declare a macro that will define all CodegenOptions/DebuggingOptions fields and parsers all | |
320 | /// at once. The goal of this macro is to define an interface that can be | |
321 | /// programmatically used by the option parser in order to initialize the struct | |
322 | /// without hardcoding field names all over the place. | |
323 | /// | |
324 | /// The goal is to invoke this macro once with the correct fields, and then this | |
325 | /// macro generates all necessary code. The main gotcha of this macro is the | |
326 | /// cgsetters module which is a bunch of generated code to parse an option into | |
327 | /// its respective field in the struct. There are a few hand-written parsers for | |
328 | /// parsing specific types of values in this module. | |
329 | macro_rules! options { | |
330 | ($struct_name:ident, $setter_name:ident, $defaultfn:ident, | |
331 | $buildfn:ident, $prefix:expr, $outputname:expr, | |
332 | $stat:ident, $mod_desc:ident, $mod_set:ident, | |
333 | $($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) => | |
334 | ( | |
335 | #[derive(Clone)] | |
1a4d82fc JJ |
336 | pub struct $struct_name { $(pub $opt: $t),* } |
337 | ||
338 | pub fn $defaultfn() -> $struct_name { | |
339 | $struct_name { $($opt: $init),* } | |
340 | } | |
341 | ||
9cc50fc6 | 342 | pub fn $buildfn(matches: &getopts::Matches, error_format: ErrorOutputType) -> $struct_name |
1a4d82fc JJ |
343 | { |
344 | let mut op = $defaultfn(); | |
85aaf69f | 345 | for option in matches.opt_strs($prefix) { |
c34b1796 | 346 | let mut iter = option.splitn(2, '='); |
1a4d82fc JJ |
347 | let key = iter.next().unwrap(); |
348 | let value = iter.next(); | |
349 | let option_to_lookup = key.replace("-", "_"); | |
350 | let mut found = false; | |
85aaf69f | 351 | for &(candidate, setter, opt_type_desc, _) in $stat { |
1a4d82fc JJ |
352 | if option_to_lookup != candidate { continue } |
353 | if !setter(&mut op, value) { | |
354 | match (value, opt_type_desc) { | |
355 | (Some(..), None) => { | |
9cc50fc6 SL |
356 | early_error(error_format, &format!("{} option `{}` takes no \ |
357 | value", $outputname, key)) | |
1a4d82fc JJ |
358 | } |
359 | (None, Some(type_desc)) => { | |
9cc50fc6 SL |
360 | early_error(error_format, &format!("{0} option `{1}` requires \ |
361 | {2} ({3} {1}=<value>)", | |
362 | $outputname, key, | |
363 | type_desc, $prefix)) | |
1a4d82fc JJ |
364 | } |
365 | (Some(value), Some(type_desc)) => { | |
9cc50fc6 SL |
366 | early_error(error_format, &format!("incorrect value `{}` for {} \ |
367 | option `{}` - {} was expected", | |
368 | value, $outputname, | |
369 | key, type_desc)) | |
1a4d82fc | 370 | } |
54a0048b | 371 | (None, None) => bug!() |
1a4d82fc JJ |
372 | } |
373 | } | |
374 | found = true; | |
375 | break; | |
376 | } | |
377 | if !found { | |
9cc50fc6 SL |
378 | early_error(error_format, &format!("unknown {} option: `{}`", |
379 | $outputname, key)); | |
1a4d82fc JJ |
380 | } |
381 | } | |
382 | return op; | |
383 | } | |
384 | ||
385 | pub type $setter_name = fn(&mut $struct_name, v: Option<&str>) -> bool; | |
386 | pub const $stat: &'static [(&'static str, $setter_name, | |
387 | Option<&'static str>, &'static str)] = | |
388 | &[ $( (stringify!($opt), $mod_set::$opt, $mod_desc::$parse, $desc) ),* ]; | |
389 | ||
390 | #[allow(non_upper_case_globals, dead_code)] | |
391 | mod $mod_desc { | |
392 | pub const parse_bool: Option<&'static str> = None; | |
c34b1796 AL |
393 | pub const parse_opt_bool: Option<&'static str> = |
394 | Some("one of: `y`, `yes`, `on`, `n`, `no`, or `off`"); | |
1a4d82fc JJ |
395 | pub const parse_string: Option<&'static str> = Some("a string"); |
396 | pub const parse_opt_string: Option<&'static str> = Some("a string"); | |
397 | pub const parse_list: Option<&'static str> = Some("a space-separated list of strings"); | |
398 | pub const parse_opt_list: Option<&'static str> = Some("a space-separated list of strings"); | |
399 | pub const parse_uint: Option<&'static str> = Some("a number"); | |
400 | pub const parse_passes: Option<&'static str> = | |
401 | Some("a space-separated list of passes, or `all`"); | |
402 | pub const parse_opt_uint: Option<&'static str> = | |
403 | Some("a number"); | |
404 | } | |
405 | ||
406 | #[allow(dead_code)] | |
407 | mod $mod_set { | |
408 | use super::{$struct_name, Passes, SomePasses, AllPasses}; | |
409 | ||
410 | $( | |
411 | pub fn $opt(cg: &mut $struct_name, v: Option<&str>) -> bool { | |
412 | $parse(&mut cg.$opt, v) | |
413 | } | |
414 | )* | |
415 | ||
416 | fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool { | |
417 | match v { | |
418 | Some(..) => false, | |
419 | None => { *slot = true; true } | |
420 | } | |
421 | } | |
422 | ||
423 | fn parse_opt_bool(slot: &mut Option<bool>, v: Option<&str>) -> bool { | |
424 | match v { | |
c34b1796 AL |
425 | Some(s) => { |
426 | match s { | |
427 | "n" | "no" | "off" => { | |
428 | *slot = Some(false); | |
429 | } | |
430 | "y" | "yes" | "on" => { | |
431 | *slot = Some(true); | |
432 | } | |
433 | _ => { return false; } | |
434 | } | |
435 | ||
436 | true | |
437 | }, | |
1a4d82fc JJ |
438 | None => { *slot = Some(true); true } |
439 | } | |
440 | } | |
441 | ||
442 | fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool { | |
443 | match v { | |
444 | Some(s) => { *slot = Some(s.to_string()); true }, | |
445 | None => false, | |
446 | } | |
447 | } | |
448 | ||
449 | fn parse_string(slot: &mut String, v: Option<&str>) -> bool { | |
450 | match v { | |
451 | Some(s) => { *slot = s.to_string(); true }, | |
452 | None => false, | |
453 | } | |
454 | } | |
455 | ||
456 | fn parse_list(slot: &mut Vec<String>, v: Option<&str>) | |
457 | -> bool { | |
458 | match v { | |
459 | Some(s) => { | |
d9579d0f | 460 | for s in s.split_whitespace() { |
1a4d82fc JJ |
461 | slot.push(s.to_string()); |
462 | } | |
463 | true | |
464 | }, | |
465 | None => false, | |
466 | } | |
467 | } | |
468 | ||
469 | fn parse_opt_list(slot: &mut Option<Vec<String>>, v: Option<&str>) | |
470 | -> bool { | |
471 | match v { | |
472 | Some(s) => { | |
d9579d0f | 473 | let v = s.split_whitespace().map(|s| s.to_string()).collect(); |
1a4d82fc JJ |
474 | *slot = Some(v); |
475 | true | |
476 | }, | |
477 | None => false, | |
478 | } | |
479 | } | |
480 | ||
c34b1796 | 481 | fn parse_uint(slot: &mut usize, v: Option<&str>) -> bool { |
85aaf69f | 482 | match v.and_then(|s| s.parse().ok()) { |
1a4d82fc JJ |
483 | Some(i) => { *slot = i; true }, |
484 | None => false | |
485 | } | |
486 | } | |
487 | ||
c34b1796 | 488 | fn parse_opt_uint(slot: &mut Option<usize>, v: Option<&str>) -> bool { |
1a4d82fc | 489 | match v { |
85aaf69f | 490 | Some(s) => { *slot = s.parse().ok(); slot.is_some() } |
1a4d82fc JJ |
491 | None => { *slot = None; true } |
492 | } | |
493 | } | |
494 | ||
495 | fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool { | |
496 | match v { | |
497 | Some("all") => { | |
498 | *slot = AllPasses; | |
499 | true | |
500 | } | |
501 | v => { | |
502 | let mut passes = vec!(); | |
503 | if parse_list(&mut passes, v) { | |
504 | *slot = SomePasses(passes); | |
505 | true | |
506 | } else { | |
507 | false | |
508 | } | |
509 | } | |
510 | } | |
511 | } | |
512 | } | |
513 | ) } | |
514 | ||
515 | options! {CodegenOptions, CodegenSetter, basic_codegen_options, | |
516 | build_codegen_options, "C", "codegen", | |
517 | CG_OPTIONS, cg_type_desc, cgsetters, | |
518 | ar: Option<String> = (None, parse_opt_string, | |
519 | "tool to assemble archives with"), | |
520 | linker: Option<String> = (None, parse_opt_string, | |
521 | "system linker to link outputs with"), | |
522 | link_args: Option<Vec<String>> = (None, parse_opt_list, | |
523 | "extra arguments to pass to the linker (space separated)"), | |
7453a54e SL |
524 | link_dead_code: bool = (false, parse_bool, |
525 | "don't let linker strip dead code (turning it on can be used for code coverage)"), | |
1a4d82fc JJ |
526 | lto: bool = (false, parse_bool, |
527 | "perform LLVM link-time optimizations"), | |
528 | target_cpu: Option<String> = (None, parse_opt_string, | |
529 | "select target processor (llc -mcpu=help for details)"), | |
530 | target_feature: String = ("".to_string(), parse_string, | |
531 | "target specific attributes (llc -mattr=help for details)"), | |
532 | passes: Vec<String> = (Vec::new(), parse_list, | |
533 | "a list of extra LLVM passes to run (space separated)"), | |
534 | llvm_args: Vec<String> = (Vec::new(), parse_list, | |
535 | "a list of arguments to pass to llvm (space separated)"), | |
536 | save_temps: bool = (false, parse_bool, | |
537 | "save all temporary output files during compilation"), | |
538 | rpath: bool = (false, parse_bool, | |
539 | "set rpath values in libs/exes"), | |
540 | no_prepopulate_passes: bool = (false, parse_bool, | |
541 | "don't pre-populate the pass manager with a list of passes"), | |
542 | no_vectorize_loops: bool = (false, parse_bool, | |
543 | "don't run the loop vectorization optimization passes"), | |
544 | no_vectorize_slp: bool = (false, parse_bool, | |
545 | "don't run LLVM's SLP vectorization pass"), | |
546 | soft_float: bool = (false, parse_bool, | |
547 | "generate software floating point library calls"), | |
548 | prefer_dynamic: bool = (false, parse_bool, | |
549 | "prefer dynamic linking to static linking"), | |
550 | no_integrated_as: bool = (false, parse_bool, | |
551 | "use an external assembler rather than LLVM's integrated one"), | |
552 | no_redzone: Option<bool> = (None, parse_opt_bool, | |
553 | "disable the use of the redzone"), | |
554 | relocation_model: Option<String> = (None, parse_opt_string, | |
555 | "choose the relocation model to use (llc -relocation-model for details)"), | |
556 | code_model: Option<String> = (None, parse_opt_string, | |
557 | "choose the code model to use (llc -code-model for details)"), | |
558 | metadata: Vec<String> = (Vec::new(), parse_list, | |
559 | "metadata to mangle symbol names with"), | |
560 | extra_filename: String = ("".to_string(), parse_string, | |
561 | "extra data to put in each output filename"), | |
c34b1796 | 562 | codegen_units: usize = (1, parse_uint, |
1a4d82fc JJ |
563 | "divide crate into N units to optimize in parallel"), |
564 | remark: Passes = (SomePasses(Vec::new()), parse_passes, | |
565 | "print remarks for these optimization passes (space separated, or \"all\")"), | |
566 | no_stack_check: bool = (false, parse_bool, | |
567 | "disable checks for stack exhaustion (a memory-safety hazard!)"), | |
c34b1796 | 568 | debuginfo: Option<usize> = (None, parse_opt_uint, |
1a4d82fc JJ |
569 | "debug info emission level, 0 = no debug info, 1 = line tables only, \ |
570 | 2 = full debug info with variable and type information"), | |
c34b1796 | 571 | opt_level: Option<usize> = (None, parse_opt_uint, |
92a42be0 | 572 | "optimize with possible levels 0-3"), |
c34b1796 AL |
573 | debug_assertions: Option<bool> = (None, parse_opt_bool, |
574 | "explicitly enable the cfg(debug_assertions) directive"), | |
92a42be0 SL |
575 | inline_threshold: Option<usize> = (None, parse_opt_uint, |
576 | "set the inlining threshold for"), | |
1a4d82fc JJ |
577 | } |
578 | ||
579 | ||
580 | options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, | |
581 | build_debugging_options, "Z", "debugging", | |
582 | DB_OPTIONS, db_type_desc, dbsetters, | |
583 | verbose: bool = (false, parse_bool, | |
584 | "in general, enable more debug printouts"), | |
585 | time_passes: bool = (false, parse_bool, | |
586 | "measure time of each rustc pass"), | |
587 | count_llvm_insns: bool = (false, parse_bool, | |
588 | "count where LLVM instrs originate"), | |
589 | time_llvm_passes: bool = (false, parse_bool, | |
590 | "measure time of each LLVM pass"), | |
92a42be0 SL |
591 | input_stats: bool = (false, parse_bool, |
592 | "gather statistics about the input"), | |
1a4d82fc JJ |
593 | trans_stats: bool = (false, parse_bool, |
594 | "gather trans statistics"), | |
595 | asm_comments: bool = (false, parse_bool, | |
596 | "generate comments into the assembly (may change behavior)"), | |
597 | no_verify: bool = (false, parse_bool, | |
598 | "skip LLVM verification"), | |
599 | borrowck_stats: bool = (false, parse_bool, | |
600 | "gather borrowck statistics"), | |
601 | no_landing_pads: bool = (false, parse_bool, | |
602 | "omit landing pads for unwinding"), | |
603 | debug_llvm: bool = (false, parse_bool, | |
604 | "enable debug output from LLVM"), | |
605 | count_type_sizes: bool = (false, parse_bool, | |
606 | "count the sizes of aggregate types"), | |
607 | meta_stats: bool = (false, parse_bool, | |
608 | "gather metadata statistics"), | |
609 | print_link_args: bool = (false, parse_bool, | |
92a42be0 | 610 | "print the arguments passed to the linker"), |
1a4d82fc | 611 | gc: bool = (false, parse_bool, |
92a42be0 | 612 | "garbage collect shared data (experimental)"), |
1a4d82fc | 613 | print_llvm_passes: bool = (false, parse_bool, |
92a42be0 | 614 | "prints the llvm optimization passes being run"), |
1a4d82fc | 615 | ast_json: bool = (false, parse_bool, |
92a42be0 | 616 | "print the AST as JSON and halt"), |
1a4d82fc | 617 | ast_json_noexpand: bool = (false, parse_bool, |
92a42be0 | 618 | "print the pre-expansion AST as JSON and halt"), |
1a4d82fc | 619 | ls: bool = (false, parse_bool, |
92a42be0 | 620 | "list the symbols defined by a library crate"), |
1a4d82fc | 621 | save_analysis: bool = (false, parse_bool, |
92a42be0 | 622 | "write syntax and type analysis information in addition to normal output"), |
1a4d82fc | 623 | print_move_fragments: bool = (false, parse_bool, |
92a42be0 | 624 | "print out move-fragment data for every fn"), |
1a4d82fc | 625 | flowgraph_print_loans: bool = (false, parse_bool, |
92a42be0 | 626 | "include loan analysis data in --unpretty flowgraph output"), |
1a4d82fc | 627 | flowgraph_print_moves: bool = (false, parse_bool, |
92a42be0 | 628 | "include move analysis data in --unpretty flowgraph output"), |
1a4d82fc | 629 | flowgraph_print_assigns: bool = (false, parse_bool, |
92a42be0 | 630 | "include assignment analysis data in --unpretty flowgraph output"), |
1a4d82fc | 631 | flowgraph_print_all: bool = (false, parse_bool, |
92a42be0 | 632 | "include all dataflow analysis data in --unpretty flowgraph output"), |
1a4d82fc | 633 | print_region_graph: bool = (false, parse_bool, |
92a42be0 | 634 | "prints region inference graph. \ |
1a4d82fc JJ |
635 | Use with RUST_REGION_GRAPH=help for more info"), |
636 | parse_only: bool = (false, parse_bool, | |
92a42be0 | 637 | "parse only; do not compile, assemble, or link"), |
1a4d82fc | 638 | no_trans: bool = (false, parse_bool, |
92a42be0 | 639 | "run all passes except translation; no output"), |
c34b1796 | 640 | treat_err_as_bug: bool = (false, parse_bool, |
92a42be0 | 641 | "treat all errors that occur as bugs"), |
7453a54e SL |
642 | continue_parse_after_error: bool = (false, parse_bool, |
643 | "attempt to recover from parse errors (experimental)"), | |
54a0048b | 644 | incremental: Option<String> = (None, parse_opt_string, |
9cc50fc6 SL |
645 | "enable incremental compilation (experimental)"), |
646 | dump_dep_graph: bool = (false, parse_bool, | |
647 | "dump the dependency graph to $RUST_DEP_GRAPH (default: /tmp/dep_graph.gv)"), | |
54a0048b SL |
648 | query_dep_graph: bool = (false, parse_bool, |
649 | "enable queries of the dependency graph for regression testing"), | |
1a4d82fc | 650 | no_analysis: bool = (false, parse_bool, |
92a42be0 | 651 | "parse and expand the source, but run no analysis"), |
1a4d82fc JJ |
652 | extra_plugins: Vec<String> = (Vec::new(), parse_list, |
653 | "load extra plugins"), | |
654 | unstable_options: bool = (false, parse_bool, | |
92a42be0 | 655 | "adds unstable command line options to rustc interface"), |
1a4d82fc | 656 | print_enum_sizes: bool = (false, parse_bool, |
92a42be0 | 657 | "print the size of enums and their variants"), |
c34b1796 | 658 | force_overflow_checks: Option<bool> = (None, parse_opt_bool, |
92a42be0 | 659 | "force overflow checks on or off"), |
c34b1796 | 660 | force_dropflag_checks: Option<bool> = (None, parse_opt_bool, |
92a42be0 | 661 | "force drop flag checks on or off"), |
d9579d0f | 662 | trace_macros: bool = (false, parse_bool, |
92a42be0 | 663 | "for every macro invocation, print its name and arguments"), |
c1a9b12d | 664 | enable_nonzeroing_move_hints: bool = (false, parse_bool, |
92a42be0 | 665 | "force nonzeroing move optimization on"), |
b039eaaf | 666 | keep_mtwt_tables: bool = (false, parse_bool, |
92a42be0 | 667 | "don't clear the resolution tables after analysis"), |
9cc50fc6 SL |
668 | keep_ast: bool = (false, parse_bool, |
669 | "keep the AST after lowering it to HIR"), | |
670 | show_span: Option<String> = (None, parse_opt_string, | |
671 | "show spans for compiler debugging (expr|pat|ty)"), | |
7453a54e SL |
672 | print_trans_items: Option<String> = (None, parse_opt_string, |
673 | "print the result of the translation item collection pass"), | |
674 | mir_opt_level: Option<usize> = (None, parse_opt_uint, | |
675 | "set the MIR optimization level (0-3)"), | |
54a0048b SL |
676 | dump_mir: Option<String> = (None, parse_opt_string, |
677 | "dump MIR state at various points in translation"), | |
678 | orbit: bool = (false, parse_bool, | |
679 | "get MIR where it belongs - everywhere; most importantly, in orbit"), | |
1a4d82fc JJ |
680 | } |
681 | ||
682 | pub fn default_lib_output() -> CrateType { | |
683 | CrateTypeRlib | |
684 | } | |
685 | ||
686 | pub fn default_configuration(sess: &Session) -> ast::CrateConfig { | |
687 | use syntax::parse::token::intern_and_get_ident as intern; | |
688 | ||
c34b1796 AL |
689 | let end = &sess.target.target.target_endian; |
690 | let arch = &sess.target.target.arch; | |
691 | let wordsz = &sess.target.target.target_pointer_width; | |
692 | let os = &sess.target.target.target_os; | |
d9579d0f | 693 | let env = &sess.target.target.target_env; |
b039eaaf | 694 | let vendor = &sess.target.target.target_vendor; |
1a4d82fc | 695 | |
92a42be0 SL |
696 | let fam = if let Some(ref fam) = sess.target.target.options.target_family { |
697 | intern(fam) | |
698 | } else if sess.target.target.options.is_like_windows { | |
699 | InternedString::new("windows") | |
700 | } else { | |
701 | InternedString::new("unix") | |
1a4d82fc JJ |
702 | }; |
703 | ||
704 | let mk = attr::mk_name_value_item_str; | |
c34b1796 | 705 | let mut ret = vec![ // Target bindings. |
92a42be0 SL |
706 | mk(InternedString::new("target_os"), intern(os)), |
707 | mk(InternedString::new("target_family"), fam.clone()), | |
708 | mk(InternedString::new("target_arch"), intern(arch)), | |
709 | mk(InternedString::new("target_endian"), intern(end)), | |
710 | mk(InternedString::new("target_pointer_width"), intern(wordsz)), | |
711 | mk(InternedString::new("target_env"), intern(env)), | |
712 | mk(InternedString::new("target_vendor"), intern(vendor)), | |
c34b1796 | 713 | ]; |
92a42be0 SL |
714 | match &fam[..] { |
715 | "windows" | "unix" => ret.push(attr::mk_word_item(fam)), | |
716 | _ => (), | |
717 | } | |
9cc50fc6 SL |
718 | if sess.target.target.options.has_elf_tls { |
719 | ret.push(attr::mk_word_item(InternedString::new("target_thread_local"))); | |
720 | } | |
c34b1796 AL |
721 | if sess.opts.debug_assertions { |
722 | ret.push(attr::mk_word_item(InternedString::new("debug_assertions"))); | |
723 | } | |
724 | return ret; | |
1a4d82fc JJ |
725 | } |
726 | ||
727 | pub fn append_configuration(cfg: &mut ast::CrateConfig, | |
728 | name: InternedString) { | |
729 | if !cfg.iter().any(|mi| mi.name() == name) { | |
730 | cfg.push(attr::mk_word_item(name)) | |
731 | } | |
732 | } | |
733 | ||
734 | pub fn build_configuration(sess: &Session) -> ast::CrateConfig { | |
735 | // Combine the configuration requested by the session (command line) with | |
736 | // some default and generated configuration items | |
737 | let default_cfg = default_configuration(sess); | |
738 | let mut user_cfg = sess.opts.cfg.clone(); | |
739 | // If the user wants a test runner, then add the test cfg | |
740 | if sess.opts.test { | |
741 | append_configuration(&mut user_cfg, InternedString::new("test")) | |
742 | } | |
743 | let mut v = user_cfg.into_iter().collect::<Vec<_>>(); | |
92a42be0 | 744 | v.extend_from_slice(&default_cfg[..]); |
1a4d82fc JJ |
745 | v |
746 | } | |
747 | ||
9cc50fc6 | 748 | pub fn build_target_config(opts: &Options, sp: &Handler) -> Config { |
c34b1796 | 749 | let target = match Target::search(&opts.target_triple) { |
1a4d82fc JJ |
750 | Ok(t) => t, |
751 | Err(e) => { | |
9cc50fc6 | 752 | panic!(sp.fatal(&format!("Error loading target specification: {}", e))); |
d9579d0f | 753 | } |
1a4d82fc JJ |
754 | }; |
755 | ||
c34b1796 | 756 | let (int_type, uint_type) = match &target.target_pointer_width[..] { |
7453a54e SL |
757 | "32" => (ast::IntTy::I32, ast::UintTy::U32), |
758 | "64" => (ast::IntTy::I64, ast::UintTy::U64), | |
9cc50fc6 SL |
759 | w => panic!(sp.fatal(&format!("target specification was invalid: \ |
760 | unrecognized target-pointer-width {}", w))), | |
1a4d82fc JJ |
761 | }; |
762 | ||
763 | Config { | |
764 | target: target, | |
765 | int_type: int_type, | |
766 | uint_type: uint_type, | |
767 | } | |
768 | } | |
769 | ||
85aaf69f | 770 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] |
7453a54e SL |
771 | pub enum OptionStability { |
772 | Stable, | |
773 | ||
774 | // FIXME: historically there were some options which were either `-Z` or | |
775 | // required the `-Z unstable-options` flag, which were all intended | |
776 | // to be unstable. Unfortunately we didn't actually gate usage of | |
777 | // these options on the stable compiler, so we still allow them there | |
778 | // today. There are some warnings printed out about this in the | |
779 | // driver. | |
780 | UnstableButNotReally, | |
781 | ||
782 | Unstable, | |
783 | } | |
1a4d82fc JJ |
784 | |
785 | #[derive(Clone, PartialEq, Eq)] | |
786 | pub struct RustcOptGroup { | |
787 | pub opt_group: getopts::OptGroup, | |
788 | pub stability: OptionStability, | |
789 | } | |
790 | ||
791 | impl RustcOptGroup { | |
792 | pub fn is_stable(&self) -> bool { | |
793 | self.stability == OptionStability::Stable | |
794 | } | |
795 | ||
54a0048b | 796 | pub fn stable(g: getopts::OptGroup) -> RustcOptGroup { |
1a4d82fc JJ |
797 | RustcOptGroup { opt_group: g, stability: OptionStability::Stable } |
798 | } | |
799 | ||
7453a54e | 800 | #[allow(dead_code)] // currently we have no "truly unstable" options |
54a0048b | 801 | pub fn unstable(g: getopts::OptGroup) -> RustcOptGroup { |
1a4d82fc JJ |
802 | RustcOptGroup { opt_group: g, stability: OptionStability::Unstable } |
803 | } | |
7453a54e SL |
804 | |
805 | fn unstable_bnr(g: getopts::OptGroup) -> RustcOptGroup { | |
806 | RustcOptGroup { | |
807 | opt_group: g, | |
808 | stability: OptionStability::UnstableButNotReally, | |
809 | } | |
810 | } | |
1a4d82fc JJ |
811 | } |
812 | ||
813 | // The `opt` local module holds wrappers around the `getopts` API that | |
814 | // adds extra rustc-specific metadata to each option; such metadata | |
815 | // is exposed by . The public | |
816 | // functions below ending with `_u` are the functions that return | |
817 | // *unstable* options, i.e. options that are only enabled when the | |
818 | // user also passes the `-Z unstable-options` debugging flag. | |
819 | mod opt { | |
820 | // The `fn opt_u` etc below are written so that we can use them | |
821 | // in the future; do not warn about them not being used right now. | |
822 | #![allow(dead_code)] | |
823 | ||
824 | use getopts; | |
825 | use super::RustcOptGroup; | |
826 | ||
c34b1796 AL |
827 | pub type R = RustcOptGroup; |
828 | pub type S<'a> = &'a str; | |
1a4d82fc JJ |
829 | |
830 | fn stable(g: getopts::OptGroup) -> R { RustcOptGroup::stable(g) } | |
831 | fn unstable(g: getopts::OptGroup) -> R { RustcOptGroup::unstable(g) } | |
7453a54e | 832 | fn unstable_bnr(g: getopts::OptGroup) -> R { RustcOptGroup::unstable_bnr(g) } |
1a4d82fc | 833 | |
7453a54e SL |
834 | pub fn opt_s(a: S, b: S, c: S, d: S) -> R { |
835 | stable(getopts::optopt(a, b, c, d)) | |
836 | } | |
837 | pub fn multi_s(a: S, b: S, c: S, d: S) -> R { | |
838 | stable(getopts::optmulti(a, b, c, d)) | |
839 | } | |
840 | pub fn flag_s(a: S, b: S, c: S) -> R { | |
841 | stable(getopts::optflag(a, b, c)) | |
842 | } | |
843 | pub fn flagopt_s(a: S, b: S, c: S, d: S) -> R { | |
844 | stable(getopts::optflagopt(a, b, c, d)) | |
845 | } | |
846 | pub fn flagmulti_s(a: S, b: S, c: S) -> R { | |
847 | stable(getopts::optflagmulti(a, b, c)) | |
848 | } | |
d9579d0f | 849 | |
7453a54e SL |
850 | pub fn opt(a: S, b: S, c: S, d: S) -> R { |
851 | unstable(getopts::optopt(a, b, c, d)) | |
852 | } | |
853 | pub fn multi(a: S, b: S, c: S, d: S) -> R { | |
854 | unstable(getopts::optmulti(a, b, c, d)) | |
855 | } | |
856 | pub fn flag(a: S, b: S, c: S) -> R { | |
857 | unstable(getopts::optflag(a, b, c)) | |
858 | } | |
859 | pub fn flagopt(a: S, b: S, c: S, d: S) -> R { | |
860 | unstable(getopts::optflagopt(a, b, c, d)) | |
861 | } | |
862 | pub fn flagmulti(a: S, b: S, c: S) -> R { | |
863 | unstable(getopts::optflagmulti(a, b, c)) | |
864 | } | |
1a4d82fc | 865 | |
7453a54e SL |
866 | // Do not use these functions for any new options added to the compiler, all |
867 | // new options should use the `*_u` variants above to be truly unstable. | |
868 | pub fn opt_ubnr(a: S, b: S, c: S, d: S) -> R { | |
869 | unstable_bnr(getopts::optopt(a, b, c, d)) | |
870 | } | |
871 | pub fn multi_ubnr(a: S, b: S, c: S, d: S) -> R { | |
872 | unstable_bnr(getopts::optmulti(a, b, c, d)) | |
873 | } | |
874 | pub fn flag_ubnr(a: S, b: S, c: S) -> R { | |
875 | unstable_bnr(getopts::optflag(a, b, c)) | |
876 | } | |
877 | pub fn flagopt_ubnr(a: S, b: S, c: S, d: S) -> R { | |
878 | unstable_bnr(getopts::optflagopt(a, b, c, d)) | |
879 | } | |
880 | pub fn flagmulti_ubnr(a: S, b: S, c: S) -> R { | |
881 | unstable_bnr(getopts::optflagmulti(a, b, c)) | |
882 | } | |
1a4d82fc JJ |
883 | } |
884 | ||
885 | /// Returns the "short" subset of the rustc command line options, | |
886 | /// including metadata for each option, such as whether the option is | |
887 | /// part of the stable long-term interface for rustc. | |
888 | pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> { | |
889 | vec![ | |
7453a54e SL |
890 | opt::flag_s("h", "help", "Display this message"), |
891 | opt::multi_s("", "cfg", "Configure the compilation environment", "SPEC"), | |
892 | opt::multi_s("L", "", "Add a directory to the library search path", | |
85aaf69f | 893 | "[KIND=]PATH"), |
7453a54e | 894 | opt::multi_s("l", "", "Link the generated crate(s) to the specified native |
1a4d82fc JJ |
895 | library NAME. The optional KIND can be one of, |
896 | static, dylib, or framework. If omitted, dylib is | |
897 | assumed.", "[KIND=]NAME"), | |
7453a54e | 898 | opt::multi_s("", "crate-type", "Comma separated list of types of crates |
1a4d82fc JJ |
899 | for the compiler to emit", |
900 | "[bin|lib|rlib|dylib|staticlib]"), | |
7453a54e | 901 | opt::opt_s("", "crate-name", "Specify the name of the crate being built", |
1a4d82fc | 902 | "NAME"), |
7453a54e | 903 | opt::multi_s("", "emit", "Comma separated list of types of output for \ |
1a4d82fc JJ |
904 | the compiler to emit", |
905 | "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"), | |
7453a54e | 906 | opt::multi_s("", "print", "Comma separated list of compiler information to \ |
1a4d82fc | 907 | print on stdout", |
54a0048b | 908 | "[crate-name|file-names|sysroot|cfg|target-list]"), |
7453a54e SL |
909 | opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), |
910 | opt::flagmulti_s("O", "", "Equivalent to -C opt-level=2"), | |
911 | opt::opt_s("o", "", "Write output to <filename>", "FILENAME"), | |
912 | opt::opt_s("", "out-dir", "Write output to compiler-chosen filename \ | |
1a4d82fc | 913 | in <dir>", "DIR"), |
7453a54e | 914 | opt::opt_s("", "explain", "Provide a detailed explanation of an error \ |
1a4d82fc | 915 | message", "OPT"), |
7453a54e SL |
916 | opt::flag_s("", "test", "Build a test harness"), |
917 | opt::opt_s("", "target", "Target triple for which the code is compiled", "TARGET"), | |
918 | opt::multi_s("W", "warn", "Set lint warnings", "OPT"), | |
919 | opt::multi_s("A", "allow", "Set lint allowed", "OPT"), | |
920 | opt::multi_s("D", "deny", "Set lint denied", "OPT"), | |
921 | opt::multi_s("F", "forbid", "Set lint forbidden", "OPT"), | |
922 | opt::multi_s("", "cap-lints", "Set the most restrictive lint level. \ | |
c1a9b12d SL |
923 | More restrictive lints are capped at this \ |
924 | level", "LEVEL"), | |
7453a54e SL |
925 | opt::multi_s("C", "codegen", "Set a codegen option", "OPT[=VALUE]"), |
926 | opt::flag_s("V", "version", "Print version info and exit"), | |
927 | opt::flag_s("v", "verbose", "Use verbose output"), | |
1a4d82fc JJ |
928 | ] |
929 | } | |
930 | ||
931 | /// Returns all rustc command line options, including metadata for | |
932 | /// each option, such as whether the option is part of the stable | |
933 | /// long-term interface for rustc. | |
934 | pub fn rustc_optgroups() -> Vec<RustcOptGroup> { | |
935 | let mut opts = rustc_short_optgroups(); | |
92a42be0 | 936 | opts.extend_from_slice(&[ |
54a0048b SL |
937 | opt::multi_s("", "extern", "Specify where an external rust library is located", |
938 | "NAME=PATH"), | |
7453a54e SL |
939 | opt::opt_s("", "sysroot", "Override the system root", "PATH"), |
940 | opt::multi_ubnr("Z", "", "Set internal debugging options", "FLAG"), | |
941 | opt::opt_ubnr("", "error-format", | |
942 | "How errors and other messages are produced", | |
943 | "human|json"), | |
944 | opt::opt_s("", "color", "Configure coloring of output: | |
54a0048b SL |
945 | auto = colorize, if output goes to a tty (default); |
946 | always = always colorize output; | |
947 | never = never colorize output", "auto|always|never"), | |
1a4d82fc | 948 | |
7453a54e | 949 | opt::flagopt_ubnr("", "pretty", |
54a0048b SL |
950 | "Pretty-print the input instead of compiling; |
951 | valid types are: `normal` (un-annotated source), | |
952 | `expanded` (crates expanded), or | |
953 | `expanded,identified` (fully parenthesized, AST nodes with IDs).", | |
954 | "TYPE"), | |
7453a54e | 955 | opt::flagopt_ubnr("", "unpretty", |
54a0048b SL |
956 | "Present the input source, unstable (and less-pretty) variants; |
957 | valid types are any of the types for `--pretty`, as well as: | |
958 | `flowgraph=<nodeid>` (graphviz formatted flowgraph for node), | |
959 | `everybody_loops` (all function bodies replaced with `loop {}`), | |
960 | `hir` (the HIR), `hir,identified`, or | |
961 | `hir,typed` (HIR with types for each node).", | |
962 | "TYPE"), | |
7453a54e SL |
963 | |
964 | // new options here should **not** use the `_ubnr` functions, all new | |
965 | // unstable options should use the short variants to indicate that they | |
966 | // are truly unstable. All `_ubnr` flags are just that way because they | |
967 | // were so historically. | |
968 | // | |
969 | // You may also wish to keep this comment at the bottom of this list to | |
970 | // ensure that others see it. | |
1a4d82fc JJ |
971 | ]); |
972 | opts | |
973 | } | |
974 | ||
975 | // Convert strings provided as --cfg [cfgspec] into a crate_cfg | |
976 | pub fn parse_cfgspecs(cfgspecs: Vec<String> ) -> ast::CrateConfig { | |
977 | cfgspecs.into_iter().map(|s| { | |
7453a54e SL |
978 | let sess = parse::ParseSess::new(); |
979 | let mut parser = parse::new_parser_from_source_str(&sess, | |
980 | Vec::new(), | |
981 | "cfgspec".to_string(), | |
982 | s.to_string()); | |
983 | let meta_item = panictry!(parser.parse_meta_item()); | |
984 | ||
985 | if !parser.reader.is_eof() { | |
986 | early_error(ErrorOutputType::default(), &format!("invalid --cfg argument: {}", | |
987 | s)) | |
988 | } | |
989 | ||
990 | meta_item | |
1a4d82fc JJ |
991 | }).collect::<ast::CrateConfig>() |
992 | } | |
993 | ||
994 | pub fn build_session_options(matches: &getopts::Matches) -> Options { | |
e9174d1e | 995 | let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) { |
9cc50fc6 SL |
996 | Some("auto") => ColorConfig::Auto, |
997 | Some("always") => ColorConfig::Always, | |
998 | Some("never") => ColorConfig::Never, | |
e9174d1e | 999 | |
9cc50fc6 | 1000 | None => ColorConfig::Auto, |
e9174d1e SL |
1001 | |
1002 | Some(arg) => { | |
9cc50fc6 SL |
1003 | early_error(ErrorOutputType::default(), &format!("argument for --color must be auto, \ |
1004 | always or never (instead was `{}`)", | |
1005 | arg)) | |
1006 | } | |
1007 | }; | |
1008 | ||
1009 | // We need the opts_present check because the driver will send us Matches | |
1010 | // with only stable options if no unstable options are used. Since error-format | |
1011 | // is unstable, it will not be present. We have to use opts_present not | |
1012 | // opt_present because the latter will panic. | |
1013 | let error_format = if matches.opts_present(&["error-format".to_owned()]) { | |
1014 | match matches.opt_str("error-format").as_ref().map(|s| &s[..]) { | |
1015 | Some("human") => ErrorOutputType::HumanReadable(color), | |
1016 | Some("json") => ErrorOutputType::Json, | |
1017 | ||
1018 | None => ErrorOutputType::HumanReadable(color), | |
1019 | ||
1020 | Some(arg) => { | |
1021 | early_error(ErrorOutputType::HumanReadable(color), | |
1022 | &format!("argument for --error-format must be human or json (instead \ | |
1023 | was `{}`)", | |
1024 | arg)) | |
1025 | } | |
e9174d1e | 1026 | } |
9cc50fc6 SL |
1027 | } else { |
1028 | ErrorOutputType::HumanReadable(color) | |
e9174d1e SL |
1029 | }; |
1030 | ||
1a4d82fc JJ |
1031 | let unparsed_crate_types = matches.opt_strs("crate-type"); |
1032 | let crate_types = parse_crate_types_from_list(unparsed_crate_types) | |
9cc50fc6 | 1033 | .unwrap_or_else(|e| early_error(error_format, &e[..])); |
1a4d82fc JJ |
1034 | |
1035 | let mut lint_opts = vec!(); | |
1036 | let mut describe_lints = false; | |
1037 | ||
85aaf69f SL |
1038 | for &level in &[lint::Allow, lint::Warn, lint::Deny, lint::Forbid] { |
1039 | for lint_name in matches.opt_strs(level.as_str()) { | |
1a4d82fc JJ |
1040 | if lint_name == "help" { |
1041 | describe_lints = true; | |
1042 | } else { | |
1043 | lint_opts.push((lint_name.replace("-", "_"), level)); | |
1044 | } | |
1045 | } | |
1046 | } | |
1047 | ||
c1a9b12d SL |
1048 | let lint_cap = matches.opt_str("cap-lints").map(|cap| { |
1049 | lint::Level::from_str(&cap).unwrap_or_else(|| { | |
9cc50fc6 | 1050 | early_error(error_format, &format!("unknown lint level: `{}`", cap)) |
c1a9b12d SL |
1051 | }) |
1052 | }); | |
1053 | ||
9cc50fc6 | 1054 | let debugging_opts = build_debugging_options(matches, error_format); |
1a4d82fc | 1055 | |
85aaf69f SL |
1056 | let parse_only = debugging_opts.parse_only; |
1057 | let no_trans = debugging_opts.no_trans; | |
c34b1796 | 1058 | let treat_err_as_bug = debugging_opts.treat_err_as_bug; |
7453a54e SL |
1059 | let continue_parse_after_error = debugging_opts.continue_parse_after_error; |
1060 | let mir_opt_level = debugging_opts.mir_opt_level.unwrap_or(1); | |
85aaf69f | 1061 | let no_analysis = debugging_opts.no_analysis; |
1a4d82fc | 1062 | |
b039eaaf | 1063 | let mut output_types = HashMap::new(); |
1a4d82fc | 1064 | if !debugging_opts.parse_only && !no_trans { |
b039eaaf SL |
1065 | for list in matches.opt_strs("emit") { |
1066 | for output_type in list.split(',') { | |
1067 | let mut parts = output_type.splitn(2, '='); | |
1068 | let output_type = match parts.next().unwrap() { | |
1069 | "asm" => OutputType::Assembly, | |
1070 | "llvm-ir" => OutputType::LlvmAssembly, | |
1071 | "llvm-bc" => OutputType::Bitcode, | |
1072 | "obj" => OutputType::Object, | |
1073 | "link" => OutputType::Exe, | |
1074 | "dep-info" => OutputType::DepInfo, | |
1075 | part => { | |
9cc50fc6 | 1076 | early_error(error_format, &format!("unknown emission type: `{}`", |
e9174d1e | 1077 | part)) |
1a4d82fc JJ |
1078 | } |
1079 | }; | |
b039eaaf SL |
1080 | let path = parts.next().map(PathBuf::from); |
1081 | output_types.insert(output_type, path); | |
1a4d82fc JJ |
1082 | } |
1083 | } | |
1084 | }; | |
9346a6ac | 1085 | if output_types.is_empty() { |
b039eaaf | 1086 | output_types.insert(OutputType::Exe, None); |
1a4d82fc JJ |
1087 | } |
1088 | ||
9cc50fc6 | 1089 | let mut cg = build_codegen_options(matches, error_format); |
92a42be0 SL |
1090 | |
1091 | // Issue #30063: if user requests llvm-related output to one | |
1092 | // particular path, disable codegen-units. | |
1093 | if matches.opt_present("o") && cg.codegen_units != 1 { | |
1094 | let incompatible: Vec<_> = output_types.iter() | |
1095 | .map(|ot_path| ot_path.0) | |
1096 | .filter(|ot| { | |
1097 | !ot.is_compatible_with_codegen_units_and_single_output_file() | |
1098 | }).collect(); | |
1099 | if !incompatible.is_empty() { | |
1100 | for ot in &incompatible { | |
9cc50fc6 SL |
1101 | early_warn(error_format, &format!("--emit={} with -o incompatible with \ |
1102 | -C codegen-units=N for N > 1", | |
1103 | ot.shorthand())); | |
92a42be0 | 1104 | } |
9cc50fc6 | 1105 | early_warn(error_format, "resetting to default -C codegen-units=1"); |
92a42be0 SL |
1106 | cg.codegen_units = 1; |
1107 | } | |
1108 | } | |
1109 | ||
54a0048b SL |
1110 | if cg.codegen_units < 1 { |
1111 | early_error(error_format, "Value for codegen units must be a positive nonzero integer"); | |
1112 | } | |
1113 | ||
92a42be0 | 1114 | let cg = cg; |
1a4d82fc | 1115 | |
c34b1796 | 1116 | let sysroot_opt = matches.opt_str("sysroot").map(|m| PathBuf::from(&m)); |
1a4d82fc JJ |
1117 | let target = matches.opt_str("target").unwrap_or( |
1118 | host_triple().to_string()); | |
1119 | let opt_level = { | |
1120 | if matches.opt_present("O") { | |
1a4d82fc | 1121 | if cg.opt_level.is_some() { |
9cc50fc6 | 1122 | early_error(error_format, "-O and -C opt-level both provided"); |
1a4d82fc | 1123 | } |
9cc50fc6 | 1124 | OptLevel::Default |
1a4d82fc JJ |
1125 | } else { |
1126 | match cg.opt_level { | |
9cc50fc6 SL |
1127 | None => OptLevel::No, |
1128 | Some(0) => OptLevel::No, | |
1129 | Some(1) => OptLevel::Less, | |
1130 | Some(2) => OptLevel::Default, | |
1131 | Some(3) => OptLevel::Aggressive, | |
1a4d82fc | 1132 | Some(arg) => { |
9cc50fc6 SL |
1133 | early_error(error_format, &format!("optimization level needs to be \ |
1134 | between 0-3 (instead was `{}`)", | |
1135 | arg)); | |
1a4d82fc JJ |
1136 | } |
1137 | } | |
1138 | } | |
1139 | }; | |
9cc50fc6 | 1140 | let debug_assertions = cg.debug_assertions.unwrap_or(opt_level == OptLevel::No); |
1a4d82fc JJ |
1141 | let gc = debugging_opts.gc; |
1142 | let debuginfo = if matches.opt_present("g") { | |
1a4d82fc | 1143 | if cg.debuginfo.is_some() { |
9cc50fc6 | 1144 | early_error(error_format, "-g and -C debuginfo both provided"); |
1a4d82fc JJ |
1145 | } |
1146 | FullDebugInfo | |
1a4d82fc JJ |
1147 | } else { |
1148 | match cg.debuginfo { | |
1149 | None | Some(0) => NoDebugInfo, | |
1150 | Some(1) => LimitedDebugInfo, | |
1151 | Some(2) => FullDebugInfo, | |
1152 | Some(arg) => { | |
9cc50fc6 SL |
1153 | early_error(error_format, &format!("debug info level needs to be between \ |
1154 | 0-2 (instead was `{}`)", | |
1155 | arg)); | |
1a4d82fc JJ |
1156 | } |
1157 | } | |
1158 | }; | |
1159 | ||
1160 | let mut search_paths = SearchPaths::new(); | |
85aaf69f | 1161 | for s in &matches.opt_strs("L") { |
9cc50fc6 | 1162 | search_paths.add_path(&s[..], error_format); |
1a4d82fc JJ |
1163 | } |
1164 | ||
1165 | let libs = matches.opt_strs("l").into_iter().map(|s| { | |
c34b1796 | 1166 | let mut parts = s.splitn(2, '='); |
1a4d82fc JJ |
1167 | let kind = parts.next().unwrap(); |
1168 | let (name, kind) = match (parts.next(), kind) { | |
1169 | (None, name) | | |
1170 | (Some(name), "dylib") => (name, cstore::NativeUnknown), | |
1171 | (Some(name), "framework") => (name, cstore::NativeFramework), | |
1172 | (Some(name), "static") => (name, cstore::NativeStatic), | |
1173 | (_, s) => { | |
9cc50fc6 SL |
1174 | early_error(error_format, &format!("unknown library kind `{}`, expected \ |
1175 | one of dylib, framework, or static", | |
1176 | s)); | |
1a4d82fc JJ |
1177 | } |
1178 | }; | |
1179 | (name.to_string(), kind) | |
1180 | }).collect(); | |
1181 | ||
1182 | let cfg = parse_cfgspecs(matches.opt_strs("cfg")); | |
1183 | let test = matches.opt_present("test"); | |
1a4d82fc | 1184 | |
85aaf69f SL |
1185 | let prints = matches.opt_strs("print").into_iter().map(|s| { |
1186 | match &*s { | |
1a4d82fc JJ |
1187 | "crate-name" => PrintRequest::CrateName, |
1188 | "file-names" => PrintRequest::FileNames, | |
1189 | "sysroot" => PrintRequest::Sysroot, | |
7453a54e SL |
1190 | "cfg" => PrintRequest::Cfg, |
1191 | "target-list" => PrintRequest::TargetList, | |
1a4d82fc | 1192 | req => { |
9cc50fc6 | 1193 | early_error(error_format, &format!("unknown print request `{}`", req)) |
1a4d82fc JJ |
1194 | } |
1195 | } | |
1196 | }).collect::<Vec<_>>(); | |
1a4d82fc JJ |
1197 | |
1198 | if !cg.remark.is_empty() && debuginfo == NoDebugInfo { | |
9cc50fc6 SL |
1199 | early_warn(error_format, "-C remark will not show source locations without \ |
1200 | --debuginfo"); | |
1a4d82fc JJ |
1201 | } |
1202 | ||
1a4d82fc | 1203 | let mut externs = HashMap::new(); |
85aaf69f | 1204 | for arg in &matches.opt_strs("extern") { |
c34b1796 | 1205 | let mut parts = arg.splitn(2, '='); |
1a4d82fc JJ |
1206 | let name = match parts.next() { |
1207 | Some(s) => s, | |
9cc50fc6 | 1208 | None => early_error(error_format, "--extern value must not be empty"), |
1a4d82fc JJ |
1209 | }; |
1210 | let location = match parts.next() { | |
1211 | Some(s) => s, | |
9cc50fc6 | 1212 | None => early_error(error_format, "--extern value must be of the format `foo=bar`"), |
1a4d82fc JJ |
1213 | }; |
1214 | ||
c34b1796 | 1215 | externs.entry(name.to_string()).or_insert(vec![]).push(location.to_string()); |
1a4d82fc JJ |
1216 | } |
1217 | ||
1218 | let crate_name = matches.opt_str("crate-name"); | |
1219 | ||
54a0048b SL |
1220 | let incremental = debugging_opts.incremental.as_ref().map(|m| PathBuf::from(m)); |
1221 | ||
1a4d82fc JJ |
1222 | Options { |
1223 | crate_types: crate_types, | |
1224 | gc: gc, | |
1225 | optimize: opt_level, | |
1226 | debuginfo: debuginfo, | |
1227 | lint_opts: lint_opts, | |
c1a9b12d | 1228 | lint_cap: lint_cap, |
1a4d82fc JJ |
1229 | describe_lints: describe_lints, |
1230 | output_types: output_types, | |
1231 | search_paths: search_paths, | |
1232 | maybe_sysroot: sysroot_opt, | |
1233 | target_triple: target, | |
1234 | cfg: cfg, | |
1235 | test: test, | |
1236 | parse_only: parse_only, | |
1237 | no_trans: no_trans, | |
c34b1796 | 1238 | treat_err_as_bug: treat_err_as_bug, |
7453a54e SL |
1239 | continue_parse_after_error: continue_parse_after_error, |
1240 | mir_opt_level: mir_opt_level, | |
54a0048b | 1241 | incremental: incremental, |
1a4d82fc JJ |
1242 | no_analysis: no_analysis, |
1243 | debugging_opts: debugging_opts, | |
1a4d82fc JJ |
1244 | prints: prints, |
1245 | cg: cg, | |
9cc50fc6 | 1246 | error_format: error_format, |
1a4d82fc JJ |
1247 | externs: externs, |
1248 | crate_name: crate_name, | |
1249 | alt_std_name: None, | |
1250 | libs: libs, | |
85aaf69f | 1251 | unstable_features: get_unstable_features_setting(), |
c34b1796 | 1252 | debug_assertions: debug_assertions, |
85aaf69f SL |
1253 | } |
1254 | } | |
1255 | ||
1256 | pub fn get_unstable_features_setting() -> UnstableFeatures { | |
1257 | // Whether this is a feature-staged build, i.e. on the beta or stable channel | |
1258 | let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some(); | |
1259 | // The secret key needed to get through the rustc build itself by | |
1260 | // subverting the unstable features lints | |
1261 | let bootstrap_secret_key = option_env!("CFG_BOOTSTRAP_KEY"); | |
1262 | // The matching key to the above, only known by the build system | |
1263 | let bootstrap_provided_key = env::var("RUSTC_BOOTSTRAP_KEY").ok(); | |
1264 | match (disable_unstable_features, bootstrap_secret_key, bootstrap_provided_key) { | |
1265 | (_, Some(ref s), Some(ref p)) if s == p => UnstableFeatures::Cheat, | |
1266 | (true, _, _) => UnstableFeatures::Disallow, | |
62682a34 | 1267 | (false, _, _) => UnstableFeatures::Allow |
1a4d82fc JJ |
1268 | } |
1269 | } | |
1270 | ||
1271 | pub fn parse_crate_types_from_list(list_list: Vec<String>) -> Result<Vec<CrateType>, String> { | |
1a4d82fc | 1272 | let mut crate_types: Vec<CrateType> = Vec::new(); |
85aaf69f | 1273 | for unparsed_crate_type in &list_list { |
1a4d82fc JJ |
1274 | for part in unparsed_crate_type.split(',') { |
1275 | let new_part = match part { | |
1276 | "lib" => default_lib_output(), | |
1277 | "rlib" => CrateTypeRlib, | |
1278 | "staticlib" => CrateTypeStaticlib, | |
1279 | "dylib" => CrateTypeDylib, | |
1280 | "bin" => CrateTypeExecutable, | |
1281 | _ => { | |
1282 | return Err(format!("unknown crate type: `{}`", | |
1283 | part)); | |
1284 | } | |
1285 | }; | |
85aaf69f SL |
1286 | if !crate_types.contains(&new_part) { |
1287 | crate_types.push(new_part) | |
1288 | } | |
1a4d82fc JJ |
1289 | } |
1290 | } | |
1291 | ||
1292 | return Ok(crate_types); | |
1293 | } | |
1294 | ||
54a0048b SL |
1295 | pub mod nightly_options { |
1296 | use getopts; | |
1297 | use syntax::feature_gate::UnstableFeatures; | |
1298 | use super::{ErrorOutputType, OptionStability, RustcOptGroup, get_unstable_features_setting}; | |
1299 | use session::{early_error, early_warn}; | |
1300 | ||
1301 | pub fn is_unstable_enabled(matches: &getopts::Matches) -> bool { | |
1302 | is_nightly_build() && matches.opt_strs("Z").iter().any(|x| *x == "unstable-options") | |
1303 | } | |
1304 | ||
1305 | fn is_nightly_build() -> bool { | |
1306 | match get_unstable_features_setting() { | |
1307 | UnstableFeatures::Allow | UnstableFeatures::Cheat => true, | |
1308 | _ => false, | |
1309 | } | |
1310 | } | |
1311 | ||
1312 | pub fn check_nightly_options(matches: &getopts::Matches, flags: &[RustcOptGroup]) { | |
1313 | let has_z_unstable_option = matches.opt_strs("Z").iter().any(|x| *x == "unstable-options"); | |
1314 | let really_allows_unstable_options = match get_unstable_features_setting() { | |
1315 | UnstableFeatures::Disallow => false, | |
1316 | _ => true, | |
1317 | }; | |
1318 | ||
1319 | for opt in flags.iter() { | |
1320 | if opt.stability == OptionStability::Stable { | |
1321 | continue | |
1322 | } | |
1323 | let opt_name = if opt.opt_group.long_name.is_empty() { | |
1324 | &opt.opt_group.short_name | |
1325 | } else { | |
1326 | &opt.opt_group.long_name | |
1327 | }; | |
1328 | if !matches.opt_present(opt_name) { | |
1329 | continue | |
1330 | } | |
1331 | if opt_name != "Z" && !has_z_unstable_option { | |
1332 | early_error(ErrorOutputType::default(), | |
1333 | &format!("the `-Z unstable-options` flag must also be passed to enable \ | |
1334 | the flag `{}`", | |
1335 | opt_name)); | |
1336 | } | |
1337 | if really_allows_unstable_options { | |
1338 | continue | |
1339 | } | |
1340 | match opt.stability { | |
1341 | OptionStability::Unstable => { | |
1342 | let msg = format!("the option `{}` is only accepted on the \ | |
1343 | nightly compiler", opt_name); | |
1344 | early_error(ErrorOutputType::default(), &msg); | |
1345 | } | |
1346 | OptionStability::UnstableButNotReally => { | |
1347 | let msg = format!("the option `{}` is is unstable and should \ | |
1348 | only be used on the nightly compiler, but \ | |
1349 | it is currently accepted for backwards \ | |
1350 | compatibility; this will soon change, \ | |
1351 | see issue #31847 for more details", | |
1352 | opt_name); | |
1353 | early_warn(ErrorOutputType::default(), &msg); | |
1354 | } | |
1355 | OptionStability::Stable => {} | |
1356 | } | |
1357 | } | |
1358 | } | |
1359 | } | |
1360 | ||
85aaf69f | 1361 | impl fmt::Display for CrateType { |
1a4d82fc JJ |
1362 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1363 | match *self { | |
1364 | CrateTypeExecutable => "bin".fmt(f), | |
1365 | CrateTypeDylib => "dylib".fmt(f), | |
1366 | CrateTypeRlib => "rlib".fmt(f), | |
1367 | CrateTypeStaticlib => "staticlib".fmt(f) | |
1368 | } | |
1369 | } | |
1370 | } | |
1371 | ||
1372 | #[cfg(test)] | |
d9579d0f | 1373 | mod tests { |
92a42be0 | 1374 | use middle::cstore::DummyCrateStore; |
7453a54e | 1375 | use session::config::{build_configuration, build_session_options}; |
1a4d82fc JJ |
1376 | use session::build_session; |
1377 | ||
92a42be0 | 1378 | use std::rc::Rc; |
7453a54e | 1379 | use getopts::{getopts, OptGroup}; |
1a4d82fc JJ |
1380 | use syntax::attr; |
1381 | use syntax::attr::AttrMetaMethods; | |
1382 | use syntax::diagnostics; | |
1383 | ||
7453a54e SL |
1384 | fn optgroups() -> Vec<OptGroup> { |
1385 | super::rustc_optgroups().into_iter() | |
1386 | .map(|a| a.opt_group) | |
1387 | .collect() | |
1388 | } | |
1389 | ||
1a4d82fc JJ |
1390 | // When the user supplies --test we should implicitly supply --cfg test |
1391 | #[test] | |
1392 | fn test_switch_implies_cfg_test() { | |
1393 | let matches = | |
c34b1796 | 1394 | &match getopts(&["--test".to_string()], &optgroups()) { |
1a4d82fc JJ |
1395 | Ok(m) => m, |
1396 | Err(f) => panic!("test_switch_implies_cfg_test: {}", f) | |
1397 | }; | |
1398 | let registry = diagnostics::registry::Registry::new(&[]); | |
1399 | let sessopts = build_session_options(matches); | |
92a42be0 | 1400 | let sess = build_session(sessopts, None, registry, Rc::new(DummyCrateStore)); |
1a4d82fc | 1401 | let cfg = build_configuration(&sess); |
85aaf69f | 1402 | assert!((attr::contains_name(&cfg[..], "test"))); |
1a4d82fc JJ |
1403 | } |
1404 | ||
1405 | // When the user supplies --test and --cfg test, don't implicitly add | |
1406 | // another --cfg test | |
1407 | #[test] | |
1408 | fn test_switch_implies_cfg_test_unless_cfg_test() { | |
1409 | let matches = | |
1410 | &match getopts(&["--test".to_string(), "--cfg=test".to_string()], | |
c34b1796 | 1411 | &optgroups()) { |
1a4d82fc JJ |
1412 | Ok(m) => m, |
1413 | Err(f) => { | |
1414 | panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f) | |
1415 | } | |
1416 | }; | |
1417 | let registry = diagnostics::registry::Registry::new(&[]); | |
1418 | let sessopts = build_session_options(matches); | |
92a42be0 SL |
1419 | let sess = build_session(sessopts, None, registry, |
1420 | Rc::new(DummyCrateStore)); | |
1a4d82fc JJ |
1421 | let cfg = build_configuration(&sess); |
1422 | let mut test_items = cfg.iter().filter(|m| m.name() == "test"); | |
1423 | assert!(test_items.next().is_some()); | |
1424 | assert!(test_items.next().is_none()); | |
1425 | } | |
1426 | ||
1427 | #[test] | |
1428 | fn test_can_print_warnings() { | |
1429 | { | |
1430 | let matches = getopts(&[ | |
1431 | "-Awarnings".to_string() | |
c34b1796 | 1432 | ], &optgroups()).unwrap(); |
1a4d82fc JJ |
1433 | let registry = diagnostics::registry::Registry::new(&[]); |
1434 | let sessopts = build_session_options(&matches); | |
92a42be0 SL |
1435 | let sess = build_session(sessopts, None, registry, |
1436 | Rc::new(DummyCrateStore)); | |
9cc50fc6 | 1437 | assert!(!sess.diagnostic().can_emit_warnings); |
1a4d82fc JJ |
1438 | } |
1439 | ||
1440 | { | |
1441 | let matches = getopts(&[ | |
1442 | "-Awarnings".to_string(), | |
1443 | "-Dwarnings".to_string() | |
c34b1796 | 1444 | ], &optgroups()).unwrap(); |
1a4d82fc JJ |
1445 | let registry = diagnostics::registry::Registry::new(&[]); |
1446 | let sessopts = build_session_options(&matches); | |
92a42be0 SL |
1447 | let sess = build_session(sessopts, None, registry, |
1448 | Rc::new(DummyCrateStore)); | |
9cc50fc6 | 1449 | assert!(sess.diagnostic().can_emit_warnings); |
1a4d82fc JJ |
1450 | } |
1451 | ||
1452 | { | |
1453 | let matches = getopts(&[ | |
1454 | "-Adead_code".to_string() | |
c34b1796 | 1455 | ], &optgroups()).unwrap(); |
1a4d82fc JJ |
1456 | let registry = diagnostics::registry::Registry::new(&[]); |
1457 | let sessopts = build_session_options(&matches); | |
92a42be0 SL |
1458 | let sess = build_session(sessopts, None, registry, |
1459 | Rc::new(DummyCrateStore)); | |
9cc50fc6 | 1460 | assert!(sess.diagnostic().can_emit_warnings); |
1a4d82fc JJ |
1461 | } |
1462 | } | |
1463 | } |