11use crate :: compile:: benchmark:: profile:: Profile ;
22use anyhow:: { anyhow, Context } ;
33use log:: debug;
4+ use std:: ffi:: OsStr ;
45use std:: fs:: { self , File } ;
56use std:: io:: { BufReader , Read } ;
67use std:: path:: { Path , PathBuf } ;
@@ -12,9 +13,7 @@ use xz2::bufread::XzDecoder;
1213/// Sysroot downloaded from CI.
1314pub struct Sysroot {
1415 pub sha : String ,
15- pub rustc : PathBuf ,
16- pub rustdoc : PathBuf ,
17- pub cargo : PathBuf ,
16+ pub components : ToolchainComponents ,
1817 pub triple : String ,
1918 pub preserve : bool ,
2019}
@@ -121,10 +120,15 @@ impl SysrootDownload {
121120 } )
122121 } ;
123122
123+ let components = ToolchainComponents :: from_binaries_and_libdir (
124+ sysroot_bin ( "rustc" ) ?,
125+ Some ( sysroot_bin ( "rustdoc" ) ?) ,
126+ sysroot_bin ( "cargo" ) ?,
127+ & self . directory . join ( & self . rust_sha ) . join ( "lib" ) ,
128+ ) ?;
129+
124130 Ok ( Sysroot {
125- rustc : sysroot_bin ( "rustc" ) ?,
126- rustdoc : sysroot_bin ( "rustdoc" ) ?,
127- cargo : sysroot_bin ( "cargo" ) ?,
131+ components,
128132 sha : self . rust_sha ,
129133 triple : self . triple ,
130134 preserve : false ,
@@ -218,25 +222,72 @@ impl SysrootDownload {
218222/// Representation of a toolchain that can be used to compile Rust programs.
219223#[ derive( Debug , Clone ) ]
220224pub struct Toolchain {
221- pub rustc : PathBuf ,
222- pub rustdoc : Option < PathBuf > ,
223- pub cargo : PathBuf ,
225+ pub components : ToolchainComponents ,
224226 pub id : String ,
225227 pub triple : String ,
226228}
227229
228230impl Toolchain {
229231 pub fn from_sysroot ( sysroot : & Sysroot , id : String ) -> Self {
230232 Self {
231- rustc : sysroot. rustc . clone ( ) ,
232- rustdoc : Some ( sysroot. rustdoc . clone ( ) ) ,
233- cargo : sysroot. cargo . clone ( ) ,
233+ components : sysroot. components . clone ( ) ,
234234 id,
235235 triple : sysroot. triple . clone ( ) ,
236236 }
237237 }
238238}
239239
240+ #[ derive( Debug , Clone , Default ) ]
241+ pub struct ToolchainComponents {
242+ pub rustc : PathBuf ,
243+ pub rustdoc : Option < PathBuf > ,
244+ pub cargo : PathBuf ,
245+ pub lib_rustc : Option < PathBuf > ,
246+ pub lib_std : Option < PathBuf > ,
247+ pub lib_test : Option < PathBuf > ,
248+ pub lib_llvm : Option < PathBuf > ,
249+ }
250+
251+ impl ToolchainComponents {
252+ fn from_binaries_and_libdir (
253+ rustc : PathBuf ,
254+ rustdoc : Option < PathBuf > ,
255+ cargo : PathBuf ,
256+ libdir : & Path ,
257+ ) -> anyhow:: Result < Self > {
258+ let mut component = ToolchainComponents {
259+ rustc,
260+ rustdoc,
261+ cargo,
262+ ..Default :: default ( )
263+ } ;
264+ component. fill_libraries ( libdir) ?;
265+ Ok ( component)
266+ }
267+
268+ /// Finds known library components in the given `dir` and stores them in `self`.
269+ fn fill_libraries ( & mut self , dir : & Path ) -> anyhow:: Result < ( ) > {
270+ for entry in fs:: read_dir ( dir) . context ( "Cannot read lib dir to find components" ) ? {
271+ let entry = entry?;
272+ let path = entry. path ( ) ;
273+ if path. is_file ( ) && path. extension ( ) == Some ( OsStr :: new ( "so" ) ) {
274+ if let Some ( filename) = path. file_name ( ) . and_then ( |s| s. to_str ( ) ) {
275+ if filename. starts_with ( "libLLVM" ) {
276+ self . lib_llvm = Some ( path) ;
277+ } else if filename. starts_with ( "librustc_driver" ) {
278+ self . lib_rustc = Some ( path) ;
279+ } else if filename. starts_with ( "libstd" ) {
280+ self . lib_std = Some ( path) ;
281+ } else if filename. starts_with ( "libtest" ) {
282+ self . lib_test = Some ( path) ;
283+ }
284+ }
285+ }
286+ }
287+ Ok ( ( ) )
288+ }
289+ }
290+
240291/// Get a toolchain from the input.
241292/// - `rustc`: check if the given one is acceptable.
242293/// - `rustdoc`: if one is given, check if it is acceptable. Otherwise, if
@@ -374,10 +425,10 @@ pub fn get_local_toolchain(
374425 cargo
375426 } ;
376427
428+ let lib_dir = get_lib_dir_from_rustc ( & rustc) . context ( "Cannot find libdir for rustc" ) ?;
429+
377430 Ok ( Toolchain {
378- rustc,
379- rustdoc,
380- cargo,
431+ components : ToolchainComponents :: from_binaries_and_libdir ( rustc, rustdoc, cargo, & lib_dir) ?,
381432 id,
382433 triple : target_triple,
383434 } )
@@ -420,11 +471,25 @@ pub fn create_toolchain_from_published_version(
420471 debug ! ( "Found rustdoc: {}" , rustdoc. display( ) ) ;
421472 debug ! ( "Found cargo: {}" , cargo. display( ) ) ;
422473
474+ let lib_dir = get_lib_dir_from_rustc ( & rustc) ?;
475+
476+ let components =
477+ ToolchainComponents :: from_binaries_and_libdir ( rustc, Some ( rustdoc) , cargo, & lib_dir) ?;
478+
423479 Ok ( Toolchain {
424- rustc,
425- rustdoc : Some ( rustdoc) ,
426- cargo,
480+ components,
427481 id : toolchain. to_string ( ) ,
428482 triple : target_triple. to_string ( ) ,
429483 } )
430484}
485+
486+ fn get_lib_dir_from_rustc ( rustc : & Path ) -> anyhow:: Result < PathBuf > {
487+ let sysroot = Command :: new ( rustc)
488+ . arg ( "--print" )
489+ . arg ( "sysroot" )
490+ . output ( ) ?
491+ . stdout ;
492+ let sysroot_path = String :: from_utf8_lossy ( & sysroot) ;
493+
494+ Ok ( Path :: new ( sysroot_path. as_ref ( ) . trim ( ) ) . join ( "lib" ) )
495+ }
0 commit comments