@@ -150,8 +150,13 @@ impl Step for Std {
150150 fn run ( self , builder : & Builder < ' _ > ) {
151151 let target = self . target ;
152152
153- // We already have std ready to be used for stage 0.
154- if self . compiler . stage == 0 {
153+ // In most cases, we already have the std ready to be used for stage 0.
154+ // However, if we are doing a local rebuild (so the build compiler can compile the standard
155+ // library even on stage 0), and we're cross-compiling (so the stage0 standard library for
156+ // *target* is not available), we still allow the stdlib to be built here.
157+ if self . compiler . stage == 0
158+ && !( builder. local_rebuild && target != builder. host_target )
159+ {
155160 let compiler = self . compiler ;
156161 builder. ensure ( StdLink :: from_std ( self , compiler) ) ;
157162
@@ -204,13 +209,7 @@ impl Step for Std {
204209 let compiler_to_use = builder. compiler_for ( compiler. stage , compiler. host , target) ;
205210 trace ! ( ?compiler_to_use) ;
206211
207- if compiler_to_use != compiler
208- // Never uplift std unless we have compiled stage 1; if stage 1 is compiled,
209- // uplift it from there.
210- //
211- // FIXME: improve `fn compiler_for` to avoid adding stage condition here.
212- && compiler. stage > 1
213- {
212+ if compiler_to_use != compiler {
214213 trace ! ( ?compiler_to_use, ?compiler, "compiler != compiler_to_use, uplifting library" ) ;
215214
216215 builder. ensure ( Std :: new ( compiler_to_use, target) ) ;
@@ -235,6 +234,8 @@ impl Step for Std {
235234 return ;
236235 }
237236
237+
238+
238239 trace ! (
239240 ?compiler_to_use,
240241 ?compiler,
@@ -243,6 +244,27 @@ impl Step for Std {
243244
244245 target_deps. extend ( self . copy_extra_objects ( builder, & compiler, target) ) ;
245246
247+ // The LLD wrappers and `rust-lld` are self-contained linking components that can be
248+ // necessary to link the stdlib on some targets. We'll also need to copy these binaries to
249+ // the `stage0-sysroot` to ensure the linker is found when bootstrapping on such a target.
250+ if compiler. stage == 0 && builder. config . is_host_target ( compiler. host ) {
251+ trace ! (
252+ "(build == host) copying linking components to `stage0-sysroot` for bootstrapping"
253+ ) ;
254+ // We want to copy the host `bin` folder within the `rustlib` folder in the sysroot.
255+ let src_sysroot_bin = builder
256+ . rustc_snapshot_sysroot ( )
257+ . join ( "lib" )
258+ . join ( "rustlib" )
259+ . join ( compiler. host )
260+ . join ( "bin" ) ;
261+ if src_sysroot_bin. exists ( ) {
262+ let target_sysroot_bin = builder. sysroot_target_bindir ( compiler, target) ;
263+ t ! ( fs:: create_dir_all( & target_sysroot_bin) ) ;
264+ builder. cp_link_r ( & src_sysroot_bin, & target_sysroot_bin) ;
265+ }
266+ }
267+
246268 // We build a sysroot for mir-opt tests using the same trick that Miri does: A check build
247269 // with -Zalways-encode-mir. This frees us from the need to have a target linker, and the
248270 // fact that this is a check build integrates nicely with run_cargo.
@@ -762,16 +784,23 @@ impl Step for StdLink {
762784 ( libdir, hostdir)
763785 } ;
764786
765- let is_downloaded_beta_stage0 = builder
766- . build
767- . config
768- . initial_rustc
769- . starts_with ( builder. out . join ( compiler. host ) . join ( "stage0/bin" ) ) ;
787+ add_to_sysroot (
788+ builder,
789+ & libdir,
790+ & hostdir,
791+ & build_stamp:: libstd_stamp ( builder, compiler, target) ,
792+ ) ;
770793
771794 // Special case for stage0, to make `rustup toolchain link` and `x dist --stage 0`
772795 // work for stage0-sysroot. We only do this if the stage0 compiler comes from beta,
773796 // and is not set to a custom path.
774- if compiler. stage == 0 && is_downloaded_beta_stage0 {
797+ if compiler. stage == 0
798+ && builder
799+ . build
800+ . config
801+ . initial_rustc
802+ . starts_with ( builder. out . join ( compiler. host ) . join ( "stage0/bin" ) )
803+ {
775804 // Copy bin files from stage0/bin to stage0-sysroot/bin
776805 let sysroot = builder. out . join ( compiler. host ) . join ( "stage0-sysroot" ) ;
777806
@@ -781,9 +810,21 @@ impl Step for StdLink {
781810 t ! ( fs:: create_dir_all( & sysroot_bin_dir) ) ;
782811 builder. cp_link_r ( & stage0_bin_dir, & sysroot_bin_dir) ;
783812
813+ // Copy all files from stage0/lib to stage0-sysroot/lib
784814 let stage0_lib_dir = builder. out . join ( host) . join ( "stage0/lib" ) ;
785- t ! ( fs:: create_dir_all( sysroot. join( "lib" ) ) ) ;
786- builder. cp_link_r ( & stage0_lib_dir, & sysroot. join ( "lib" ) ) ;
815+ if let Ok ( files) = fs:: read_dir ( stage0_lib_dir) {
816+ for file in files {
817+ let file = t ! ( file) ;
818+ let path = file. path ( ) ;
819+ if path. is_file ( ) {
820+ builder. copy_link (
821+ & path,
822+ & sysroot. join ( "lib" ) . join ( path. file_name ( ) . unwrap ( ) ) ,
823+ FileType :: Regular ,
824+ ) ;
825+ }
826+ }
827+ }
787828
788829 // Copy codegen-backends from stage0
789830 let sysroot_codegen_backends = builder. sysroot_codegen_backends ( compiler) ;
@@ -797,30 +838,6 @@ impl Step for StdLink {
797838 if stage0_codegen_backends. exists ( ) {
798839 builder. cp_link_r ( & stage0_codegen_backends, & sysroot_codegen_backends) ;
799840 }
800- } else if compiler. stage == 0 {
801- let sysroot = builder. out . join ( compiler. host . triple ) . join ( "stage0-sysroot" ) ;
802-
803- if builder. local_rebuild {
804- // On local rebuilds this path might be a symlink to the project root,
805- // which can be read-only (e.g., on CI). So remove it before copying
806- // the stage0 lib.
807- let _ = fs:: remove_dir_all ( sysroot. join ( "lib/rustlib/src/rust" ) ) ;
808- }
809-
810- builder. cp_link_r ( & builder. initial_sysroot . join ( "lib" ) , & sysroot. join ( "lib" ) ) ;
811- } else {
812- if builder. download_rustc ( ) {
813- // Ensure there are no CI-rustc std artifacts.
814- let _ = fs:: remove_dir_all ( & libdir) ;
815- let _ = fs:: remove_dir_all ( & hostdir) ;
816- }
817-
818- add_to_sysroot (
819- builder,
820- & libdir,
821- & hostdir,
822- & build_stamp:: libstd_stamp ( builder, compiler, target) ,
823- ) ;
824841 }
825842 }
826843}
0 commit comments