@@ -9,7 +9,7 @@ use crate::core::builder::{Builder, Cargo as CargoCommand, RunConfig, ShouldRun,
99use  crate :: core:: config:: TargetSelection ; 
1010use  crate :: utils:: channel:: GitInfo ; 
1111use  crate :: utils:: exec:: { command,  BootstrapCommand } ; 
12- use  crate :: utils:: helpers:: { add_dylib_path,  exe,  t} ; 
12+ use  crate :: utils:: helpers:: { add_dylib_path,  exe,  get_closest_merge_base_commit ,  git ,   t} ; 
1313use  crate :: Compiler ; 
1414use  crate :: Mode ; 
1515use  crate :: { gha,  Kind } ; 
@@ -554,6 +554,54 @@ impl Step for Rustdoc {
554554        } 
555555        let  target = target_compiler. host ; 
556556
557+         let  bin_rustdoc = || { 
558+             let  sysroot = builder. sysroot ( target_compiler) ; 
559+             let  bindir = sysroot. join ( "bin" ) ; 
560+             t ! ( fs:: create_dir_all( & bindir) ) ; 
561+             let  bin_rustdoc = bindir. join ( exe ( "rustdoc" ,  target_compiler. host ) ) ; 
562+             let  _ = fs:: remove_file ( & bin_rustdoc) ; 
563+             bin_rustdoc
564+         } ; 
565+ 
566+         // If CI rustc is enabled and we haven't modified the rustdoc sources, 
567+         // use the precompiled rustdoc from CI rustc's sysroot to speed up bootstrapping. 
568+         if  builder. download_rustc ( ) 
569+             && target_compiler. stage  > 0 
570+             && builder. rust_info ( ) . is_managed_git_subrepository ( ) 
571+         { 
572+             let  commit = get_closest_merge_base_commit ( 
573+                 Some ( & builder. config . src ) , 
574+                 & builder. config . git_config ( ) , 
575+                 & builder. config . stage0_metadata . config . git_merge_commit_email , 
576+                 & [ ] , 
577+             ) 
578+             . unwrap ( ) ; 
579+ 
580+             let  librustdoc_src = builder. config . src . join ( "src/librustdoc" ) ; 
581+             let  rustdoc_src = builder. config . src . join ( "src/tools/rustdoc" ) ; 
582+ 
583+             let  has_changes = !git ( Some ( & builder. config . src ) ) 
584+                 . allow_failure ( ) 
585+                 . args ( [ "diff-index" ,  "--quiet" ,  & commit] ) 
586+                 . arg ( "--" ) 
587+                 . arg ( librustdoc_src) 
588+                 . arg ( rustdoc_src) 
589+                 . run ( builder) 
590+                 . is_success ( ) ; 
591+ 
592+             if  !has_changes { 
593+                 let  precompiled_rustdoc = builder
594+                     . config 
595+                     . ci_rustc_dir ( ) 
596+                     . join ( "bin" ) 
597+                     . join ( exe ( "rustdoc" ,  target_compiler. host ) ) ; 
598+ 
599+                 let  bin_rustdoc = bin_rustdoc ( ) ; 
600+                 builder. copy_link ( & precompiled_rustdoc,  & bin_rustdoc) ; 
601+                 return  bin_rustdoc; 
602+             } 
603+         } 
604+ 
557605        let  build_compiler = if  builder. download_rustc ( )  && target_compiler. stage  == 1  { 
558606            // We already have the stage 1 compiler, we don't need to cut the stage. 
559607            builder. compiler ( target_compiler. stage ,  builder. config . build ) 
@@ -614,11 +662,7 @@ impl Step for Rustdoc {
614662
615663        // don't create a stage0-sysroot/bin directory. 
616664        if  target_compiler. stage  > 0  { 
617-             let  sysroot = builder. sysroot ( target_compiler) ; 
618-             let  bindir = sysroot. join ( "bin" ) ; 
619-             t ! ( fs:: create_dir_all( & bindir) ) ; 
620-             let  bin_rustdoc = bindir. join ( exe ( "rustdoc" ,  target_compiler. host ) ) ; 
621-             let  _ = fs:: remove_file ( & bin_rustdoc) ; 
665+             let  bin_rustdoc = bin_rustdoc ( ) ; 
622666            builder. copy_link ( & tool_rustdoc,  & bin_rustdoc) ; 
623667            bin_rustdoc
624668        }  else  { 
0 commit comments