1
1
use crate :: compile:: benchmark:: profile:: Profile ;
2
2
use anyhow:: { anyhow, Context } ;
3
3
use log:: debug;
4
+ use std:: ffi:: OsStr ;
4
5
use std:: fs:: { self , File } ;
5
6
use std:: io:: { BufReader , Read } ;
6
7
use std:: path:: { Path , PathBuf } ;
@@ -12,9 +13,7 @@ use xz2::bufread::XzDecoder;
12
13
/// Sysroot downloaded from CI.
13
14
pub struct Sysroot {
14
15
pub sha : String ,
15
- pub rustc : PathBuf ,
16
- pub rustdoc : PathBuf ,
17
- pub cargo : PathBuf ,
16
+ pub components : ToolchainComponents ,
18
17
pub triple : String ,
19
18
pub preserve : bool ,
20
19
}
@@ -121,10 +120,15 @@ impl SysrootDownload {
121
120
} )
122
121
} ;
123
122
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
+
124
130
Ok ( Sysroot {
125
- rustc : sysroot_bin ( "rustc" ) ?,
126
- rustdoc : sysroot_bin ( "rustdoc" ) ?,
127
- cargo : sysroot_bin ( "cargo" ) ?,
131
+ components,
128
132
sha : self . rust_sha ,
129
133
triple : self . triple ,
130
134
preserve : false ,
@@ -218,25 +222,72 @@ impl SysrootDownload {
218
222
/// Representation of a toolchain that can be used to compile Rust programs.
219
223
#[ derive( Debug , Clone ) ]
220
224
pub struct Toolchain {
221
- pub rustc : PathBuf ,
222
- pub rustdoc : Option < PathBuf > ,
223
- pub cargo : PathBuf ,
225
+ pub components : ToolchainComponents ,
224
226
pub id : String ,
225
227
pub triple : String ,
226
228
}
227
229
228
230
impl Toolchain {
229
231
pub fn from_sysroot ( sysroot : & Sysroot , id : String ) -> Self {
230
232
Self {
231
- rustc : sysroot. rustc . clone ( ) ,
232
- rustdoc : Some ( sysroot. rustdoc . clone ( ) ) ,
233
- cargo : sysroot. cargo . clone ( ) ,
233
+ components : sysroot. components . clone ( ) ,
234
234
id,
235
235
triple : sysroot. triple . clone ( ) ,
236
236
}
237
237
}
238
238
}
239
239
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
+
240
291
/// Get a toolchain from the input.
241
292
/// - `rustc`: check if the given one is acceptable.
242
293
/// - `rustdoc`: if one is given, check if it is acceptable. Otherwise, if
@@ -374,10 +425,10 @@ pub fn get_local_toolchain(
374
425
cargo
375
426
} ;
376
427
428
+ let lib_dir = get_lib_dir_from_rustc ( & rustc) . context ( "Cannot find libdir for rustc" ) ?;
429
+
377
430
Ok ( Toolchain {
378
- rustc,
379
- rustdoc,
380
- cargo,
431
+ components : ToolchainComponents :: from_binaries_and_libdir ( rustc, rustdoc, cargo, & lib_dir) ?,
381
432
id,
382
433
triple : target_triple,
383
434
} )
@@ -420,11 +471,25 @@ pub fn create_toolchain_from_published_version(
420
471
debug ! ( "Found rustdoc: {}" , rustdoc. display( ) ) ;
421
472
debug ! ( "Found cargo: {}" , cargo. display( ) ) ;
422
473
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
+
423
479
Ok ( Toolchain {
424
- rustc,
425
- rustdoc : Some ( rustdoc) ,
426
- cargo,
480
+ components,
427
481
id : toolchain. to_string ( ) ,
428
482
triple : target_triple. to_string ( ) ,
429
483
} )
430
484
}
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