@@ -289,20 +289,39 @@ pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
289
289
backend
290
290
}
291
291
292
- pub fn get_codegen_sysroot ( backend_name : & str ) -> fn ( ) -> Box < dyn CodegenBackend > {
293
- // For now we only allow this function to be called once as it'll dlopen a
294
- // few things, which seems to work best if we only do that once. In
295
- // general this assertion never trips due to the once guard in `get_codegen_backend`,
296
- // but there's a few manual calls to this function in this file we protect
297
- // against.
298
- static LOADED : AtomicBool = AtomicBool :: new ( false ) ;
299
- assert ! ( !LOADED . fetch_or( true , Ordering :: SeqCst ) ,
300
- "cannot load the default codegen backend twice" ) ;
292
+ // This is used for rustdoc, but it uses similar machinery to codegen backend
293
+ // loading, so we leave the code here. It is potentially useful for other tools
294
+ // that want to invoke the rustc binary while linking to rustc as well.
295
+ pub fn rustc_path < ' a > ( ) -> Option < & ' a Path > {
296
+ static RUSTC_PATH : once_cell:: sync:: OnceCell < Option < PathBuf > > =
297
+ once_cell:: sync:: OnceCell :: new ( ) ;
301
298
299
+ const BIN_PATH : & str = env ! ( "RUSTC_INSTALL_BINDIR" ) ;
300
+
301
+ RUSTC_PATH . get_or_init ( || get_rustc_path_inner ( BIN_PATH ) ) . as_ref ( ) . map ( |v| & * * v)
302
+ }
303
+
304
+ fn get_rustc_path_inner ( bin_path : & str ) -> Option < PathBuf > {
305
+ sysroot_candidates ( ) . iter ( )
306
+ . filter_map ( |sysroot| {
307
+ let candidate = sysroot. join ( bin_path) . join ( if cfg ! ( target_os = "windows" ) {
308
+ "rustc.exe"
309
+ } else {
310
+ "rustc"
311
+ } ) ;
312
+ if candidate. exists ( ) {
313
+ Some ( candidate)
314
+ } else {
315
+ None
316
+ }
317
+ } )
318
+ . next ( )
319
+ }
320
+
321
+ fn sysroot_candidates ( ) -> Vec < PathBuf > {
302
322
let target = session:: config:: host_triple ( ) ;
303
323
let mut sysroot_candidates = vec ! [ filesearch:: get_or_default_sysroot( ) ] ;
304
- let path = current_dll_path ( )
305
- . and_then ( |s| s. canonicalize ( ) . ok ( ) ) ;
324
+ let path = current_dll_path ( ) . and_then ( |s| s. canonicalize ( ) . ok ( ) ) ;
306
325
if let Some ( dll) = path {
307
326
// use `parent` twice to chop off the file name and then also the
308
327
// directory containing the dll which should be either `lib` or `bin`.
@@ -327,69 +346,7 @@ pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend
327
346
}
328
347
}
329
348
330
- let sysroot = sysroot_candidates. iter ( )
331
- . map ( |sysroot| {
332
- let libdir = filesearch:: relative_target_lib_path ( & sysroot, & target) ;
333
- sysroot. join ( libdir) . with_file_name (
334
- option_env ! ( "CFG_CODEGEN_BACKENDS_DIR" ) . unwrap_or ( "codegen-backends" ) )
335
- } )
336
- . filter ( |f| {
337
- info ! ( "codegen backend candidate: {}" , f. display( ) ) ;
338
- f. exists ( )
339
- } )
340
- . next ( ) ;
341
- let sysroot = sysroot. unwrap_or_else ( || {
342
- let candidates = sysroot_candidates. iter ( )
343
- . map ( |p| p. display ( ) . to_string ( ) )
344
- . collect :: < Vec < _ > > ( )
345
- . join ( "\n * " ) ;
346
- let err = format ! ( "failed to find a `codegen-backends` folder \
347
- in the sysroot candidates:\n * {}", candidates) ;
348
- early_error ( ErrorOutputType :: default ( ) , & err) ;
349
- } ) ;
350
- info ! ( "probing {} for a codegen backend" , sysroot. display( ) ) ;
351
-
352
- let d = sysroot. read_dir ( ) . unwrap_or_else ( |e| {
353
- let err = format ! ( "failed to load default codegen backend, couldn't \
354
- read `{}`: {}", sysroot. display( ) , e) ;
355
- early_error ( ErrorOutputType :: default ( ) , & err) ;
356
- } ) ;
357
-
358
- let mut file: Option < PathBuf > = None ;
359
-
360
- let expected_name = format ! ( "rustc_codegen_llvm-{}" , backend_name) ;
361
- for entry in d. filter_map ( |e| e. ok ( ) ) {
362
- let path = entry. path ( ) ;
363
- let filename = match path. file_name ( ) . and_then ( |s| s. to_str ( ) ) {
364
- Some ( s) => s,
365
- None => continue ,
366
- } ;
367
- if !( filename. starts_with ( DLL_PREFIX ) && filename. ends_with ( DLL_SUFFIX ) ) {
368
- continue
369
- }
370
- let name = & filename[ DLL_PREFIX . len ( ) .. filename. len ( ) - DLL_SUFFIX . len ( ) ] ;
371
- if name != expected_name {
372
- continue
373
- }
374
- if let Some ( ref prev) = file {
375
- let err = format ! ( "duplicate codegen backends found\n \
376
- first: {}\n \
377
- second: {}\n \
378
- ", prev. display( ) , path. display( ) ) ;
379
- early_error ( ErrorOutputType :: default ( ) , & err) ;
380
- }
381
- file = Some ( path. clone ( ) ) ;
382
- }
383
-
384
- match file {
385
- Some ( ref s) => return load_backend_from_dylib ( s) ,
386
- None => {
387
- let err = format ! ( "failed to load default codegen backend for `{}`, \
388
- no appropriate codegen dylib found in `{}`",
389
- backend_name, sysroot. display( ) ) ;
390
- early_error ( ErrorOutputType :: default ( ) , & err) ;
391
- }
392
- }
349
+ return sysroot_candidates;
393
350
394
351
#[ cfg( unix) ]
395
352
fn current_dll_path ( ) -> Option < PathBuf > {
@@ -459,6 +416,85 @@ pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend
459
416
}
460
417
}
461
418
419
+ pub fn get_codegen_sysroot ( backend_name : & str ) -> fn ( ) -> Box < dyn CodegenBackend > {
420
+ // For now we only allow this function to be called once as it'll dlopen a
421
+ // few things, which seems to work best if we only do that once. In
422
+ // general this assertion never trips due to the once guard in `get_codegen_backend`,
423
+ // but there's a few manual calls to this function in this file we protect
424
+ // against.
425
+ static LOADED : AtomicBool = AtomicBool :: new ( false ) ;
426
+ assert ! ( !LOADED . fetch_or( true , Ordering :: SeqCst ) ,
427
+ "cannot load the default codegen backend twice" ) ;
428
+
429
+ let target = session:: config:: host_triple ( ) ;
430
+ let sysroot_candidates = sysroot_candidates ( ) ;
431
+
432
+ let sysroot = sysroot_candidates. iter ( )
433
+ . map ( |sysroot| {
434
+ let libdir = filesearch:: relative_target_lib_path ( & sysroot, & target) ;
435
+ sysroot. join ( libdir) . with_file_name (
436
+ option_env ! ( "CFG_CODEGEN_BACKENDS_DIR" ) . unwrap_or ( "codegen-backends" ) )
437
+ } )
438
+ . filter ( |f| {
439
+ info ! ( "codegen backend candidate: {}" , f. display( ) ) ;
440
+ f. exists ( )
441
+ } )
442
+ . next ( ) ;
443
+ let sysroot = sysroot. unwrap_or_else ( || {
444
+ let candidates = sysroot_candidates. iter ( )
445
+ . map ( |p| p. display ( ) . to_string ( ) )
446
+ . collect :: < Vec < _ > > ( )
447
+ . join ( "\n * " ) ;
448
+ let err = format ! ( "failed to find a `codegen-backends` folder \
449
+ in the sysroot candidates:\n * {}", candidates) ;
450
+ early_error ( ErrorOutputType :: default ( ) , & err) ;
451
+ } ) ;
452
+ info ! ( "probing {} for a codegen backend" , sysroot. display( ) ) ;
453
+
454
+ let d = sysroot. read_dir ( ) . unwrap_or_else ( |e| {
455
+ let err = format ! ( "failed to load default codegen backend, couldn't \
456
+ read `{}`: {}", sysroot. display( ) , e) ;
457
+ early_error ( ErrorOutputType :: default ( ) , & err) ;
458
+ } ) ;
459
+
460
+ let mut file: Option < PathBuf > = None ;
461
+
462
+ let expected_name = format ! ( "rustc_codegen_llvm-{}" , backend_name) ;
463
+ for entry in d. filter_map ( |e| e. ok ( ) ) {
464
+ let path = entry. path ( ) ;
465
+ let filename = match path. file_name ( ) . and_then ( |s| s. to_str ( ) ) {
466
+ Some ( s) => s,
467
+ None => continue ,
468
+ } ;
469
+ if !( filename. starts_with ( DLL_PREFIX ) && filename. ends_with ( DLL_SUFFIX ) ) {
470
+ continue
471
+ }
472
+ let name = & filename[ DLL_PREFIX . len ( ) .. filename. len ( ) - DLL_SUFFIX . len ( ) ] ;
473
+ if name != expected_name {
474
+ continue
475
+ }
476
+ if let Some ( ref prev) = file {
477
+ let err = format ! ( "duplicate codegen backends found\n \
478
+ first: {}\n \
479
+ second: {}\n \
480
+ ", prev. display( ) , path. display( ) ) ;
481
+ early_error ( ErrorOutputType :: default ( ) , & err) ;
482
+ }
483
+ file = Some ( path. clone ( ) ) ;
484
+ }
485
+
486
+ match file {
487
+ Some ( ref s) => return load_backend_from_dylib ( s) ,
488
+ None => {
489
+ let err = format ! ( "failed to load default codegen backend for `{}`, \
490
+ no appropriate codegen dylib found in `{}`",
491
+ backend_name, sysroot. display( ) ) ;
492
+ early_error ( ErrorOutputType :: default ( ) , & err) ;
493
+ }
494
+ }
495
+
496
+ }
497
+
462
498
pub ( crate ) fn compute_crate_disambiguator ( session : & Session ) -> CrateDisambiguator {
463
499
use std:: hash:: Hasher ;
464
500
0 commit comments