@@ -289,20 +289,39 @@ pub fn get_codegen_backend(sess: &Session) -> Box<dyn CodegenBackend> {
289289 backend
290290}
291291
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 ( ) ;
301298
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 > {
302322 let target = session:: config:: host_triple ( ) ;
303323 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 ( ) ) ;
306325 if let Some ( dll) = path {
307326 // use `parent` twice to chop off the file name and then also the
308327 // 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
327346 }
328347 }
329348
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;
393350
394351 #[ cfg( unix) ]
395352 fn current_dll_path ( ) -> Option < PathBuf > {
@@ -459,6 +416,85 @@ pub fn get_codegen_sysroot(backend_name: &str) -> fn() -> Box<dyn CodegenBackend
459416 }
460417}
461418
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+
462498pub ( crate ) fn compute_crate_disambiguator ( session : & Session ) -> CrateDisambiguator {
463499 use std:: hash:: Hasher ;
464500
0 commit comments