]>
Commit | Line | Data |
---|---|---|
a7813a04 XL |
1 | //! Serialized configuration of a build. |
2 | //! | |
ea8adc8c XL |
3 | //! This module implements parsing `config.toml` configuration files to tweak |
4 | //! how the build runs. | |
a7813a04 | 5 | |
dfeec247 | 6 | use std::cmp; |
2c00a5a8 | 7 | use std::collections::{HashMap, HashSet}; |
7453a54e | 8 | use std::env; |
dfeec247 | 9 | use std::ffi::OsString; |
3dfed10e | 10 | use std::fmt; |
0731742a | 11 | use std::fs; |
2c00a5a8 | 12 | use std::path::{Path, PathBuf}; |
29967ef6 | 13 | use std::str::FromStr; |
7453a54e | 14 | |
dfeec247 | 15 | use crate::cache::{Interned, INTERNER}; |
0731742a | 16 | pub use crate::flags::Subcommand; |
fc512014 | 17 | use crate::flags::{Color, Flags}; |
1b1a35ee | 18 | use crate::util::exe; |
dfeec247 | 19 | use build_helper::t; |
1b1a35ee | 20 | use merge::Merge; |
dfeec247 | 21 | use serde::Deserialize; |
7453a54e | 22 | |
1b1a35ee XL |
23 | macro_rules! check_ci_llvm { |
24 | ($name:expr) => { | |
25 | assert!( | |
26 | $name.is_none(), | |
27 | "setting {} is incompatible with download-ci-llvm.", | |
28 | stringify!($name) | |
29 | ); | |
30 | }; | |
31 | } | |
32 | ||
7453a54e SL |
33 | /// Global configuration for the entire build and/or bootstrap. |
34 | /// | |
35 | /// This structure is derived from a combination of both `config.toml` and | |
36 | /// `config.mk`. As of the time of this writing it's unlikely that `config.toml` | |
37 | /// is used all that much, so this is primarily filled out by `config.mk` which | |
38 | /// is generated from `./configure`. | |
39 | /// | |
40 | /// Note that this structure is not decoded directly into, but rather it is | |
a7813a04 XL |
41 | /// filled out from the decoded forms of the structs below. For documentation |
42 | /// each field, see the corresponding fields in | |
3b2f2976 | 43 | /// `config.toml.example`. |
7453a54e SL |
44 | #[derive(Default)] |
45 | pub struct Config { | |
1b1a35ee | 46 | pub changelog_seen: Option<usize>, |
476ff2be | 47 | pub ccache: Option<String>, |
1b1a35ee XL |
48 | /// Call Build::ninja() instead of this. |
49 | pub ninja_in_file: bool, | |
32a655c1 | 50 | pub verbose: usize, |
7453a54e | 51 | pub submodules: bool, |
0531ce1d | 52 | pub fast_submodules: bool, |
7453a54e | 53 | pub compiler_docs: bool, |
6a06907d | 54 | pub docs_minification: bool, |
7453a54e | 55 | pub docs: bool, |
8bb4bdeb | 56 | pub locked_deps: bool, |
476ff2be | 57 | pub vendor: bool, |
3dfed10e | 58 | pub target_config: HashMap<TargetSelection, Target>, |
32a655c1 SL |
59 | pub full_bootstrap: bool, |
60 | pub extended: bool, | |
2c00a5a8 | 61 | pub tools: Option<HashSet<String>>, |
8bb4bdeb | 62 | pub sanitizers: bool, |
041b39d2 | 63 | pub profiler: bool, |
3b2f2976 | 64 | pub ignore_git: bool, |
2c00a5a8 | 65 | pub exclude: Vec<PathBuf>, |
1b1a35ee | 66 | pub include_default_paths: bool, |
0531ce1d | 67 | pub rustc_error_format: Option<String>, |
ba9703b0 | 68 | pub json_output: bool, |
a1dfa0c6 | 69 | pub test_compare_mode: bool, |
29967ef6 | 70 | pub llvm_libunwind: Option<LlvmLibunwind>, |
fc512014 | 71 | pub color: Color, |
3b2f2976 | 72 | |
3b2f2976 | 73 | pub on_fail: Option<String>, |
1b1a35ee | 74 | pub stage: u32, |
8faf50e0 | 75 | pub keep_stage: Vec<u32>, |
1b1a35ee | 76 | pub keep_stage_std: Vec<u32>, |
3b2f2976 | 77 | pub src: PathBuf, |
1b1a35ee XL |
78 | // defaults to `config.toml` |
79 | pub config: PathBuf, | |
3b2f2976 XL |
80 | pub jobs: Option<u32>, |
81 | pub cmd: Subcommand, | |
82 | pub incremental: bool, | |
83c7162d | 83 | pub dry_run: bool, |
6a06907d | 84 | pub download_rustc: bool, |
83c7162d XL |
85 | |
86 | pub deny_warnings: bool, | |
87 | pub backtrace_on_ice: bool, | |
7453a54e SL |
88 | |
89 | // llvm codegen options | |
dfeec247 | 90 | pub llvm_skip_rebuild: bool, |
7453a54e SL |
91 | pub llvm_assertions: bool, |
92 | pub llvm_optimize: bool, | |
b7449926 | 93 | pub llvm_thin_lto: bool, |
476ff2be | 94 | pub llvm_release_debuginfo: bool, |
7453a54e SL |
95 | pub llvm_version_check: bool, |
96 | pub llvm_static_stdcpp: bool, | |
476ff2be | 97 | pub llvm_link_shared: bool, |
94b46f34 | 98 | pub llvm_clang_cl: Option<String>, |
32a655c1 | 99 | pub llvm_targets: Option<String>, |
416331ca | 100 | pub llvm_experimental_targets: Option<String>, |
8bb4bdeb | 101 | pub llvm_link_jobs: Option<u32>, |
b7449926 | 102 | pub llvm_version_suffix: Option<String>, |
9fa01778 | 103 | pub llvm_use_linker: Option<String>, |
532ac7d7 | 104 | pub llvm_allow_old_toolchain: Option<bool>, |
29967ef6 | 105 | pub llvm_polly: Option<bool>, |
1b1a35ee | 106 | pub llvm_from_ci: bool, |
7453a54e | 107 | |
74b04a01 | 108 | pub use_lld: bool, |
0531ce1d | 109 | pub lld_enabled: bool, |
8faf50e0 | 110 | pub llvm_tools_enabled: bool, |
0531ce1d | 111 | |
9fa01778 XL |
112 | pub llvm_cflags: Option<String>, |
113 | pub llvm_cxxflags: Option<String>, | |
114 | pub llvm_ldflags: Option<String>, | |
0731742a XL |
115 | pub llvm_use_libcxx: bool, |
116 | ||
7453a54e SL |
117 | // rust codegen options |
118 | pub rust_optimize: bool, | |
abe05a73 | 119 | pub rust_codegen_units: Option<u32>, |
a1dfa0c6 | 120 | pub rust_codegen_units_std: Option<u32>, |
7453a54e | 121 | pub rust_debug_assertions: bool, |
f9f354fc | 122 | pub rust_debug_assertions_std: bool, |
1b1a35ee | 123 | pub rust_debug_logging: bool, |
dc9dc135 XL |
124 | pub rust_debuginfo_level_rustc: u32, |
125 | pub rust_debuginfo_level_std: u32, | |
126 | pub rust_debuginfo_level_tools: u32, | |
127 | pub rust_debuginfo_level_tests: u32, | |
fc512014 | 128 | pub rust_run_dsymutil: bool, |
7453a54e | 129 | pub rust_rpath: bool, |
9fa01778 | 130 | pub rustc_parallel: bool, |
7453a54e | 131 | pub rustc_default_linker: Option<String>, |
a7813a04 | 132 | pub rust_optimize_tests: bool, |
8bb4bdeb | 133 | pub rust_dist_src: bool, |
2c00a5a8 | 134 | pub rust_codegen_backends: Vec<Interned<String>>, |
8faf50e0 | 135 | pub rust_verify_llvm_ir: bool, |
dfeec247 | 136 | pub rust_thin_lto_import_instr_limit: Option<u32>, |
b7449926 | 137 | pub rust_remap_debuginfo: bool, |
3dfed10e | 138 | pub rust_new_symbol_mangling: bool, |
fc512014 XL |
139 | pub rust_profile_use: Option<String>, |
140 | pub rust_profile_generate: Option<String>, | |
7453a54e | 141 | |
3dfed10e XL |
142 | pub build: TargetSelection, |
143 | pub hosts: Vec<TargetSelection>, | |
144 | pub targets: Vec<TargetSelection>, | |
3157f602 | 145 | pub local_rebuild: bool, |
a1dfa0c6 | 146 | pub jemalloc: bool, |
74b04a01 | 147 | pub control_flow_guard: bool, |
7453a54e | 148 | |
32a655c1 SL |
149 | // dist misc |
150 | pub dist_sign_folder: Option<PathBuf>, | |
151 | pub dist_upload_addr: Option<String>, | |
152 | pub dist_gpg_password_file: Option<PathBuf>, | |
5869c6ff | 153 | pub dist_compression_formats: Option<Vec<String>>, |
32a655c1 | 154 | |
7453a54e | 155 | // libstd features |
5bcae85e | 156 | pub backtrace: bool, // support for RUST_BACKTRACE |
7453a54e SL |
157 | |
158 | // misc | |
7cac9316 | 159 | pub low_priority: bool, |
7453a54e | 160 | pub channel: String, |
fc512014 | 161 | pub description: Option<String>, |
94b46f34 | 162 | pub verbose_tests: bool, |
ff7c6d11 | 163 | pub save_toolstates: Option<PathBuf>, |
0531ce1d | 164 | pub print_step_timings: bool, |
6a06907d | 165 | pub print_step_rusage: bool, |
0bf4aa26 | 166 | pub missing_tools: bool, |
ff7c6d11 | 167 | |
9e0c209e | 168 | // Fallback musl-root for all targets |
7453a54e | 169 | pub musl_root: Option<PathBuf>, |
32a655c1 | 170 | pub prefix: Option<PathBuf>, |
7cac9316 | 171 | pub sysconfdir: Option<PathBuf>, |
2c00a5a8 | 172 | pub datadir: Option<PathBuf>, |
32a655c1 | 173 | pub docdir: Option<PathBuf>, |
e1599b0c | 174 | pub bindir: PathBuf, |
32a655c1 | 175 | pub libdir: Option<PathBuf>, |
32a655c1 | 176 | pub mandir: Option<PathBuf>, |
9e0c209e SL |
177 | pub codegen_tests: bool, |
178 | pub nodejs: Option<PathBuf>, | |
6a06907d | 179 | pub npm: Option<PathBuf>, |
c30ab7b3 | 180 | pub gdb: Option<PathBuf>, |
476ff2be | 181 | pub python: Option<PathBuf>, |
0bf4aa26 | 182 | pub cargo_native_static: bool, |
ea8adc8c | 183 | pub configure_args: Vec<String>, |
041b39d2 XL |
184 | |
185 | // These are either the stage0 downloaded binaries or the locally installed ones. | |
186 | pub initial_cargo: PathBuf, | |
187 | pub initial_rustc: PathBuf, | |
dfeec247 | 188 | pub initial_rustfmt: Option<PathBuf>, |
83c7162d | 189 | pub out: PathBuf, |
7453a54e SL |
190 | } |
191 | ||
29967ef6 XL |
192 | #[derive(Debug, Clone, Copy, PartialEq)] |
193 | pub enum LlvmLibunwind { | |
194 | No, | |
195 | InTree, | |
196 | System, | |
197 | } | |
198 | ||
199 | impl Default for LlvmLibunwind { | |
200 | fn default() -> Self { | |
201 | Self::No | |
202 | } | |
203 | } | |
204 | ||
205 | impl FromStr for LlvmLibunwind { | |
206 | type Err = String; | |
207 | ||
208 | fn from_str(value: &str) -> Result<Self, Self::Err> { | |
209 | match value { | |
210 | "no" => Ok(Self::No), | |
211 | "in-tree" => Ok(Self::InTree), | |
212 | "system" => Ok(Self::System), | |
213 | invalid => Err(format!("Invalid value '{}' for rust.llvm-libunwind config.", invalid)), | |
214 | } | |
215 | } | |
216 | } | |
217 | ||
3dfed10e XL |
218 | #[derive(Debug, Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] |
219 | pub struct TargetSelection { | |
220 | pub triple: Interned<String>, | |
221 | file: Option<Interned<String>>, | |
222 | } | |
223 | ||
224 | impl TargetSelection { | |
225 | pub fn from_user(selection: &str) -> Self { | |
226 | let path = Path::new(selection); | |
227 | ||
228 | let (triple, file) = if path.exists() { | |
229 | let triple = path | |
230 | .file_stem() | |
231 | .expect("Target specification file has no file stem") | |
232 | .to_str() | |
233 | .expect("Target specification file stem is not UTF-8"); | |
234 | ||
235 | (triple, Some(selection)) | |
236 | } else { | |
237 | (selection, None) | |
238 | }; | |
239 | ||
240 | let triple = INTERNER.intern_str(triple); | |
241 | let file = file.map(|f| INTERNER.intern_str(f)); | |
242 | ||
243 | Self { triple, file } | |
244 | } | |
245 | ||
246 | pub fn rustc_target_arg(&self) -> &str { | |
247 | self.file.as_ref().unwrap_or(&self.triple) | |
248 | } | |
249 | ||
250 | pub fn contains(&self, needle: &str) -> bool { | |
251 | self.triple.contains(needle) | |
252 | } | |
253 | ||
254 | pub fn starts_with(&self, needle: &str) -> bool { | |
255 | self.triple.starts_with(needle) | |
256 | } | |
257 | ||
258 | pub fn ends_with(&self, needle: &str) -> bool { | |
259 | self.triple.ends_with(needle) | |
260 | } | |
261 | } | |
262 | ||
263 | impl fmt::Display for TargetSelection { | |
264 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | |
265 | write!(f, "{}", self.triple)?; | |
266 | if let Some(file) = self.file { | |
267 | write!(f, "({})", file)?; | |
268 | } | |
269 | Ok(()) | |
270 | } | |
271 | } | |
272 | ||
273 | impl PartialEq<&str> for TargetSelection { | |
274 | fn eq(&self, other: &&str) -> bool { | |
275 | self.triple == *other | |
276 | } | |
277 | } | |
278 | ||
7453a54e SL |
279 | /// Per-target configuration stored in the global configuration structure. |
280 | #[derive(Default)] | |
281 | pub struct Target { | |
041b39d2 | 282 | /// Some(path to llvm-config) if using an external LLVM. |
7453a54e | 283 | pub llvm_config: Option<PathBuf>, |
0bf4aa26 XL |
284 | /// Some(path to FileCheck) if one was specified. |
285 | pub llvm_filecheck: Option<PathBuf>, | |
7453a54e SL |
286 | pub cc: Option<PathBuf>, |
287 | pub cxx: Option<PathBuf>, | |
abe05a73 | 288 | pub ar: Option<PathBuf>, |
b7449926 | 289 | pub ranlib: Option<PathBuf>, |
abe05a73 | 290 | pub linker: Option<PathBuf>, |
7453a54e | 291 | pub ndk: Option<PathBuf>, |
fc512014 XL |
292 | pub sanitizers: Option<bool>, |
293 | pub profiler: Option<bool>, | |
3b2f2976 | 294 | pub crt_static: Option<bool>, |
9e0c209e | 295 | pub musl_root: Option<PathBuf>, |
f035d41b | 296 | pub musl_libdir: Option<PathBuf>, |
532ac7d7 | 297 | pub wasi_root: Option<PathBuf>, |
8bb4bdeb | 298 | pub qemu_rootfs: Option<PathBuf>, |
83c7162d | 299 | pub no_std: bool, |
7453a54e SL |
300 | } |
301 | ||
74b04a01 XL |
302 | impl Target { |
303 | pub fn from_triple(triple: &str) -> Self { | |
304 | let mut target: Self = Default::default(); | |
305 | if triple.contains("-none") || triple.contains("nvptx") { | |
306 | target.no_std = true; | |
307 | } | |
308 | target | |
309 | } | |
310 | } | |
7453a54e SL |
311 | /// Structure of the `config.toml` file that configuration is read from. |
312 | /// | |
313 | /// This structure uses `Decodable` to automatically decode a TOML configuration | |
314 | /// file into this format, and then this is traversed and written into the above | |
315 | /// `Config` structure. | |
3b2f2976 XL |
316 | #[derive(Deserialize, Default)] |
317 | #[serde(deny_unknown_fields, rename_all = "kebab-case")] | |
7453a54e | 318 | struct TomlConfig { |
1b1a35ee | 319 | changelog_seen: Option<usize>, |
7453a54e | 320 | build: Option<Build>, |
32a655c1 | 321 | install: Option<Install>, |
7453a54e SL |
322 | llvm: Option<Llvm>, |
323 | rust: Option<Rust>, | |
324 | target: Option<HashMap<String, TomlTarget>>, | |
32a655c1 | 325 | dist: Option<Dist>, |
1b1a35ee XL |
326 | profile: Option<String>, |
327 | } | |
328 | ||
329 | impl Merge for TomlConfig { | |
330 | fn merge( | |
331 | &mut self, | |
332 | TomlConfig { build, install, llvm, rust, dist, target, profile: _, changelog_seen: _ }: Self, | |
333 | ) { | |
334 | fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>) { | |
335 | if let Some(new) = y { | |
336 | if let Some(original) = x { | |
337 | original.merge(new); | |
338 | } else { | |
339 | *x = Some(new); | |
340 | } | |
341 | } | |
5869c6ff | 342 | } |
1b1a35ee XL |
343 | do_merge(&mut self.build, build); |
344 | do_merge(&mut self.install, install); | |
345 | do_merge(&mut self.llvm, llvm); | |
346 | do_merge(&mut self.rust, rust); | |
347 | do_merge(&mut self.dist, dist); | |
348 | assert!(target.is_none(), "merging target-specific config is not currently supported"); | |
349 | } | |
7453a54e SL |
350 | } |
351 | ||
352 | /// TOML representation of various global build decisions. | |
1b1a35ee | 353 | #[derive(Deserialize, Default, Clone, Merge)] |
3b2f2976 | 354 | #[serde(deny_unknown_fields, rename_all = "kebab-case")] |
7453a54e SL |
355 | struct Build { |
356 | build: Option<String>, | |
1b1a35ee XL |
357 | host: Option<Vec<String>>, |
358 | target: Option<Vec<String>>, | |
f9f354fc XL |
359 | // This is ignored, the rust code always gets the build directory from the `BUILD_DIR` env variable |
360 | build_dir: Option<String>, | |
7453a54e SL |
361 | cargo: Option<String>, |
362 | rustc: Option<String>, | |
1b1a35ee | 363 | rustfmt: Option<PathBuf>, |
7453a54e | 364 | docs: Option<bool>, |
e74abb32 | 365 | compiler_docs: Option<bool>, |
6a06907d | 366 | docs_minification: Option<bool>, |
c30ab7b3 | 367 | submodules: Option<bool>, |
0531ce1d | 368 | fast_submodules: Option<bool>, |
c30ab7b3 | 369 | gdb: Option<String>, |
476ff2be | 370 | nodejs: Option<String>, |
6a06907d | 371 | npm: Option<String>, |
476ff2be | 372 | python: Option<String>, |
e74abb32 XL |
373 | locked_deps: Option<bool>, |
374 | vendor: Option<bool>, | |
32a655c1 SL |
375 | full_bootstrap: Option<bool>, |
376 | extended: Option<bool>, | |
2c00a5a8 | 377 | tools: Option<HashSet<String>>, |
8bb4bdeb XL |
378 | verbose: Option<usize>, |
379 | sanitizers: Option<bool>, | |
041b39d2 | 380 | profiler: Option<bool>, |
0bf4aa26 | 381 | cargo_native_static: Option<bool>, |
e74abb32 | 382 | low_priority: Option<bool>, |
ea8adc8c XL |
383 | configure_args: Option<Vec<String>>, |
384 | local_rebuild: Option<bool>, | |
0531ce1d | 385 | print_step_timings: Option<bool>, |
6a06907d | 386 | print_step_rusage: Option<bool>, |
5869c6ff | 387 | check_stage: Option<u32>, |
1b1a35ee XL |
388 | doc_stage: Option<u32>, |
389 | build_stage: Option<u32>, | |
390 | test_stage: Option<u32>, | |
391 | install_stage: Option<u32>, | |
392 | dist_stage: Option<u32>, | |
393 | bench_stage: Option<u32>, | |
32a655c1 SL |
394 | } |
395 | ||
396 | /// TOML representation of various global install decisions. | |
1b1a35ee | 397 | #[derive(Deserialize, Default, Clone, Merge)] |
3b2f2976 | 398 | #[serde(deny_unknown_fields, rename_all = "kebab-case")] |
32a655c1 SL |
399 | struct Install { |
400 | prefix: Option<String>, | |
7cac9316 | 401 | sysconfdir: Option<String>, |
32a655c1 | 402 | docdir: Option<String>, |
7cac9316 | 403 | bindir: Option<String>, |
32a655c1 | 404 | libdir: Option<String>, |
7cac9316 | 405 | mandir: Option<String>, |
e74abb32 | 406 | datadir: Option<String>, |
abe05a73 XL |
407 | |
408 | // standard paths, currently unused | |
abe05a73 XL |
409 | infodir: Option<String>, |
410 | localstatedir: Option<String>, | |
7453a54e SL |
411 | } |
412 | ||
413 | /// TOML representation of how the LLVM build is configured. | |
1b1a35ee | 414 | #[derive(Deserialize, Default, Merge)] |
3b2f2976 | 415 | #[serde(deny_unknown_fields, rename_all = "kebab-case")] |
7453a54e | 416 | struct Llvm { |
dfeec247 | 417 | skip_rebuild: Option<bool>, |
7453a54e | 418 | optimize: Option<bool>, |
b7449926 | 419 | thin_lto: Option<bool>, |
476ff2be | 420 | release_debuginfo: Option<bool>, |
e74abb32 XL |
421 | assertions: Option<bool>, |
422 | ccache: Option<StringOrBool>, | |
7453a54e SL |
423 | version_check: Option<bool>, |
424 | static_libstdcpp: Option<bool>, | |
e74abb32 | 425 | ninja: Option<bool>, |
32a655c1 | 426 | targets: Option<String>, |
041b39d2 | 427 | experimental_targets: Option<String>, |
8bb4bdeb | 428 | link_jobs: Option<u32>, |
ea8adc8c | 429 | link_shared: Option<bool>, |
b7449926 | 430 | version_suffix: Option<String>, |
a1dfa0c6 | 431 | clang_cl: Option<String>, |
9fa01778 XL |
432 | cflags: Option<String>, |
433 | cxxflags: Option<String>, | |
434 | ldflags: Option<String>, | |
0731742a | 435 | use_libcxx: Option<bool>, |
9fa01778 | 436 | use_linker: Option<String>, |
532ac7d7 | 437 | allow_old_toolchain: Option<bool>, |
29967ef6 XL |
438 | polly: Option<bool>, |
439 | download_ci_llvm: Option<StringOrBool>, | |
32a655c1 SL |
440 | } |
441 | ||
1b1a35ee | 442 | #[derive(Deserialize, Default, Clone, Merge)] |
3b2f2976 | 443 | #[serde(deny_unknown_fields, rename_all = "kebab-case")] |
32a655c1 SL |
444 | struct Dist { |
445 | sign_folder: Option<String>, | |
446 | gpg_password_file: Option<String>, | |
447 | upload_addr: Option<String>, | |
8bb4bdeb | 448 | src_tarball: Option<bool>, |
0bf4aa26 | 449 | missing_tools: Option<bool>, |
5869c6ff | 450 | compression_formats: Option<Vec<String>>, |
7453a54e SL |
451 | } |
452 | ||
3b2f2976 XL |
453 | #[derive(Deserialize)] |
454 | #[serde(untagged)] | |
476ff2be SL |
455 | enum StringOrBool { |
456 | String(String), | |
457 | Bool(bool), | |
458 | } | |
459 | ||
460 | impl Default for StringOrBool { | |
461 | fn default() -> StringOrBool { | |
462 | StringOrBool::Bool(false) | |
463 | } | |
464 | } | |
465 | ||
7453a54e | 466 | /// TOML representation of how the Rust build is configured. |
1b1a35ee | 467 | #[derive(Deserialize, Default, Merge)] |
3b2f2976 | 468 | #[serde(deny_unknown_fields, rename_all = "kebab-case")] |
7453a54e SL |
469 | struct Rust { |
470 | optimize: Option<bool>, | |
e74abb32 | 471 | debug: Option<bool>, |
7453a54e | 472 | codegen_units: Option<u32>, |
a1dfa0c6 | 473 | codegen_units_std: Option<u32>, |
7453a54e | 474 | debug_assertions: Option<bool>, |
f9f354fc | 475 | debug_assertions_std: Option<bool>, |
1b1a35ee | 476 | debug_logging: Option<bool>, |
dc9dc135 XL |
477 | debuginfo_level: Option<u32>, |
478 | debuginfo_level_rustc: Option<u32>, | |
479 | debuginfo_level_std: Option<u32>, | |
480 | debuginfo_level_tools: Option<u32>, | |
481 | debuginfo_level_tests: Option<u32>, | |
fc512014 | 482 | run_dsymutil: Option<bool>, |
5bcae85e | 483 | backtrace: Option<bool>, |
e74abb32 XL |
484 | incremental: Option<bool>, |
485 | parallel_compiler: Option<bool>, | |
7453a54e | 486 | default_linker: Option<String>, |
7453a54e | 487 | channel: Option<String>, |
fc512014 | 488 | description: Option<String>, |
7453a54e SL |
489 | musl_root: Option<String>, |
490 | rpath: Option<bool>, | |
e74abb32 | 491 | verbose_tests: Option<bool>, |
a7813a04 | 492 | optimize_tests: Option<bool>, |
9e0c209e | 493 | codegen_tests: Option<bool>, |
3b2f2976 | 494 | ignore_git: Option<bool>, |
ea8adc8c | 495 | dist_src: Option<bool>, |
ff7c6d11 | 496 | save_toolstates: Option<String>, |
2c00a5a8 | 497 | codegen_backends: Option<Vec<String>>, |
0531ce1d | 498 | lld: Option<bool>, |
74b04a01 | 499 | use_lld: Option<bool>, |
8faf50e0 | 500 | llvm_tools: Option<bool>, |
83c7162d XL |
501 | deny_warnings: Option<bool>, |
502 | backtrace_on_ice: Option<bool>, | |
8faf50e0 | 503 | verify_llvm_ir: Option<bool>, |
dfeec247 | 504 | thin_lto_import_instr_limit: Option<u32>, |
b7449926 | 505 | remap_debuginfo: Option<bool>, |
a1dfa0c6 XL |
506 | jemalloc: Option<bool>, |
507 | test_compare_mode: Option<bool>, | |
29967ef6 | 508 | llvm_libunwind: Option<String>, |
74b04a01 | 509 | control_flow_guard: Option<bool>, |
3dfed10e | 510 | new_symbol_mangling: Option<bool>, |
fc512014 XL |
511 | profile_generate: Option<String>, |
512 | profile_use: Option<String>, | |
6a06907d | 513 | download_rustc: Option<bool>, |
7453a54e SL |
514 | } |
515 | ||
516 | /// TOML representation of how each build target is configured. | |
1b1a35ee | 517 | #[derive(Deserialize, Default, Merge)] |
3b2f2976 | 518 | #[serde(deny_unknown_fields, rename_all = "kebab-case")] |
7453a54e | 519 | struct TomlTarget { |
7453a54e SL |
520 | cc: Option<String>, |
521 | cxx: Option<String>, | |
abe05a73 | 522 | ar: Option<String>, |
b7449926 | 523 | ranlib: Option<String>, |
abe05a73 | 524 | linker: Option<String>, |
e74abb32 XL |
525 | llvm_config: Option<String>, |
526 | llvm_filecheck: Option<String>, | |
7453a54e | 527 | android_ndk: Option<String>, |
29967ef6 XL |
528 | sanitizers: Option<bool>, |
529 | profiler: Option<bool>, | |
3b2f2976 | 530 | crt_static: Option<bool>, |
c30ab7b3 | 531 | musl_root: Option<String>, |
f035d41b | 532 | musl_libdir: Option<String>, |
532ac7d7 | 533 | wasi_root: Option<String>, |
8bb4bdeb | 534 | qemu_rootfs: Option<String>, |
74b04a01 | 535 | no_std: Option<bool>, |
7453a54e SL |
536 | } |
537 | ||
538 | impl Config { | |
83c7162d XL |
539 | fn path_from_python(var_key: &str) -> PathBuf { |
540 | match env::var_os(var_key) { | |
dfeec247 | 541 | Some(var_val) => Self::normalize_python_path(var_val), |
83c7162d XL |
542 | _ => panic!("expected '{}' to be set", var_key), |
543 | } | |
544 | } | |
545 | ||
dfeec247 XL |
546 | /// Normalizes paths from Python slightly. We don't trust paths from Python (#49785). |
547 | fn normalize_python_path(path: OsString) -> PathBuf { | |
548 | Path::new(&path).components().collect() | |
549 | } | |
550 | ||
83c7162d | 551 | pub fn default_opts() -> Config { |
7453a54e SL |
552 | let mut config = Config::default(); |
553 | config.llvm_optimize = true; | |
1b1a35ee | 554 | config.ninja_in_file = true; |
abe05a73 | 555 | config.llvm_version_check = true; |
5bcae85e | 556 | config.backtrace = true; |
7453a54e | 557 | config.rust_optimize = true; |
a7813a04 | 558 | config.rust_optimize_tests = true; |
7453a54e | 559 | config.submodules = true; |
0531ce1d | 560 | config.fast_submodules = true; |
7453a54e | 561 | config.docs = true; |
6a06907d | 562 | config.docs_minification = true; |
7453a54e | 563 | config.rust_rpath = true; |
7453a54e | 564 | config.channel = "dev".to_string(); |
9e0c209e | 565 | config.codegen_tests = true; |
3b2f2976 | 566 | config.ignore_git = false; |
8bb4bdeb | 567 | config.rust_dist_src = true; |
2c00a5a8 | 568 | config.rust_codegen_backends = vec![INTERNER.intern_str("llvm")]; |
83c7162d | 569 | config.deny_warnings = true; |
0bf4aa26 | 570 | config.missing_tools = false; |
83c7162d | 571 | |
fc512014 | 572 | // set by build.rs |
1b1a35ee XL |
573 | config.build = TargetSelection::from_user(&env!("BUILD_TRIPLE")); |
574 | let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); | |
575 | // Undo `src/bootstrap` | |
576 | config.src = manifest_dir.parent().unwrap().parent().unwrap().to_owned(); | |
83c7162d XL |
577 | config.out = Config::path_from_python("BUILD_DIR"); |
578 | ||
1b1a35ee XL |
579 | config.initial_cargo = PathBuf::from(env!("CARGO")); |
580 | config.initial_rustc = PathBuf::from(env!("RUSTC")); | |
7453a54e | 581 | |
83c7162d XL |
582 | config |
583 | } | |
584 | ||
585 | pub fn parse(args: &[String]) -> Config { | |
586 | let flags = Flags::parse(&args); | |
1b1a35ee | 587 | |
83c7162d XL |
588 | let mut config = Config::default_opts(); |
589 | config.exclude = flags.exclude; | |
1b1a35ee | 590 | config.include_default_paths = flags.include_default_paths; |
0531ce1d | 591 | config.rustc_error_format = flags.rustc_error_format; |
ba9703b0 | 592 | config.json_output = flags.json_output; |
3b2f2976 | 593 | config.on_fail = flags.on_fail; |
dc9dc135 | 594 | config.jobs = flags.jobs.map(threads_from_config); |
3b2f2976 XL |
595 | config.cmd = flags.cmd; |
596 | config.incremental = flags.incremental; | |
83c7162d | 597 | config.dry_run = flags.dry_run; |
3b2f2976 | 598 | config.keep_stage = flags.keep_stage; |
1b1a35ee | 599 | config.keep_stage_std = flags.keep_stage_std; |
e1599b0c | 600 | config.bindir = "bin".into(); // default |
fc512014 | 601 | config.color = flags.color; |
416331ca | 602 | if let Some(value) = flags.deny_warnings { |
83c7162d XL |
603 | config.deny_warnings = value; |
604 | } | |
605 | ||
606 | if config.dry_run { | |
607 | let dir = config.out.join("tmp-dry-run"); | |
608 | t!(fs::create_dir_all(&dir)); | |
609 | config.out = dir; | |
610 | } | |
3b2f2976 | 611 | |
1b1a35ee XL |
612 | #[cfg(test)] |
613 | let get_toml = |_| TomlConfig::default(); | |
614 | #[cfg(not(test))] | |
615 | let get_toml = |file: &Path| { | |
616 | use std::process; | |
617 | ||
618 | let contents = t!(fs::read_to_string(file), "`include` config not found"); | |
619 | match toml::from_str(&contents) { | |
620 | Ok(table) => table, | |
621 | Err(err) => { | |
622 | println!("failed to parse TOML configuration '{}': {}", file.display(), err); | |
623 | process::exit(2); | |
7453a54e | 624 | } |
7453a54e | 625 | } |
1b1a35ee XL |
626 | }; |
627 | ||
628 | let mut toml = flags.config.as_deref().map(get_toml).unwrap_or_else(TomlConfig::default); | |
629 | if let Some(include) = &toml.profile { | |
630 | let mut include_path = config.src.clone(); | |
631 | include_path.push("src"); | |
632 | include_path.push("bootstrap"); | |
633 | include_path.push("defaults"); | |
29967ef6 | 634 | include_path.push(format!("config.{}.toml", include)); |
1b1a35ee XL |
635 | let included_toml = get_toml(&include_path); |
636 | toml.merge(included_toml); | |
7453a54e | 637 | } |
1b1a35ee XL |
638 | |
639 | config.changelog_seen = toml.changelog_seen; | |
640 | if let Some(cfg) = flags.config { | |
641 | config.config = cfg; | |
7453a54e | 642 | } |
1b1a35ee XL |
643 | |
644 | let build = toml.build.unwrap_or_default(); | |
645 | ||
646 | config.hosts = if let Some(arg_host) = flags.host { | |
647 | arg_host | |
648 | } else if let Some(file_host) = build.host { | |
649 | file_host.iter().map(|h| TargetSelection::from_user(h)).collect() | |
650 | } else { | |
651 | vec![config.build] | |
652 | }; | |
653 | config.targets = if let Some(arg_target) = flags.target { | |
654 | arg_target | |
655 | } else if let Some(file_target) = build.target { | |
656 | file_target.iter().map(|h| TargetSelection::from_user(h)).collect() | |
657 | } else { | |
658 | // If target is *not* configured, then default to the host | |
659 | // toolchains. | |
660 | config.hosts.clone() | |
661 | }; | |
3b2f2976 | 662 | |
476ff2be | 663 | config.nodejs = build.nodejs.map(PathBuf::from); |
6a06907d | 664 | config.npm = build.npm.map(PathBuf::from); |
c30ab7b3 | 665 | config.gdb = build.gdb.map(PathBuf::from); |
476ff2be | 666 | config.python = build.python.map(PathBuf::from); |
7cac9316 | 667 | set(&mut config.low_priority, build.low_priority); |
7453a54e | 668 | set(&mut config.compiler_docs, build.compiler_docs); |
6a06907d | 669 | set(&mut config.docs_minification, build.docs_minification); |
7453a54e | 670 | set(&mut config.docs, build.docs); |
c30ab7b3 | 671 | set(&mut config.submodules, build.submodules); |
0531ce1d | 672 | set(&mut config.fast_submodules, build.fast_submodules); |
8bb4bdeb | 673 | set(&mut config.locked_deps, build.locked_deps); |
476ff2be | 674 | set(&mut config.vendor, build.vendor); |
32a655c1 SL |
675 | set(&mut config.full_bootstrap, build.full_bootstrap); |
676 | set(&mut config.extended, build.extended); | |
2c00a5a8 | 677 | config.tools = build.tools; |
1b1a35ee XL |
678 | if build.rustfmt.is_some() { |
679 | config.initial_rustfmt = build.rustfmt; | |
680 | } | |
8bb4bdeb XL |
681 | set(&mut config.verbose, build.verbose); |
682 | set(&mut config.sanitizers, build.sanitizers); | |
041b39d2 | 683 | set(&mut config.profiler, build.profiler); |
0bf4aa26 | 684 | set(&mut config.cargo_native_static, build.cargo_native_static); |
ea8adc8c XL |
685 | set(&mut config.configure_args, build.configure_args); |
686 | set(&mut config.local_rebuild, build.local_rebuild); | |
0531ce1d | 687 | set(&mut config.print_step_timings, build.print_step_timings); |
6a06907d | 688 | set(&mut config.print_step_rusage, build.print_step_rusage); |
1b1a35ee XL |
689 | |
690 | // See https://github.com/rust-lang/compiler-team/issues/326 | |
691 | config.stage = match config.cmd { | |
5869c6ff | 692 | Subcommand::Check { .. } => flags.stage.or(build.check_stage).unwrap_or(0), |
1b1a35ee XL |
693 | Subcommand::Doc { .. } => flags.stage.or(build.doc_stage).unwrap_or(0), |
694 | Subcommand::Build { .. } => flags.stage.or(build.build_stage).unwrap_or(1), | |
695 | Subcommand::Test { .. } => flags.stage.or(build.test_stage).unwrap_or(1), | |
696 | Subcommand::Bench { .. } => flags.stage.or(build.bench_stage).unwrap_or(2), | |
697 | Subcommand::Dist { .. } => flags.stage.or(build.dist_stage).unwrap_or(2), | |
698 | Subcommand::Install { .. } => flags.stage.or(build.install_stage).unwrap_or(2), | |
699 | // These are all bootstrap tools, which don't depend on the compiler. | |
700 | // The stage we pass shouldn't matter, but use 0 just in case. | |
701 | Subcommand::Clean { .. } | |
1b1a35ee XL |
702 | | Subcommand::Clippy { .. } |
703 | | Subcommand::Fix { .. } | |
704 | | Subcommand::Run { .. } | |
705 | | Subcommand::Setup { .. } | |
706 | | Subcommand::Format { .. } => flags.stage.unwrap_or(0), | |
707 | }; | |
708 | ||
709 | // CI should always run stage 2 builds, unless it specifically states otherwise | |
710 | #[cfg(not(test))] | |
711 | if flags.stage.is_none() && crate::CiEnv::current() != crate::CiEnv::None { | |
712 | match config.cmd { | |
713 | Subcommand::Test { .. } | |
714 | | Subcommand::Doc { .. } | |
715 | | Subcommand::Build { .. } | |
716 | | Subcommand::Bench { .. } | |
717 | | Subcommand::Dist { .. } | |
718 | | Subcommand::Install { .. } => { | |
719 | assert_eq!( | |
720 | config.stage, 2, | |
721 | "x.py should be run with `--stage 2` on CI, but was run with `--stage {}`", | |
722 | config.stage, | |
723 | ); | |
724 | } | |
725 | Subcommand::Clean { .. } | |
726 | | Subcommand::Check { .. } | |
727 | | Subcommand::Clippy { .. } | |
728 | | Subcommand::Fix { .. } | |
729 | | Subcommand::Run { .. } | |
730 | | Subcommand::Setup { .. } | |
731 | | Subcommand::Format { .. } => {} | |
732 | } | |
733 | } | |
734 | ||
3b2f2976 | 735 | config.verbose = cmp::max(config.verbose, flags.verbose); |
32a655c1 | 736 | |
1b1a35ee XL |
737 | if let Some(install) = toml.install { |
738 | config.prefix = install.prefix.map(PathBuf::from); | |
739 | config.sysconfdir = install.sysconfdir.map(PathBuf::from); | |
740 | config.datadir = install.datadir.map(PathBuf::from); | |
741 | config.docdir = install.docdir.map(PathBuf::from); | |
742 | set(&mut config.bindir, install.bindir.map(PathBuf::from)); | |
743 | config.libdir = install.libdir.map(PathBuf::from); | |
744 | config.mandir = install.mandir.map(PathBuf::from); | |
32a655c1 | 745 | } |
7453a54e | 746 | |
dfeec247 XL |
747 | // We want the llvm-skip-rebuild flag to take precedence over the |
748 | // skip-rebuild config.toml option so we store it separately | |
749 | // so that we can infer the right value | |
750 | let mut llvm_skip_rebuild = flags.llvm_skip_rebuild; | |
751 | ||
ea8adc8c XL |
752 | // Store off these values as options because if they're not provided |
753 | // we'll infer default values for them later | |
754 | let mut llvm_assertions = None; | |
ea8adc8c | 755 | let mut debug = None; |
ea8adc8c | 756 | let mut debug_assertions = None; |
f9f354fc | 757 | let mut debug_assertions_std = None; |
1b1a35ee | 758 | let mut debug_logging = None; |
dc9dc135 XL |
759 | let mut debuginfo_level = None; |
760 | let mut debuginfo_level_rustc = None; | |
761 | let mut debuginfo_level_std = None; | |
762 | let mut debuginfo_level_tools = None; | |
763 | let mut debuginfo_level_tests = None; | |
ea8adc8c XL |
764 | let mut optimize = None; |
765 | let mut ignore_git = None; | |
766 | ||
1b1a35ee | 767 | if let Some(llvm) = toml.llvm { |
476ff2be | 768 | match llvm.ccache { |
dfeec247 | 769 | Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()), |
476ff2be SL |
770 | Some(StringOrBool::Bool(true)) => { |
771 | config.ccache = Some("ccache".to_string()); | |
772 | } | |
773 | Some(StringOrBool::Bool(false)) | None => {} | |
774 | } | |
1b1a35ee | 775 | set(&mut config.ninja_in_file, llvm.ninja); |
ea8adc8c | 776 | llvm_assertions = llvm.assertions; |
dfeec247 | 777 | llvm_skip_rebuild = llvm_skip_rebuild.or(llvm.skip_rebuild); |
7453a54e | 778 | set(&mut config.llvm_optimize, llvm.optimize); |
b7449926 | 779 | set(&mut config.llvm_thin_lto, llvm.thin_lto); |
476ff2be | 780 | set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo); |
7453a54e SL |
781 | set(&mut config.llvm_version_check, llvm.version_check); |
782 | set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp); | |
ea8adc8c | 783 | set(&mut config.llvm_link_shared, llvm.link_shared); |
32a655c1 | 784 | config.llvm_targets = llvm.targets.clone(); |
416331ca | 785 | config.llvm_experimental_targets = llvm.experimental_targets.clone(); |
8bb4bdeb | 786 | config.llvm_link_jobs = llvm.link_jobs; |
b7449926 | 787 | config.llvm_version_suffix = llvm.version_suffix.clone(); |
94b46f34 | 788 | config.llvm_clang_cl = llvm.clang_cl.clone(); |
9fa01778 XL |
789 | |
790 | config.llvm_cflags = llvm.cflags.clone(); | |
791 | config.llvm_cxxflags = llvm.cxxflags.clone(); | |
792 | config.llvm_ldflags = llvm.ldflags.clone(); | |
0731742a | 793 | set(&mut config.llvm_use_libcxx, llvm.use_libcxx); |
9fa01778 | 794 | config.llvm_use_linker = llvm.use_linker.clone(); |
74b04a01 | 795 | config.llvm_allow_old_toolchain = llvm.allow_old_toolchain; |
29967ef6 XL |
796 | config.llvm_polly = llvm.polly; |
797 | config.llvm_from_ci = match llvm.download_ci_llvm { | |
798 | Some(StringOrBool::String(s)) => { | |
799 | assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s); | |
800 | config.build.triple == "x86_64-unknown-linux-gnu" | |
801 | } | |
802 | Some(StringOrBool::Bool(b)) => b, | |
803 | None => false, | |
804 | }; | |
1b1a35ee XL |
805 | |
806 | if config.llvm_from_ci { | |
807 | // None of the LLVM options, except assertions, are supported | |
808 | // when using downloaded LLVM. We could just ignore these but | |
809 | // that's potentially confusing, so force them to not be | |
810 | // explicitly set. The defaults and CI defaults don't | |
811 | // necessarily match but forcing people to match (somewhat | |
812 | // arbitrary) CI configuration locally seems bad/hard. | |
813 | check_ci_llvm!(llvm.optimize); | |
814 | check_ci_llvm!(llvm.thin_lto); | |
815 | check_ci_llvm!(llvm.release_debuginfo); | |
816 | check_ci_llvm!(llvm.link_shared); | |
817 | check_ci_llvm!(llvm.static_libstdcpp); | |
818 | check_ci_llvm!(llvm.targets); | |
819 | check_ci_llvm!(llvm.experimental_targets); | |
820 | check_ci_llvm!(llvm.link_jobs); | |
821 | check_ci_llvm!(llvm.link_shared); | |
822 | check_ci_llvm!(llvm.clang_cl); | |
823 | check_ci_llvm!(llvm.version_suffix); | |
824 | check_ci_llvm!(llvm.cflags); | |
825 | check_ci_llvm!(llvm.cxxflags); | |
826 | check_ci_llvm!(llvm.ldflags); | |
827 | check_ci_llvm!(llvm.use_libcxx); | |
828 | check_ci_llvm!(llvm.use_linker); | |
829 | check_ci_llvm!(llvm.allow_old_toolchain); | |
29967ef6 | 830 | check_ci_llvm!(llvm.polly); |
1b1a35ee | 831 | |
5869c6ff XL |
832 | // CI-built LLVM can be either dynamic or static. |
833 | let ci_llvm = config.out.join(&*config.build.triple).join("ci-llvm"); | |
834 | let link_type = t!(std::fs::read_to_string(ci_llvm.join("link-type.txt"))); | |
835 | config.llvm_link_shared = link_type == "dynamic"; | |
1b1a35ee XL |
836 | } |
837 | ||
838 | if config.llvm_thin_lto { | |
839 | // If we're building with ThinLTO on, we want to link to LLVM | |
840 | // shared, to avoid re-doing ThinLTO (which happens in the link | |
841 | // step) with each stage. | |
842 | config.llvm_link_shared = true; | |
843 | } | |
7453a54e | 844 | } |
32a655c1 | 845 | |
1b1a35ee | 846 | if let Some(rust) = toml.rust { |
ea8adc8c XL |
847 | debug = rust.debug; |
848 | debug_assertions = rust.debug_assertions; | |
f9f354fc | 849 | debug_assertions_std = rust.debug_assertions_std; |
1b1a35ee | 850 | debug_logging = rust.debug_logging; |
dc9dc135 XL |
851 | debuginfo_level = rust.debuginfo_level; |
852 | debuginfo_level_rustc = rust.debuginfo_level_rustc; | |
853 | debuginfo_level_std = rust.debuginfo_level_std; | |
854 | debuginfo_level_tools = rust.debuginfo_level_tools; | |
855 | debuginfo_level_tests = rust.debuginfo_level_tests; | |
fc512014 | 856 | config.rust_run_dsymutil = rust.run_dsymutil.unwrap_or(false); |
ea8adc8c XL |
857 | optimize = rust.optimize; |
858 | ignore_git = rust.ignore_git; | |
3dfed10e | 859 | set(&mut config.rust_new_symbol_mangling, rust.new_symbol_mangling); |
a7813a04 | 860 | set(&mut config.rust_optimize_tests, rust.optimize_tests); |
9e0c209e | 861 | set(&mut config.codegen_tests, rust.codegen_tests); |
7453a54e | 862 | set(&mut config.rust_rpath, rust.rpath); |
a1dfa0c6 XL |
863 | set(&mut config.jemalloc, rust.jemalloc); |
864 | set(&mut config.test_compare_mode, rust.test_compare_mode); | |
29967ef6 XL |
865 | config.llvm_libunwind = rust |
866 | .llvm_libunwind | |
867 | .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind")); | |
5bcae85e | 868 | set(&mut config.backtrace, rust.backtrace); |
1b1a35ee | 869 | set(&mut config.channel, rust.channel); |
fc512014 | 870 | config.description = rust.description; |
ea8adc8c | 871 | set(&mut config.rust_dist_src, rust.dist_src); |
94b46f34 | 872 | set(&mut config.verbose_tests, rust.verbose_tests); |
94b46f34 XL |
873 | // in the case "false" is set explicitly, do not overwrite the command line args |
874 | if let Some(true) = rust.incremental { | |
875 | config.incremental = true; | |
876 | } | |
74b04a01 | 877 | set(&mut config.use_lld, rust.use_lld); |
0531ce1d | 878 | set(&mut config.lld_enabled, rust.lld); |
8faf50e0 | 879 | set(&mut config.llvm_tools_enabled, rust.llvm_tools); |
9fa01778 | 880 | config.rustc_parallel = rust.parallel_compiler.unwrap_or(false); |
1b1a35ee XL |
881 | config.rustc_default_linker = rust.default_linker; |
882 | config.musl_root = rust.musl_root.map(PathBuf::from); | |
883 | config.save_toolstates = rust.save_toolstates.map(PathBuf::from); | |
416331ca | 884 | set(&mut config.deny_warnings, flags.deny_warnings.or(rust.deny_warnings)); |
83c7162d | 885 | set(&mut config.backtrace_on_ice, rust.backtrace_on_ice); |
8faf50e0 | 886 | set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir); |
dfeec247 | 887 | config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit; |
b7449926 | 888 | set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo); |
74b04a01 | 889 | set(&mut config.control_flow_guard, rust.control_flow_guard); |
7453a54e | 890 | |
2c00a5a8 | 891 | if let Some(ref backends) = rust.codegen_backends { |
dfeec247 XL |
892 | config.rust_codegen_backends = |
893 | backends.iter().map(|s| INTERNER.intern_str(s)).collect(); | |
2c00a5a8 XL |
894 | } |
895 | ||
dc9dc135 XL |
896 | config.rust_codegen_units = rust.codegen_units.map(threads_from_config); |
897 | config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config); | |
fc512014 XL |
898 | config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use); |
899 | config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate); | |
6a06907d | 900 | config.download_rustc = rust.download_rustc.unwrap_or(false); |
fc512014 XL |
901 | } else { |
902 | config.rust_profile_use = flags.rust_profile_use; | |
903 | config.rust_profile_generate = flags.rust_profile_generate; | |
7453a54e SL |
904 | } |
905 | ||
1b1a35ee | 906 | if let Some(t) = toml.target { |
7453a54e | 907 | for (triple, cfg) in t { |
1b1a35ee | 908 | let mut target = Target::from_triple(&triple); |
7453a54e SL |
909 | |
910 | if let Some(ref s) = cfg.llvm_config { | |
83c7162d | 911 | target.llvm_config = Some(config.src.join(s)); |
7453a54e | 912 | } |
0bf4aa26 XL |
913 | if let Some(ref s) = cfg.llvm_filecheck { |
914 | target.llvm_filecheck = Some(config.src.join(s)); | |
915 | } | |
7453a54e | 916 | if let Some(ref s) = cfg.android_ndk { |
83c7162d | 917 | target.ndk = Some(config.src.join(s)); |
7453a54e | 918 | } |
74b04a01 XL |
919 | if let Some(s) = cfg.no_std { |
920 | target.no_std = s; | |
921 | } | |
1b1a35ee XL |
922 | target.cc = cfg.cc.map(PathBuf::from); |
923 | target.cxx = cfg.cxx.map(PathBuf::from); | |
924 | target.ar = cfg.ar.map(PathBuf::from); | |
925 | target.ranlib = cfg.ranlib.map(PathBuf::from); | |
926 | target.linker = cfg.linker.map(PathBuf::from); | |
74b04a01 | 927 | target.crt_static = cfg.crt_static; |
1b1a35ee XL |
928 | target.musl_root = cfg.musl_root.map(PathBuf::from); |
929 | target.musl_libdir = cfg.musl_libdir.map(PathBuf::from); | |
930 | target.wasi_root = cfg.wasi_root.map(PathBuf::from); | |
931 | target.qemu_rootfs = cfg.qemu_rootfs.map(PathBuf::from); | |
fc512014 XL |
932 | target.sanitizers = cfg.sanitizers; |
933 | target.profiler = cfg.profiler; | |
7453a54e | 934 | |
1b1a35ee | 935 | config.target_config.insert(TargetSelection::from_user(&triple), target); |
7453a54e SL |
936 | } |
937 | } | |
938 | ||
1b1a35ee XL |
939 | if config.llvm_from_ci { |
940 | let triple = &config.build.triple; | |
941 | let mut build_target = config | |
942 | .target_config | |
943 | .entry(config.build) | |
944 | .or_insert_with(|| Target::from_triple(&triple)); | |
945 | ||
946 | check_ci_llvm!(build_target.llvm_config); | |
947 | check_ci_llvm!(build_target.llvm_filecheck); | |
948 | let ci_llvm_bin = config.out.join(&*config.build.triple).join("ci-llvm/bin"); | |
949 | build_target.llvm_config = Some(ci_llvm_bin.join(exe("llvm-config", config.build))); | |
950 | build_target.llvm_filecheck = Some(ci_llvm_bin.join(exe("FileCheck", config.build))); | |
951 | } | |
952 | ||
953 | if let Some(t) = toml.dist { | |
954 | config.dist_sign_folder = t.sign_folder.map(PathBuf::from); | |
955 | config.dist_gpg_password_file = t.gpg_password_file.map(PathBuf::from); | |
956 | config.dist_upload_addr = t.upload_addr; | |
5869c6ff | 957 | config.dist_compression_formats = t.compression_formats; |
8bb4bdeb | 958 | set(&mut config.rust_dist_src, t.src_tarball); |
0bf4aa26 | 959 | set(&mut config.missing_tools, t.missing_tools); |
32a655c1 SL |
960 | } |
961 | ||
29967ef6 XL |
962 | config.initial_rustfmt = config.initial_rustfmt.or_else({ |
963 | let build = config.build; | |
964 | let initial_rustc = &config.initial_rustc; | |
965 | ||
966 | move || { | |
967 | // Cargo does not provide a RUSTFMT environment variable, so we | |
968 | // synthesize it manually. | |
969 | let rustfmt = initial_rustc.with_file_name(exe("rustfmt", build)); | |
970 | ||
971 | if rustfmt.exists() { Some(rustfmt) } else { None } | |
972 | } | |
973 | }); | |
1b1a35ee | 974 | |
ea8adc8c XL |
975 | // Now that we've reached the end of our configuration, infer the |
976 | // default values for all options that we haven't otherwise stored yet. | |
7cac9316 | 977 | |
dfeec247 XL |
978 | config.llvm_skip_rebuild = llvm_skip_rebuild.unwrap_or(false); |
979 | ||
abe05a73 | 980 | let default = false; |
ea8adc8c | 981 | config.llvm_assertions = llvm_assertions.unwrap_or(default); |
7453a54e | 982 | |
0bf4aa26 XL |
983 | let default = true; |
984 | config.rust_optimize = optimize.unwrap_or(default); | |
985 | ||
ea8adc8c | 986 | let default = debug == Some(true); |
ea8adc8c | 987 | config.rust_debug_assertions = debug_assertions.unwrap_or(default); |
f9f354fc XL |
988 | config.rust_debug_assertions_std = |
989 | debug_assertions_std.unwrap_or(config.rust_debug_assertions); | |
7453a54e | 990 | |
1b1a35ee XL |
991 | config.rust_debug_logging = debug_logging.unwrap_or(config.rust_debug_assertions); |
992 | ||
dc9dc135 | 993 | let with_defaults = |debuginfo_level_specific: Option<u32>| { |
dfeec247 | 994 | debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) { |
3dfed10e | 995 | 1 |
dfeec247 XL |
996 | } else { |
997 | 0 | |
998 | }) | |
dc9dc135 XL |
999 | }; |
1000 | config.rust_debuginfo_level_rustc = with_defaults(debuginfo_level_rustc); | |
1001 | config.rust_debuginfo_level_std = with_defaults(debuginfo_level_std); | |
1002 | config.rust_debuginfo_level_tools = with_defaults(debuginfo_level_tools); | |
1003 | config.rust_debuginfo_level_tests = debuginfo_level_tests.unwrap_or(0); | |
1004 | ||
ea8adc8c XL |
1005 | let default = config.channel == "dev"; |
1006 | config.ignore_git = ignore_git.unwrap_or(default); | |
8bb4bdeb | 1007 | |
ea8adc8c | 1008 | config |
7453a54e | 1009 | } |
32a655c1 | 1010 | |
60c5eb7d XL |
1011 | /// Try to find the relative path of `bindir`, otherwise return it in full. |
1012 | pub fn bindir_relative(&self) -> &Path { | |
1013 | let bindir = &self.bindir; | |
1014 | if bindir.is_absolute() { | |
1015 | // Try to make it relative to the prefix. | |
1016 | if let Some(prefix) = &self.prefix { | |
1017 | if let Ok(stripped) = bindir.strip_prefix(prefix) { | |
1018 | return stripped; | |
1019 | } | |
1020 | } | |
1021 | } | |
1022 | bindir | |
1023 | } | |
1024 | ||
2c00a5a8 XL |
1025 | /// Try to find the relative path of `libdir`. |
1026 | pub fn libdir_relative(&self) -> Option<&Path> { | |
1027 | let libdir = self.libdir.as_ref()?; | |
1028 | if libdir.is_relative() { | |
1029 | Some(libdir) | |
1030 | } else { | |
1031 | // Try to make it relative to the prefix. | |
1032 | libdir.strip_prefix(self.prefix.as_ref()?).ok() | |
1033 | } | |
1034 | } | |
1035 | ||
32a655c1 SL |
1036 | pub fn verbose(&self) -> bool { |
1037 | self.verbose > 0 | |
1038 | } | |
1039 | ||
1040 | pub fn very_verbose(&self) -> bool { | |
1041 | self.verbose > 1 | |
1042 | } | |
532ac7d7 | 1043 | |
29967ef6 | 1044 | pub fn sanitizers_enabled(&self, target: TargetSelection) -> bool { |
fc512014 | 1045 | self.target_config.get(&target).map(|t| t.sanitizers).flatten().unwrap_or(self.sanitizers) |
29967ef6 XL |
1046 | } |
1047 | ||
1048 | pub fn any_sanitizers_enabled(&self) -> bool { | |
fc512014 | 1049 | self.target_config.values().any(|t| t.sanitizers == Some(true)) || self.sanitizers |
29967ef6 XL |
1050 | } |
1051 | ||
1052 | pub fn profiler_enabled(&self, target: TargetSelection) -> bool { | |
fc512014 | 1053 | self.target_config.get(&target).map(|t| t.profiler).flatten().unwrap_or(self.profiler) |
29967ef6 XL |
1054 | } |
1055 | ||
1056 | pub fn any_profiler_enabled(&self) -> bool { | |
fc512014 | 1057 | self.target_config.values().any(|t| t.profiler == Some(true)) || self.profiler |
29967ef6 XL |
1058 | } |
1059 | ||
532ac7d7 XL |
1060 | pub fn llvm_enabled(&self) -> bool { |
1061 | self.rust_codegen_backends.contains(&INTERNER.intern_str("llvm")) | |
532ac7d7 | 1062 | } |
7453a54e SL |
1063 | } |
1064 | ||
1065 | fn set<T>(field: &mut T, val: Option<T>) { | |
1066 | if let Some(v) = val { | |
1067 | *field = v; | |
1068 | } | |
1069 | } | |
dc9dc135 XL |
1070 | |
1071 | fn threads_from_config(v: u32) -> u32 { | |
1072 | match v { | |
1073 | 0 => num_cpus::get() as u32, | |
1074 | n => n, | |
1075 | } | |
1076 | } |