Skip to content

Commit 328c61c

Browse files
committed
Make the default stage for x.py configurable
This allows configuring the default stage for each sub-command individually. - Normalize the stage as early as possible, so there's no confusion about which to use. - Don't add an explicit `stage` option in config.toml This offers no more flexibility than `*_stage` and makes it confusing which takes precedence. - Always give `--stage N` precedence over config.toml - Fix bootstrap tests This changes the tests to go through `Config::parse` so that they test the actual defaults, not the dummy ones provided by `default_opts`. To make this workable (and independent of the environment), it does not read `config.toml` for tests.
1 parent 12c10e3 commit 328c61c

File tree

4 files changed

+79
-42
lines changed

4 files changed

+79
-42
lines changed

config.toml.example

+17
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,23 @@
111111
# General build configuration options
112112
# =============================================================================
113113
[build]
114+
# The default stage to use for the `doc` subcommand
115+
#doc-stage = 0
116+
117+
# The default stage to use for the `build` subcommand
118+
#build-stage = 1
119+
120+
# The default stage to use for the `test` subcommand
121+
#test-stage = 1
122+
123+
# The default stage to use for the `dist` subcommand
124+
#dist-stage = 2
125+
126+
# The default stage to use for the `install` subcommand
127+
#install-stage = 2
128+
129+
# The default stage to use for the `bench` subcommand
130+
#bench-stage = 2
114131

115132
# Build triple for the original snapshot compiler. This must be a compiler that
116133
# nightlies are already produced for. The current platform must be able to run

src/bootstrap/builder.rs

+2-29
Original file line numberDiff line numberDiff line change
@@ -526,23 +526,9 @@ impl<'a> Builder<'a> {
526526
}
527527

528528
fn new_internal(build: &Build, kind: Kind, paths: Vec<PathBuf>) -> Builder<'_> {
529-
let top_stage = if let Some(explicit_stage) = build.config.stage {
530-
explicit_stage
531-
} else {
532-
// See https://github.com/rust-lang/compiler-team/issues/326
533-
match kind {
534-
Kind::Doc => 0,
535-
Kind::Build | Kind::Test => 1,
536-
Kind::Bench | Kind::Dist | Kind::Install => 2,
537-
// These are all bootstrap tools, which don't depend on the compiler.
538-
// The stage we pass shouldn't matter, but use 0 just in case.
539-
Kind::Check | Kind::Clippy | Kind::Fix | Kind::Run | Kind::Format => 0,
540-
}
541-
};
542-
543529
Builder {
544530
build,
545-
top_stage,
531+
top_stage: build.config.stage,
546532
kind,
547533
cache: Cache::new(),
548534
stack: RefCell::new(Vec::new()),
@@ -566,20 +552,7 @@ impl<'a> Builder<'a> {
566552
Subcommand::Format { .. } | Subcommand::Clean { .. } => panic!(),
567553
};
568554

569-
let this = Self::new_internal(build, kind, paths.to_owned());
570-
571-
// CI should always run stage 2 builds, unless it specifically states otherwise
572-
#[cfg(not(test))]
573-
if build.config.stage.is_none() && build.ci_env != crate::CiEnv::None {
574-
match kind {
575-
Kind::Test | Kind::Doc | Kind::Build | Kind::Bench | Kind::Dist | Kind::Install => {
576-
assert_eq!(this.top_stage, 2)
577-
}
578-
Kind::Check | Kind::Clippy | Kind::Fix | Kind::Run | Kind::Format => {}
579-
}
580-
}
581-
582-
this
555+
Self::new_internal(build, kind, paths.to_owned())
583556
}
584557

