@@ -253,12 +253,26 @@ pub enum Mode {
253253 /// These tools are intended to be only executed on the host system that
254254 /// invokes bootstrap, and they thus cannot be cross-compiled.
255255 ///
256- /// They are always built using the stage0 compiler, and typically they
256+ /// They are always built using the stage0 compiler, and they
257257 /// can be compiled with stable Rust.
258258 ///
259259 /// These tools also essentially do not participate in staging.
260260 ToolBootstrap ,
261261
262+ /// Build a cross-compilable helper tool.
263+ /// - If we compile it for the host, we use the stage0 compiler.
264+ /// - If we compile it for another target, we use local compiler (because stage0 does not have
265+ /// stdlib for the tool available for other targets).
266+ ///
267+ /// This mode exists to avoid needless (re)builds of tools that can be compiled with
268+ /// a stable/stage0 compiler. It essentially behaves as `ToolBootstrap` when not
269+ /// cross-compiling, and as `ToolStd` when cross-compiling.
270+ ///
271+ /// It is used e.g. for linkers and linker tools invoked by rustc on its host target.
272+ ///
273+ /// These tools participate in staging only when required for cross-compilation.
274+ ToolTarget ,
275+
262276 /// Build a tool which uses the locally built std, placing output in the
263277 /// "stageN-tools" directory. Its usage is quite rare, mainly used by
264278 /// compiletest which needs libtest.
@@ -804,17 +818,39 @@ impl Build {
804818 /// stage when running with a particular host compiler.
805819 ///
806820 /// The mode indicates what the root directory is for.
807- fn stage_out ( & self , compiler : Compiler , mode : Mode ) -> PathBuf {
808- let suffix = match mode {
809- Mode :: Std => "-std" ,
810- Mode :: Rustc => "-rustc" ,
811- Mode :: Codegen => "-codegen" ,
812- Mode :: ToolBootstrap => {
813- return self . out . join ( compiler. host ) . join ( "bootstrap-tools" ) ;
821+ fn stage_out ( & self , build_compiler : Compiler , mode : Mode ) -> PathBuf {
822+ use std:: fmt:: Write ;
823+
824+ fn bootstrap_tool ( ) -> ( Option < u32 > , & ' static str ) {
825+ ( None , "bootstrap-tools" )
826+ }
827+ fn staged_tool ( build_compiler : Compiler ) -> ( Option < u32 > , & ' static str ) {
828+ ( Some ( build_compiler. stage ) , "tools" )
829+ }
830+
831+ let ( stage, suffix) = match mode {
832+ Mode :: Std => ( Some ( build_compiler. stage ) , "std" ) ,
833+ Mode :: Rustc => ( Some ( build_compiler. stage ) , "rustc" ) ,
834+ Mode :: Codegen => ( Some ( build_compiler. stage ) , "codegen" ) ,
835+ Mode :: ToolBootstrap => bootstrap_tool ( ) ,
836+ Mode :: ToolStd | Mode :: ToolRustc => ( Some ( build_compiler. stage ) , "tools" ) ,
837+ Mode :: ToolTarget => {
838+ // If we're not cross-compiling (the common case), share the target directory with
839+ // bootstrap tools to reuse the build cache.
840+ if build_compiler. stage == 0 {
841+ bootstrap_tool ( )
842+ } else {
843+ staged_tool ( build_compiler)
844+ }
814845 }
815- Mode :: ToolStd | Mode :: ToolRustc => "-tools" ,
816846 } ;
817- self . out . join ( compiler. host ) . join ( format ! ( "stage{}{}" , compiler. stage, suffix) )
847+ let path = self . out . join ( build_compiler. host ) ;
848+ let mut dir_name = String :: new ( ) ;
849+ if let Some ( stage) = stage {
850+ write ! ( dir_name, "stage{stage}-" ) . unwrap ( ) ;
851+ }
852+ dir_name. push_str ( suffix) ;
853+ path. join ( dir_name)
818854 }
819855
820856 /// Returns the root output directory for all Cargo output in a given stage,
0 commit comments