11use std:: fs;
2- use std:: path:: Path ;
2+ use std:: path:: { Path , PathBuf } ;
33use std:: process:: { self , Command } ;
44
55use super :: path:: { Dirs , RelPath } ;
6- use super :: rustc_info:: {
7- get_file_name, get_rustc_version, get_toolchain_name, get_wrapper_file_name,
8- } ;
6+ use super :: rustc_info:: { get_file_name, get_rustc_version, get_toolchain_name} ;
97use super :: utils:: { spawn_and_wait, try_hard_link, CargoProject , Compiler } ;
108use super :: SysrootKind ;
119
1210static DIST_DIR : RelPath = RelPath :: DIST ;
1311static BIN_DIR : RelPath = RelPath :: DIST . join ( "bin" ) ;
1412static LIB_DIR : RelPath = RelPath :: DIST . join ( "lib" ) ;
15- static RUSTLIB_DIR : RelPath = LIB_DIR . join ( "rustlib" ) ;
1613
1714pub ( crate ) fn build_sysroot (
1815 dirs : & Dirs ,
@@ -39,145 +36,169 @@ pub(crate) fn build_sysroot(
3936 LIB_DIR
4037 }
4138 . to_path ( dirs)
42- . join ( get_file_name ( "rustc_codegen_cranelift" , "dylib" ) ) ;
39+ . join ( cg_clif_dylib_src . file_name ( ) . unwrap ( ) ) ;
4340 try_hard_link ( cg_clif_dylib_src, & cg_clif_dylib_path) ;
4441
4542 // Build and copy rustc and cargo wrappers
43+ let wrapper_base_name = get_file_name ( "____" , "bin" ) ;
44+ let toolchain_name = get_toolchain_name ( ) ;
4645 for wrapper in [ "rustc-clif" , "rustdoc-clif" , "cargo-clif" ] {
47- let wrapper_name = get_wrapper_file_name ( wrapper , "bin" ) ;
46+ let wrapper_name = wrapper_base_name . replace ( "____" , wrapper ) ;
4847
4948 let mut build_cargo_wrapper_cmd = Command :: new ( & bootstrap_host_compiler. rustc ) ;
5049 build_cargo_wrapper_cmd
51- . env ( "TOOLCHAIN_NAME" , get_toolchain_name ( ) )
50+ . env ( "TOOLCHAIN_NAME" , toolchain_name . clone ( ) )
5251 . arg ( RelPath :: SCRIPTS . to_path ( dirs) . join ( & format ! ( "{wrapper}.rs" ) ) )
5352 . arg ( "-o" )
5453 . arg ( DIST_DIR . to_path ( dirs) . join ( wrapper_name) )
55- . arg ( "-g " ) ;
54+ . arg ( "-Cstrip=debuginfo " ) ;
5655 spawn_and_wait ( build_cargo_wrapper_cmd) ;
5756 }
5857
59- let default_sysroot = super :: rustc_info:: get_default_sysroot ( & bootstrap_host_compiler. rustc ) ;
58+ let host = build_sysroot_for_triple (
59+ dirs,
60+ channel,
61+ bootstrap_host_compiler. clone ( ) ,
62+ & cg_clif_dylib_path,
63+ sysroot_kind,
64+ ) ;
65+ host. install_into_sysroot ( & DIST_DIR . to_path ( dirs) ) ;
6066
61- let host_rustlib_lib =
62- RUSTLIB_DIR . to_path ( dirs) . join ( & bootstrap_host_compiler. triple ) . join ( "lib" ) ;
63- let target_rustlib_lib = RUSTLIB_DIR . to_path ( dirs) . join ( & target_triple) . join ( "lib" ) ;
64- fs:: create_dir_all ( & host_rustlib_lib) . unwrap ( ) ;
65- fs:: create_dir_all ( & target_rustlib_lib) . unwrap ( ) ;
66-
67- if target_triple == "x86_64-pc-windows-gnu" {
68- if !default_sysroot. join ( "lib" ) . join ( "rustlib" ) . join ( & target_triple) . join ( "lib" ) . exists ( ) {
69- eprintln ! (
70- "The x86_64-pc-windows-gnu target needs to be installed first before it is possible \
71- to compile a sysroot for it.",
72- ) ;
73- process:: exit ( 1 ) ;
74- }
75- for file in fs:: read_dir (
76- default_sysroot. join ( "lib" ) . join ( "rustlib" ) . join ( & target_triple) . join ( "lib" ) ,
67+ if !is_native {
68+ build_sysroot_for_triple (
69+ dirs,
70+ channel,
71+ {
72+ let mut bootstrap_target_compiler = bootstrap_host_compiler. clone ( ) ;
73+ bootstrap_target_compiler. triple = target_triple. clone ( ) ;
74+ bootstrap_target_compiler. set_cross_linker_and_runner ( ) ;
75+ bootstrap_target_compiler
76+ } ,
77+ & cg_clif_dylib_path,
78+ sysroot_kind,
7779 )
78- . unwrap ( )
79- {
80- let file = file. unwrap ( ) . path ( ) ;
81- if file. extension ( ) . map_or ( true , |ext| ext. to_str ( ) . unwrap ( ) != "o" ) {
82- continue ; // only copy object files
83- }
84- try_hard_link ( & file, target_rustlib_lib. join ( file. file_name ( ) . unwrap ( ) ) ) ;
85- }
80+ . install_into_sysroot ( & DIST_DIR . to_path ( dirs) ) ;
8681 }
8782
88- match sysroot_kind {
89- SysrootKind :: None => { } // Nothing to do
90- SysrootKind :: Llvm => {
91- for file in fs:: read_dir (
92- default_sysroot
93- . join ( "lib" )
94- . join ( "rustlib" )
95- . join ( & bootstrap_host_compiler. triple )
96- . join ( "lib" ) ,
97- )
98- . unwrap ( )
99- {
100- let file = file. unwrap ( ) . path ( ) ;
101- let file_name_str = file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
102- if ( file_name_str. contains ( "rustc_" )
103- && !file_name_str. contains ( "rustc_std_workspace_" )
104- && !file_name_str. contains ( "rustc_demangle" ) )
105- || file_name_str. contains ( "chalk" )
106- || file_name_str. contains ( "tracing" )
107- || file_name_str. contains ( "regex" )
108- {
109- // These are large crates that are part of the rustc-dev component and are not
110- // necessary to run regular programs.
111- continue ;
112- }
113- try_hard_link ( & file, host_rustlib_lib. join ( file. file_name ( ) . unwrap ( ) ) ) ;
114- }
115-
116- if !is_native {
117- for file in fs:: read_dir (
118- default_sysroot. join ( "lib" ) . join ( "rustlib" ) . join ( & target_triple) . join ( "lib" ) ,
119- )
120- . unwrap ( )
121- {
122- let file = file. unwrap ( ) . path ( ) ;
123- try_hard_link ( & file, target_rustlib_lib. join ( file. file_name ( ) . unwrap ( ) ) ) ;
124- }
125- }
126- }
127- SysrootKind :: Clif => {
128- build_clif_sysroot_for_triple (
129- dirs,
130- channel,
131- bootstrap_host_compiler. clone ( ) ,
132- & cg_clif_dylib_path,
133- ) ;
134-
135- if !is_native {
136- build_clif_sysroot_for_triple (
137- dirs,
138- channel,
139- {
140- let mut bootstrap_target_compiler = bootstrap_host_compiler. clone ( ) ;
141- bootstrap_target_compiler. triple = target_triple. clone ( ) ;
142- bootstrap_target_compiler. set_cross_linker_and_runner ( ) ;
143- bootstrap_target_compiler
144- } ,
145- & cg_clif_dylib_path,
146- ) ;
147- }
148-
149- // Copy std for the host to the lib dir. This is necessary for the jit mode to find
150- // libstd.
151- for file in fs:: read_dir ( host_rustlib_lib) . unwrap ( ) {
152- let file = file. unwrap ( ) . path ( ) ;
153- let filename = file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
154- if filename. contains ( "std-" ) && !filename. contains ( ".rlib" ) {
155- try_hard_link ( & file, LIB_DIR . to_path ( dirs) . join ( file. file_name ( ) . unwrap ( ) ) ) ;
156- }
157- }
83+ // Copy std for the host to the lib dir. This is necessary for the jit mode to find
84+ // libstd.
85+ for lib in host. libs {
86+ let filename = lib. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
87+ if filename. contains ( "std-" ) && !filename. contains ( ".rlib" ) {
88+ try_hard_link ( & lib, LIB_DIR . to_path ( dirs) . join ( lib. file_name ( ) . unwrap ( ) ) ) ;
15889 }
15990 }
16091
161- let mut target_compiler = Compiler :: clif_with_triple ( & dirs, target_triple) ;
92+ let mut target_compiler = {
93+ let dirs: & Dirs = & dirs;
94+ let rustc_clif =
95+ RelPath :: DIST . to_path ( & dirs) . join ( wrapper_base_name. replace ( "____" , "rustc-clif" ) ) ;
96+ let rustdoc_clif =
97+ RelPath :: DIST . to_path ( & dirs) . join ( wrapper_base_name. replace ( "____" , "rustdoc-clif" ) ) ;
98+
99+ Compiler {
100+ cargo : bootstrap_host_compiler. cargo . clone ( ) ,
101+ rustc : rustc_clif. clone ( ) ,
102+ rustdoc : rustdoc_clif. clone ( ) ,
103+ rustflags : String :: new ( ) ,
104+ rustdocflags : String :: new ( ) ,
105+ triple : target_triple,
106+ runner : vec ! [ ] ,
107+ }
108+ } ;
162109 if !is_native {
163110 target_compiler. set_cross_linker_and_runner ( ) ;
164111 }
165112 target_compiler
166113}
167114
115+ struct SysrootTarget {
116+ triple : String ,
117+ libs : Vec < PathBuf > ,
118+ }
119+
120+ impl SysrootTarget {
121+ fn install_into_sysroot ( & self , sysroot : & Path ) {
122+ if self . libs . is_empty ( ) {
123+ return ;
124+ }
125+
126+ let target_rustlib_lib = sysroot. join ( "lib" ) . join ( "rustlib" ) . join ( & self . triple ) . join ( "lib" ) ;
127+ fs:: create_dir_all ( & target_rustlib_lib) . unwrap ( ) ;
128+
129+ for lib in & self . libs {
130+ try_hard_link ( lib, target_rustlib_lib. join ( lib. file_name ( ) . unwrap ( ) ) ) ;
131+ }
132+ }
133+ }
134+
168135pub ( crate ) static ORIG_BUILD_SYSROOT : RelPath = RelPath :: SOURCE . join ( "build_sysroot" ) ;
169136pub ( crate ) static BUILD_SYSROOT : RelPath = RelPath :: DOWNLOAD . join ( "sysroot" ) ;
170137pub ( crate ) static SYSROOT_RUSTC_VERSION : RelPath = BUILD_SYSROOT . join ( "rustc_version" ) ;
171138pub ( crate ) static SYSROOT_SRC : RelPath = BUILD_SYSROOT . join ( "sysroot_src" ) ;
172139pub ( crate ) static STANDARD_LIBRARY : CargoProject =
173140 CargoProject :: new ( & BUILD_SYSROOT , "build_sysroot" ) ;
141+ pub ( crate ) static RTSTARTUP_SYSROOT : RelPath = RelPath :: BUILD . join ( "rtstartup" ) ;
174142
143+ #[ must_use]
144+ fn build_sysroot_for_triple (
145+ dirs : & Dirs ,
146+ channel : & str ,
147+ compiler : Compiler ,
148+ cg_clif_dylib_path : & Path ,
149+ sysroot_kind : SysrootKind ,
150+ ) -> SysrootTarget {
151+ match sysroot_kind {
152+ SysrootKind :: None => build_rtstartup ( dirs, & compiler)
153+ . unwrap_or ( SysrootTarget { triple : compiler. triple , libs : vec ! [ ] } ) ,
154+ SysrootKind :: Llvm => build_llvm_sysroot_for_triple ( compiler) ,
155+ SysrootKind :: Clif => {
156+ build_clif_sysroot_for_triple ( dirs, channel, compiler, & cg_clif_dylib_path)
157+ }
158+ }
159+ }
160+
161+ #[ must_use]
162+ fn build_llvm_sysroot_for_triple ( compiler : Compiler ) -> SysrootTarget {
163+ let default_sysroot = super :: rustc_info:: get_default_sysroot ( & compiler. rustc ) ;
164+
165+ let mut target_libs = SysrootTarget { triple : compiler. triple , libs : vec ! [ ] } ;
166+
167+ for entry in fs:: read_dir (
168+ default_sysroot. join ( "lib" ) . join ( "rustlib" ) . join ( & target_libs. triple ) . join ( "lib" ) ,
169+ )
170+ . unwrap ( )
171+ {
172+ let entry = entry. unwrap ( ) ;
173+ if entry. file_type ( ) . unwrap ( ) . is_dir ( ) {
174+ continue ;
175+ }
176+ let file = entry. path ( ) ;
177+ let file_name_str = file. file_name ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
178+ if ( file_name_str. contains ( "rustc_" )
179+ && !file_name_str. contains ( "rustc_std_workspace_" )
180+ && !file_name_str. contains ( "rustc_demangle" ) )
181+ || file_name_str. contains ( "chalk" )
182+ || file_name_str. contains ( "tracing" )
183+ || file_name_str. contains ( "regex" )
184+ {
185+ // These are large crates that are part of the rustc-dev component and are not
186+ // necessary to run regular programs.
187+ continue ;
188+ }
189+ target_libs. libs . push ( file) ;
190+ }
191+
192+ target_libs
193+ }
194+
195+ #[ must_use]
175196fn build_clif_sysroot_for_triple (
176197 dirs : & Dirs ,
177198 channel : & str ,
178199 mut compiler : Compiler ,
179200 cg_clif_dylib_path : & Path ,
180- ) {
201+ ) -> SysrootTarget {
181202 match fs:: read_to_string ( SYSROOT_RUSTC_VERSION . to_path ( dirs) ) {
182203 Err ( e) => {
183204 eprintln ! ( "Failed to get rustc version for patched sysroot source: {}" , e) ;
@@ -196,6 +217,14 @@ fn build_clif_sysroot_for_triple(
196217 }
197218 }
198219
220+ let mut target_libs = SysrootTarget { triple : compiler. triple . clone ( ) , libs : vec ! [ ] } ;
221+
222+ if let Some ( rtstartup_target_libs) = build_rtstartup ( dirs, & compiler) {
223+ rtstartup_target_libs. install_into_sysroot ( & RTSTARTUP_SYSROOT . to_path ( dirs) ) ;
224+
225+ target_libs. libs . extend ( rtstartup_target_libs. libs ) ;
226+ }
227+
199228 let build_dir = STANDARD_LIBRARY . target_dir ( dirs) . join ( & compiler. triple ) . join ( channel) ;
200229
201230 if !super :: config:: get_bool ( "keep_sysroot" ) {
@@ -209,7 +238,9 @@ fn build_clif_sysroot_for_triple(
209238 // Build sysroot
210239 let mut rustflags = " -Zforce-unstable-if-unmarked -Cpanic=abort" . to_string ( ) ;
211240 rustflags. push_str ( & format ! ( " -Zcodegen-backend={}" , cg_clif_dylib_path. to_str( ) . unwrap( ) ) ) ;
212- rustflags. push_str ( & format ! ( " --sysroot={}" , DIST_DIR . to_path( dirs) . to_str( ) . unwrap( ) ) ) ;
241+ // Necessary for MinGW to find rsbegin.o and rsend.o
242+ rustflags
243+ . push_str ( & format ! ( " --sysroot={}" , RTSTARTUP_SYSROOT . to_path( dirs) . to_str( ) . unwrap( ) ) ) ;
213244 if channel == "release" {
214245 rustflags. push_str ( " -Zmir-opt-level=3" ) ;
215246 }
@@ -221,7 +252,6 @@ fn build_clif_sysroot_for_triple(
221252 build_cmd. env ( "__CARGO_DEFAULT_LIB_METADATA" , "cg_clif" ) ;
222253 spawn_and_wait ( build_cmd) ;
223254
224- // Copy all relevant files to the sysroot
225255 for entry in fs:: read_dir ( build_dir. join ( "deps" ) ) . unwrap ( ) {
226256 let entry = entry. unwrap ( ) ;
227257 if let Some ( ext) = entry. path ( ) . extension ( ) {
@@ -231,9 +261,35 @@ fn build_clif_sysroot_for_triple(
231261 } else {
232262 continue ;
233263 } ;
234- try_hard_link (
235- entry. path ( ) ,
236- RUSTLIB_DIR . to_path ( dirs) . join ( & compiler. triple ) . join ( "lib" ) . join ( entry. file_name ( ) ) ,
237- ) ;
264+ target_libs. libs . push ( entry. path ( ) ) ;
265+ }
266+
267+ target_libs
268+ }
269+
270+ fn build_rtstartup ( dirs : & Dirs , compiler : & Compiler ) -> Option < SysrootTarget > {
271+ if !compiler. triple . ends_with ( "windows-gnu" ) {
272+ return None ;
273+ }
274+
275+ RTSTARTUP_SYSROOT . ensure_fresh ( dirs) ;
276+
277+ let rtstartup_src = SYSROOT_SRC . to_path ( dirs) . join ( "library" ) . join ( "rtstartup" ) ;
278+ let mut target_libs = SysrootTarget { triple : compiler. triple . clone ( ) , libs : vec ! [ ] } ;
279+
280+ for file in [ "rsbegin" , "rsend" ] {
281+ let obj = RTSTARTUP_SYSROOT . to_path ( dirs) . join ( format ! ( "{file}.o" ) ) ;
282+ let mut build_rtstartup_cmd = Command :: new ( & compiler. rustc ) ;
283+ build_rtstartup_cmd
284+ . arg ( "--target" )
285+ . arg ( & compiler. triple )
286+ . arg ( "--emit=obj" )
287+ . arg ( "-o" )
288+ . arg ( & obj)
289+ . arg ( rtstartup_src. join ( format ! ( "{file}.rs" ) ) ) ;
290+ spawn_and_wait ( build_rtstartup_cmd) ;
291+ target_libs. libs . push ( obj. clone ( ) ) ;
238292 }
293+
294+ Some ( target_libs)
239295}
0 commit comments