11//! Validates all used crates and extern libraries and loads their metadata
22
33use std:: error:: Error ;
4+ use std:: ffi:: OsString ;
45use std:: ops:: Fn ;
56use std:: path:: Path ;
67use std:: str:: FromStr ;
@@ -539,6 +540,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
539540 Some ( cnum)
540541 }
541542 Err ( err) => {
543+ debug ! ( "failed to resolve crate {} {:?}" , name, dep_kind) ;
542544 let missing_core =
543545 self . maybe_resolve_crate ( sym:: core, CrateDepKind :: Explicit , None ) . is_err ( ) ;
544546 err. report ( self . sess , span, missing_core) ;
@@ -587,6 +589,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
587589 match self . load ( & mut locator) ? {
588590 Some ( res) => ( res, None ) ,
589591 None => {
592+ info ! ( "falling back to loading proc_macro" ) ;
590593 dep_kind = CrateDepKind :: MacrosOnly ;
591594 match self . load_proc_macro ( & mut locator, path_kind, host_hash) ? {
592595 Some ( res) => res,
@@ -598,6 +601,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
598601
599602 match result {
600603 ( LoadResult :: Previous ( cnum) , None ) => {
604+ info ! ( "library for `{}` was loaded previously" , name) ;
601605 // When `private_dep` is none, it indicates the directly dependent crate. If it is
602606 // not specified by `--extern` on command line parameters, it may be
603607 // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to
@@ -612,6 +616,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
612616 Ok ( cnum)
613617 }
614618 ( LoadResult :: Loaded ( library) , host_library) => {
619+ info ! ( "register newly loaded library for `{}`" , name) ;
615620 self . register_crate ( host_library, root, library, dep_kind, name, private_dep)
616621 }
617622 _ => panic ! ( ) ,
@@ -695,7 +700,25 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
695700 stable_crate_id : StableCrateId ,
696701 ) -> Result < & ' static [ ProcMacro ] , CrateError > {
697702 let sym_name = self . sess . generate_proc_macro_decls_symbol ( stable_crate_id) ;
698- Ok ( unsafe { * load_symbol_from_dylib :: < * const & [ ProcMacro ] > ( path, & sym_name) ? } )
703+ debug ! ( "trying to dlsym proc_macros {} for symbol `{}`" , path. display( ) , sym_name) ;
704+
705+ unsafe {
706+ let result = load_symbol_from_dylib :: < * const & [ ProcMacro ] > ( path, & sym_name) ;
707+ match result {
708+ Ok ( result) => {
709+ debug ! ( "loaded dlsym proc_macros {} for symbol `{}`" , path. display( ) , sym_name) ;
710+ Ok ( * result)
711+ }
712+ Err ( err) => {
713+ debug ! (
714+ "failed to dlsym proc_macros {} for symbol `{}`" ,
715+ path. display( ) ,
716+ sym_name
717+ ) ;
718+ Err ( err. into ( ) )
719+ }
720+ }
721+ }
699722 }
700723
701724 fn inject_panic_runtime ( & mut self , krate : & ast:: Crate ) {
@@ -1142,6 +1165,30 @@ fn format_dlopen_err(e: &(dyn std::error::Error + 'static)) -> String {
11421165 e. sources ( ) . map ( |e| format ! ( ": {e}" ) ) . collect ( )
11431166}
11441167
1168+ fn attempt_load_dylib ( path : & Path ) -> Result < libloading:: Library , libloading:: Error > {
1169+ if let Some ( ext) = path. extension ( )
1170+ && cfg ! ( target_os = "aix" )
1171+ && ext. eq ( "a" )
1172+ {
1173+ // On AIX, we ship all libraries as .a big_af archive
1174+ // the expected format is lib<name>.a(libname.so) for the actual
1175+ // dynamic library
1176+ let library_name = path. file_stem ( ) . expect ( "expect a library name" ) ;
1177+ let mut archive_member = OsString :: from ( "a(" ) ;
1178+ archive_member. push ( library_name) ;
1179+ archive_member. push ( ".so)" ) ;
1180+ let new_path = path. with_extension ( archive_member) ;
1181+
1182+ // On AIX, we need RTLD_MEMBER to dlopen an archived shared
1183+ // flags = RTLD_LAZY | RTLD_LOCAL | RTLD_MEMBER
1184+ // these are not yet in libc https://github.com/rust-lang/libc/pull/4044
1185+ let flags = 0x4 | 0x80000 | 0x40000 ;
1186+ unsafe { libloading:: os:: unix:: Library :: open ( Some ( & new_path) , flags) } . map ( |lib| lib. into ( ) )
1187+ } else {
1188+ unsafe { libloading:: Library :: new ( & path) }
1189+ }
1190+ }
1191+
11451192// On Windows the compiler would sometimes intermittently fail to open the
11461193// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
11471194// system still holds a lock on the file, so we retry a few times before calling it
@@ -1152,7 +1199,8 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, S
11521199 let mut last_error = None ;
11531200
11541201 for attempt in 0 ..max_attempts {
1155- match unsafe { libloading:: Library :: new ( & path) } {
1202+ debug ! ( "Attempt to load proc-macro `{}`." , path. display( ) ) ;
1203+ match attempt_load_dylib ( path) {
11561204 Ok ( lib) => {
11571205 if attempt > 0 {
11581206 debug ! (
@@ -1166,6 +1214,7 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, S
11661214 Err ( err) => {
11671215 // Only try to recover from this specific error.
11681216 if !matches ! ( err, libloading:: Error :: LoadLibraryExW { .. } ) {
1217+ debug ! ( "Failed to load proc-macro `{}`. Not retrying" , path. display( ) ) ;
11691218 let err = format_dlopen_err ( & err) ;
11701219 // We include the path of the dylib in the error ourselves, so
11711220 // if it's in the error, we strip it.
0 commit comments