585558
pub fn execute_cli(&self) {

src/bootstrap/builder/tests.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use super::*;
22
use crate::config::{Config, TargetSelection};
33
use std::thread;
44

5-
fn configure(host: &[&str], target: &[&str]) -> Config {
6-
let mut config = Config::default_opts();
5+
fn configure(cmd: &str, host: &[&str], target: &[&str]) -> Config {
6+
let mut config = Config::parse(&[cmd.to_owned()]);
77
// don't save toolstates
88
config.save_toolstates = None;
99
config.skip_only_host_steps = false;
@@ -42,7 +42,7 @@ mod defaults {
4242

4343
#[test]
4444
fn build_default() {
45-
let build = Build::new(configure(&[], &[]));
45+
let build = Build::new(configure("build", &[], &[]));
4646
let mut builder = Builder::new(&build);
4747
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
4848

@@ -70,7 +70,7 @@ mod defaults {
7070

7171
#[test]
7272
fn build_stage_0() {
73-
let config = Config { stage: Some(0), ..configure(&[], &[]) };
73+
let config = Config { stage: 0, ..configure("build", &[], &[]) };
7474
let build = Build::new(config);
7575
let mut builder = Builder::new(&build);
7676
builder.run_step_descriptions(&Builder::get_step_descriptions(Kind::Build), &[]);
@@ -92,7 +92,7 @@ mod defaults {
9292

9393
#[test]
9494
fn doc_default() {
95-
let mut config = configure(&[], &[]);
95+
let mut config = configure("doc", &[], &[]);
9696
config.compiler_docs = true;
9797
config.cmd = Subcommand::Doc { paths: Vec::new(), open: false };
9898
let build = Build::new(config);
@@ -126,7 +126,7 @@ mod dist {
126126
use pretty_assertions::assert_eq;
127127

128128
fn configure(host: &[&str], target: &[&str]) -> Config {
129-
Config { stage: Some(2), ..super::configure(host, target) }
129+
Config { stage: 2, ..super::configure("dist", host, target) }
130130
}
131131

132132
#[test]
@@ -455,7 +455,7 @@ mod dist {
455455
#[test]
456456
fn test_with_no_doc_stage0() {
457457
let mut config = configure(&[], &[]);
458-
config.stage = Some(0);
458+
config.stage = 0;
459459
config.cmd = Subcommand::Test {
460460
paths: vec!["library/std".into()],
461461
test_args: vec![],

src/bootstrap/config.rs

+53-6
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use std::ffi::OsString;
1010
use std::fmt;
1111
use std::fs;
1212
use std::path::{Path, PathBuf};
13-
use std::process;
1413

1514
use crate::cache::{Interned, INTERNER};
1615
use crate::flags::Flags;
@@ -57,7 +56,7 @@ pub struct Config {
5756
pub skip_only_host_steps: bool,
5857

5958
pub on_fail: Option<String>,
60-
pub stage: Option<u32>,
59+
pub stage: u32,
6160
pub keep_stage: Vec<u32>,
6261
pub src: PathBuf,
6362
pub jobs: Option<u32>,
@@ -300,6 +299,12 @@ struct Build {
300299
configure_args: Option<Vec<String>>,
301300
local_rebuild: Option<bool>,
302301
print_step_timings: Option<bool>,
302+
doc_stage: Option<u32>,
303+
build_stage: Option<u32>,
304+
test_stage: Option<u32>,
305+
install_stage: Option<u32>,
306+
dist_stage: Option<u32>,
307+
bench_stage: Option<u32>,
303308
}
304309

305310
/// TOML representation of various global install decisions.
@@ -480,13 +485,11 @@ impl Config {
480485

481486
pub fn parse(args: &[String]) -> Config {
482487
let flags = Flags::parse(&args);
483-
let file = flags.config.clone();
484488
let mut config = Config::default_opts();
485489
config.exclude = flags.exclude;
486490
config.rustc_error_format = flags.rustc_error_format;
487491
config.json_output = flags.json_output;
488492
config.on_fail = flags.on_fail;
489-
config.stage = flags.stage;
490493
config.jobs = flags.jobs.map(threads_from_config);
491494
config.cmd = flags.cmd;
492495
config.incremental = flags.incremental;
@@ -503,8 +506,14 @@ impl Config {
503506
config.out = dir;
504507
}
505508

506-
let toml = file
509+
#[cfg(test)]
510+
let toml = TomlConfig::default();
511+
#[cfg(not(test))]
512+
let toml = flags
513+
.config
507514
.map(|file| {
515+
use std::process;
516+
508517
let contents = t!(fs::read_to_string(&file));
509518
match toml::from_str(&contents) {
510519
Ok(table) => table,
@@ -520,7 +529,7 @@ impl Config {
520529
})
521530
.unwrap_or_else(TomlConfig::default);
522531

523-
let build = toml.build.clone().unwrap_or_default();
532+
let build = toml.build.unwrap_or_default();
524533

525534
// If --target was specified but --host wasn't specified, don't run any host-only tests.
526535
let has_hosts = build.host.is_some() || flags.host.is_some();
@@ -564,6 +573,44 @@ impl Config {
564573
set(&mut config.configure_args, build.configure_args);
565574
set(&mut config.local_rebuild, build.local_rebuild);
566575
set(&mut config.print_step_timings, build.print_step_timings);
576+
577+
// See https://github.com/rust-lang/compiler-team/issues/326
578+
config.stage = match config.cmd {
579+
Subcommand::Doc { .. } => flags.stage.or(build.doc_stage).unwrap_or(0),
580+
Subcommand::Build { .. } => flags.stage.or(build.build_stage).unwrap_or(1),
581+
Subcommand::Test { .. } => flags.stage.or(build.test_stage).unwrap_or(1),
582+
Subcommand::Bench { .. } => flags.stage.or(build.bench_stage).unwrap_or(2),
583+
Subcommand::Dist { .. } => flags.stage.or(build.dist_stage).unwrap_or(2),
584+
Subcommand::Install { .. } => flags.stage.or(build.install_stage).unwrap_or(2),
585+
// These are all bootstrap tools, which don't depend on the compiler.
586+
// The stage we pass shouldn't matter, but use 0 just in case.
587+
Subcommand::Clean { .. }
588+
| Subcommand::Check { .. }
589+
| Subcommand::Clippy { .. }
590+
| Subcommand::Fix { .. }
591+
| Subcommand::Run { .. }
592+
| Subcommand::Format { .. } => flags.stage.unwrap_or(0),
593+
};
594+
595+
// CI should always run stage 2 builds, unless it specifically states otherwise
596+
#[cfg(not(test))]
597+
if flags.stage.is_none() && crate::CiEnv::current() != crate::CiEnv::None {
598+
match config.cmd {
599+
Subcommand::Test { .. }
600+
| Subcommand::Doc { .. }
601+
| Subcommand::Build { .. }
602+
| Subcommand::Bench { .. }
603+
| Subcommand::Dist { .. }
604+
| Subcommand::Install { .. } => assert_eq!(config.stage, 2),
605+
Subcommand::Clean { .. }
606+
| Subcommand::Check { .. }
607+
| Subcommand::Clippy { .. }
608+
| Subcommand::Fix { .. }
609+
| Subcommand::Run { .. }
610+
| Subcommand::Format { .. } => {}
611+
}
612+
}
613+
567614
config.verbose = cmp::max(config.verbose, flags.verbose);
568615

569616
if let Some(ref install) = toml.install {

0 commit comments

Comments
 (0)