@@ -681,15 +681,21 @@ impl Step for RemoteTestServer {
681681 }
682682}
683683
684- #[ derive( Debug , Clone , Hash , PartialEq , Eq , Ord , PartialOrd ) ]
684+ /// Represents `Rustdoc` that either comes from the external stage0 sysroot or that is built
685+ /// locally.
686+ /// Rustdoc is special, because it both essentially corresponds to a `Compiler` (that can be
687+ /// externally provided), but also to a `ToolRustc` tool.
688+ #[ derive( Debug , Clone , Hash , PartialEq , Eq ) ]
685689pub struct Rustdoc {
686- /// This should only ever be 0 or 2 .
687- /// We sometimes want to reference the "bootstrap" rustdoc, which is why this option is here .
690+ /// If the stage of `target_compiler` is `0`, then rustdoc is externally provided .
691+ /// Otherwise it is built locally .
688692 pub target_compiler : Compiler ,
689693}
690694
691695impl Step for Rustdoc {
692- type Output = ToolBuildResult ;
696+ /// Path to the built rustdoc binary.
697+ type Output = PathBuf ;
698+
693699 const DEFAULT : bool = true ;
694700 const ONLY_HOSTS : bool = true ;
695701
@@ -703,21 +709,20 @@ impl Step for Rustdoc {
703709 } ) ;
704710 }
705711
706- fn run ( self , builder : & Builder < ' _ > ) -> ToolBuildResult {
712+ fn run ( self , builder : & Builder < ' _ > ) -> Self :: Output {
707713 let target_compiler = self . target_compiler ;
708714 let target = target_compiler. host ;
709715
716+ // If stage is 0, we use a prebuilt rustdoc from stage0
710717 if target_compiler. stage == 0 {
711718 if !target_compiler. is_snapshot ( builder) {
712719 panic ! ( "rustdoc in stage 0 must be snapshot rustdoc" ) ;
713720 }
714721
715- return ToolBuildResult {
716- tool_path : builder. initial_rustdoc . clone ( ) ,
717- build_compiler : target_compiler,
718- } ;
722+ return builder. initial_rustdoc . clone ( ) ;
719723 }
720724
725+ // If stage is higher, we build rustdoc instead
721726 let bin_rustdoc = || {
722727 let sysroot = builder. sysroot ( target_compiler) ;
723728 let bindir = sysroot. join ( "bin" ) ;
@@ -729,10 +734,7 @@ impl Step for Rustdoc {
729734
730735 // If CI rustc is enabled and we haven't modified the rustdoc sources,
731736 // use the precompiled rustdoc from CI rustc's sysroot to speed up bootstrapping.
732- if builder. download_rustc ( )
733- && target_compiler. stage > 0
734- && builder. rust_info ( ) . is_managed_git_subrepository ( )
735- {
737+ if builder. download_rustc ( ) && builder. rust_info ( ) . is_managed_git_subrepository ( ) {
736738 let files_to_track = & [ "src/librustdoc" , "src/tools/rustdoc" , "src/rustdoc-json-types" ] ;
737739
738740 // Check if unchanged
@@ -745,8 +747,7 @@ impl Step for Rustdoc {
745747
746748 let bin_rustdoc = bin_rustdoc ( ) ;
747749 builder. copy_link ( & precompiled_rustdoc, & bin_rustdoc, FileType :: Executable ) ;
748-
749- return ToolBuildResult { tool_path : bin_rustdoc, build_compiler : target_compiler } ;
750+ return bin_rustdoc;
750751 }
751752 }
752753
@@ -762,45 +763,39 @@ impl Step for Rustdoc {
762763 extra_features. push ( "jemalloc" . to_string ( ) ) ;
763764 }
764765
765- let ToolBuildResult { tool_path, build_compiler } = builder. ensure ( ToolBuild {
766- build_compiler : target_compiler,
767- target,
768- // Cargo adds a number of paths to the dylib search path on windows, which results in
769- // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
770- // rustdoc a different name.
771- tool : "rustdoc_tool_binary" ,
772- mode : Mode :: ToolRustc ,
773- path : "src/tools/rustdoc" ,
774- source_type : SourceType :: InTree ,
775- extra_features,
776- allow_features : "" ,
777- cargo_args : Vec :: new ( ) ,
778- artifact_kind : ToolArtifactKind :: Binary ,
779- } ) ;
780-
781- // FIXME: handle the build/target compiler split here somehow
782- // don't create a stage0-sysroot/bin directory.
783- if target_compiler. stage > 0 {
784- if builder. config . rust_debuginfo_level_tools == DebuginfoLevel :: None {
785- // Due to LTO a lot of debug info from C++ dependencies such as jemalloc can make it into
786- // our final binaries
787- compile:: strip_debug ( builder, target, & tool_path) ;
788- }
789- let bin_rustdoc = bin_rustdoc ( ) ;
790- builder. copy_link ( & tool_path, & bin_rustdoc, FileType :: Executable ) ;
791- ToolBuildResult { tool_path : bin_rustdoc, build_compiler }
792- } else {
793- ToolBuildResult { tool_path, build_compiler }
766+ let compilers = RustcPrivateCompilers :: from_link_compiler ( builder, target_compiler) ;
767+ let tool_path = builder
768+ . ensure ( ToolBuild {
769+ build_compiler : compilers. build_compiler ,
770+ target,
771+ // Cargo adds a number of paths to the dylib search path on windows, which results in
772+ // the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
773+ // rustdoc a different name.
774+ tool : "rustdoc_tool_binary" ,
775+ mode : Mode :: ToolRustc ,
776+ path : "src/tools/rustdoc" ,
777+ source_type : SourceType :: InTree ,
778+ extra_features,
779+ allow_features : "" ,
780+ cargo_args : Vec :: new ( ) ,
781+ artifact_kind : ToolArtifactKind :: Binary ,
782+ } )
783+ . tool_path ;
784+
785+ if builder. config . rust_debuginfo_level_tools == DebuginfoLevel :: None {
786+ // Due to LTO a lot of debug info from C++ dependencies such as jemalloc can make it into
787+ // our final binaries
788+ compile:: strip_debug ( builder, target, & tool_path) ;
794789 }
790+ let bin_rustdoc = bin_rustdoc ( ) ;
791+ builder. copy_link ( & tool_path, & bin_rustdoc, FileType :: Executable ) ;
792+ bin_rustdoc
795793 }
796794
797795 fn metadata ( & self ) -> Option < StepMetadata > {
798796 Some (
799797 StepMetadata :: build ( "rustdoc" , self . target_compiler . host )
800- // rustdoc is ToolRustc, so stage N rustdoc is built by stage N-1 rustc
801- // FIXME: make this stage deduction automatic somehow
802- // FIXME: log the compiler that actually built ToolRustc steps
803- . stage ( self . target_compiler . stage . saturating_sub ( 1 ) ) ,
798+ . stage ( self . target_compiler . stage ) ,
804799 )
805800 }
806801}
@@ -1317,18 +1312,11 @@ impl RustcPrivateCompilers {
13171312 /// Create compilers for a `rustc_private` tool with the given `stage` and for the given
13181313 /// `target`.
13191314 pub fn new ( builder : & Builder < ' _ > , stage : u32 , target : TargetSelection ) -> Self {
1320- assert ! ( stage > 0 ) ;
1321-
1322- let build_compiler = if builder. download_rustc ( ) && stage == 1 {
1323- // We shouldn't drop to stage0 compiler when using CI rustc.
1324- builder. compiler ( 1 , builder. config . host_target )
1325- } else {
1326- builder. compiler ( stage - 1 , builder. config . host_target )
1327- } ;
1315+ let build_compiler = Self :: build_compiler_from_stage ( builder, stage) ;
13281316
13291317 // This is the compiler we'll link to
13301318 // FIXME: make 100% sure that `link_compiler` was indeed built with `build_compiler`...
1331- let link_compiler = builder. compiler ( stage, target) ;
1319+ let link_compiler = builder. compiler ( build_compiler . stage + 1 , target) ;
13321320
13331321 Self { build_compiler, link_compiler }
13341322 }
@@ -1343,6 +1331,25 @@ impl RustcPrivateCompilers {
13431331 Self { build_compiler, link_compiler }
13441332 }
13451333
1334+ /// Create rustc tool compilers from the link compiler.
1335+ pub fn from_link_compiler ( builder : & Builder < ' _ > , link_compiler : Compiler ) -> Self {
1336+ Self {
1337+ build_compiler : Self :: build_compiler_from_stage ( builder, link_compiler. stage ) ,
1338+ link_compiler,
1339+ }
1340+ }
1341+
1342+ fn build_compiler_from_stage ( builder : & Builder < ' _ > , stage : u32 ) -> Compiler {
1343+ assert ! ( stage > 0 ) ;
1344+
1345+ if builder. download_rustc ( ) && stage == 1 {
1346+ // We shouldn't drop to stage0 compiler when using CI rustc.
1347+ builder. compiler ( 1 , builder. config . host_target )
1348+ } else {
1349+ builder. compiler ( stage - 1 , builder. config . host_target )
1350+ }
1351+ }
1352+
13461353 pub fn build_compiler ( & self ) -> Compiler {
13471354 self . build_compiler
13481355 }
0 commit comments