about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/bootstrap/clean.rs84
-rw-r--r--src/bootstrap/flags.rs4
-rw-r--r--src/etc/completions/x.py.fish4
-rw-r--r--src/etc/completions/x.py.ps14
-rw-r--r--src/etc/completions/x.py.sh10
5 files changed, 75 insertions, 31 deletions
diff --git a/src/bootstrap/clean.rs b/src/bootstrap/clean.rs
index ea8334eaeb6..7389816b44c 100644
--- a/src/bootstrap/clean.rs
+++ b/src/bootstrap/clean.rs
@@ -26,10 +26,15 @@ impl Step for CleanAll {
     }
 
     fn run(self, builder: &Builder<'_>) -> Self::Output {
-        let Subcommand::Clean { all, .. } = builder.config.cmd else {
+        let Subcommand::Clean { all, stage } = builder.config.cmd else {
             unreachable!("wrong subcommand?")
         };
-        clean_default(builder.build, all)
+
+        if all && stage.is_some() {
+            panic!("--all and --stage can't be used at the same time for `x clean`");
+        }
+
+        clean(builder.build, all, stage)
     }
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
@@ -86,35 +91,70 @@ clean_crate_tree! {
     Std, Mode::Std, "sysroot";
 }
 
-fn clean_default(build: &Build, all: bool) {
+fn clean(build: &Build, all: bool, stage: Option<u32>) {
     if build.config.dry_run() {
         return;
     }
 
     rm_rf("tmp".as_ref());
 
+    // Clean the entire build directory
     if all {
         rm_rf(&build.out);
-    } else {
-        rm_rf(&build.out.join("tmp"));
-        rm_rf(&build.out.join("dist"));
-        rm_rf(&build.out.join("bootstrap"));
-        rm_rf(&build.out.join("rustfmt.stamp"));
-
-        for host in &build.hosts {
-            let entries = match build.out.join(host.triple).read_dir() {
-                Ok(iter) => iter,
-                Err(_) => continue,
-            };
-
-            for entry in entries {
-                let entry = t!(entry);
-                if entry.file_name().to_str() == Some("llvm") {
-                    continue;
-                }
-                let path = t!(entry.path().canonicalize());
-                rm_rf(&path);
+        return;
+    }
+
+    // Clean the target stage artifacts
+    if let Some(stage) = stage {
+        clean_specific_stage(build, stage);
+        return;
+    }
+
+    // Follow the default behaviour
+    clean_default(build);
+}
+
+fn clean_specific_stage(build: &Build, stage: u32) {
+    for host in &build.hosts {
+        let entries = match build.out.join(host.triple).read_dir() {
+            Ok(iter) => iter,
+            Err(_) => continue,
+        };
+
+        for entry in entries {
+            let entry = t!(entry);
+            let stage_prefix = format!("stage{}", stage);
+
+            // if current entry is not related with the target stage, continue
+            if !entry.file_name().to_str().unwrap_or("").contains(&stage_prefix) {
+                continue;
+            }
+
+            let path = t!(entry.path().canonicalize());
+            rm_rf(&path);
+        }
+    }
+}
+
+fn clean_default(build: &Build) {
+    rm_rf(&build.out.join("tmp"));
+    rm_rf(&build.out.join("dist"));
+    rm_rf(&build.out.join("bootstrap"));
+    rm_rf(&build.out.join("rustfmt.stamp"));
+
+    for host in &build.hosts {
+        let entries = match build.out.join(host.triple).read_dir() {
+            Ok(iter) => iter,
+            Err(_) => continue,
+        };
+
+        for entry in entries {
+            let entry = t!(entry);
+            if entry.file_name().to_str() == Some("llvm") {
+                continue;
             }
+            let path = t!(entry.path().canonicalize());
+            rm_rf(&path);
         }
     }
 }
diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs
index dbc52d94cae..96c9daf2c2c 100644
--- a/src/bootstrap/flags.rs
+++ b/src/bootstrap/flags.rs
@@ -366,7 +366,11 @@ pub enum Subcommand {
     /// Clean out build directories
     Clean {
         #[arg(long)]
+        /// Clean the entire build directory (not used by default)
         all: bool,
+        #[arg(long, value_name = "N")]
+        /// Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used.
+        stage: Option<u32>,
     },
     /// Build distribution artifacts
     Dist,
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
index 9f65f1eeeb7..b41362e8708 100644
--- a/src/etc/completions/x.py.fish
+++ b/src/etc/completions/x.py.fish
@@ -305,6 +305,7 @@ complete -c x.py -n "__fish_seen_subcommand_from bench" -l json-output -d 'use m
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-bolt-profile-generate -d 'generate BOLT profile for LLVM build'
 complete -c x.py -n "__fish_seen_subcommand_from bench" -s h -l help -d 'Print help'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l stage -d 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used' -r
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l config -d 'TOML configuration file for build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l build-dir -d 'Build directory, overrides `build.build-dir` in `config.toml`' -r -f -a "(__fish_complete_directories)"
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l build -d 'build target of the stage0 compiler' -r -f
@@ -313,7 +314,6 @@ complete -c x.py -n "__fish_seen_subcommand_from clean" -l target -d 'target tar
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l exclude -d 'build paths to exclude' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l rustc-error-format -r -f
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l on-fail -d 'command to run on failure' -r -f -a "(__fish_complete_command)"
-complete -c x.py -n "__fish_seen_subcommand_from clean" -l stage -d 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l keep-stage -d 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l keep-stage-std -d 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)' -r -f
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l src -d 'path to the root of the rust checkout' -r -f -a "(__fish_complete_directories)"
@@ -327,7 +327,7 @@ complete -c x.py -n "__fish_seen_subcommand_from clean" -l rust-profile-use -d '
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-use -d 'use PGO profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-bolt-profile-use -d 'use BOLT profile for LLVM build' -r -F
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l set -d 'override options in config.toml' -r -f
-complete -c x.py -n "__fish_seen_subcommand_from clean" -l all
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l all -d 'Clean the entire build directory (not used by default)'
 complete -c x.py -n "__fish_seen_subcommand_from clean" -s v -l verbose -d 'use verbose output (-vv for very verbose)'
 complete -c x.py -n "__fish_seen_subcommand_from clean" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l include-default-paths -d 'include default paths in addition to the provided ones'
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
index 569c186555c..5dbb1f496f4 100644
--- a/src/etc/completions/x.py.ps1
+++ b/src/etc/completions/x.py.ps1
@@ -391,6 +391,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             break
         }
         'x.py;clean' {
+            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'Clean a specific stage without touching other artifacts. By default, every stage is cleaned if this option is not used')
             [CompletionResult]::new('--config', 'config', [CompletionResultType]::ParameterName, 'TOML configuration file for build')
             [CompletionResult]::new('--build-dir', 'build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `config.toml`')
             [CompletionResult]::new('--build', 'build', [CompletionResultType]::ParameterName, 'build target of the stage0 compiler')
@@ -399,7 +400,6 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--exclude', 'exclude', [CompletionResultType]::ParameterName, 'build paths to exclude')
             [CompletionResult]::new('--rustc-error-format', 'rustc-error-format', [CompletionResultType]::ParameterName, 'rustc-error-format')
             [CompletionResult]::new('--on-fail', 'on-fail', [CompletionResultType]::ParameterName, 'command to run on failure')
-            [CompletionResult]::new('--stage', 'stage', [CompletionResultType]::ParameterName, 'stage to build (indicates compiler to use/test, e.g., stage 0 uses the bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)')
             [CompletionResult]::new('--keep-stage', 'keep-stage', [CompletionResultType]::ParameterName, 'stage(s) to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
             [CompletionResult]::new('--keep-stage-std', 'keep-stage-std', [CompletionResultType]::ParameterName, 'stage(s) of the standard library to keep without recompiling (pass multiple times to keep e.g., both stages 0 and 1)')
             [CompletionResult]::new('--src', 'src', [CompletionResultType]::ParameterName, 'path to the root of the rust checkout')
@@ -414,7 +414,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--llvm-profile-use', 'llvm-profile-use', [CompletionResultType]::ParameterName, 'use PGO profile for LLVM build')
             [CompletionResult]::new('--llvm-bolt-profile-use', 'llvm-bolt-profile-use', [CompletionResultType]::ParameterName, 'use BOLT profile for LLVM build')
             [CompletionResult]::new('--set', 'set', [CompletionResultType]::ParameterName, 'override options in config.toml')
-            [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'all')
+            [CompletionResult]::new('--all', 'all', [CompletionResultType]::ParameterName, 'Clean the entire build directory (not used by default)')
             [CompletionResult]::new('-v', 'v', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('--verbose', 'verbose', [CompletionResultType]::ParameterName, 'use verbose output (-vv for very verbose)')
             [CompletionResult]::new('-i', 'i', [CompletionResultType]::ParameterName, 'use incremental compilation')
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
index 322afdb2883..efce2758b92 100644
--- a/src/etc/completions/x.py.sh
+++ b/src/etc/completions/x.py.sh
@@ -489,12 +489,16 @@ _x.py() {
             return 0
             ;;
         x.py__clean)
-            opts="-v -i -j -h --all --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --llvm-bolt-profile-generate --llvm-bolt-profile-use --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
             fi
             case "${prev}" in
+                --stage)
+                    COMPREPLY=($(compgen -f "${cur}"))
+                    return 0
+                    ;;
                 --config)
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
@@ -527,10 +531,6 @@ _x.py() {
                     COMPREPLY=($(compgen -f "${cur}"))
                     return 0
                     ;;
-                --stage)
-                    COMPREPLY=("${cur}")
-                    return 0
-                    ;;
                 --keep-stage)
                     COMPREPLY=("${cur}")
                     return 0