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 ;
@@ -540,6 +541,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
540541 Some ( cnum)
541542 }
542543 Err ( err) => {
544+ debug ! ( "failed to resolve crate {} {:?}" , name, dep_kind) ;
543545 let missing_core =
544546 self . maybe_resolve_crate ( sym:: core, CrateDepKind :: Explicit , None ) . is_err ( ) ;
545547 err. report ( self . sess , span, missing_core) ;
@@ -588,6 +590,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
588590 match self . load ( & mut locator) ? {
589591 Some ( res) => ( res, None ) ,
590592 None => {
593+ info ! ( "falling back to loading proc_macro" ) ;
591594 dep_kind = CrateDepKind :: MacrosOnly ;
592595 match self . load_proc_macro ( & mut locator, path_kind, host_hash) ? {
593596 Some ( res) => res,
@@ -599,6 +602,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
599602
600603 match result {
601604 ( LoadResult :: Previous ( cnum) , None ) => {
605+ info ! ( "library for `{}` was loaded previously" , name) ;
602606 // When `private_dep` is none, it indicates the directly dependent crate. If it is
603607 // not specified by `--extern` on command line parameters, it may be
604608 // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to
@@ -613,6 +617,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
613617 Ok ( cnum)
614618 }
615619 ( LoadResult :: Loaded ( library) , host_library) => {
620+ info ! ( "register newly loaded library for `{}`" , name) ;
616621 self . register_crate ( host_library, root, library, dep_kind, name, private_dep)
617622 }
618623 _ => panic ! ( ) ,
@@ -696,7 +701,25 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
696701 stable_crate_id : StableCrateId ,
697702 ) -> Result < & ' static [ ProcMacro ] , CrateError > {
698703 let sym_name = self . sess . generate_proc_macro_decls_symbol ( stable_crate_id) ;
699- Ok ( unsafe { * load_symbol_from_dylib :: < * const & [ ProcMacro ] > ( path, & sym_name) ? } )
704+ debug ! ( "trying to dlsym proc_macros {} for symbol `{}`" , path. display( ) , sym_name) ;
705+
706+ unsafe {
707+ let result = load_symbol_from_dylib :: < * const & [ ProcMacro ] > ( path, & sym_name) ;
708+ match result {
709+ Ok ( result) => {
710+ debug ! ( "loaded dlsym proc_macros {} for symbol `{}`" , path. display( ) , sym_name) ;
711+ Ok ( * result)
712+ }
713+ Err ( err) => {
714+ debug ! (
715+ "failed to dlsym proc_macros {} for symbol `{}`" ,
716+ path. display( ) ,
717+ sym_name
718+ ) ;
719+ Err ( err. into ( ) )
720+ }
721+ }
722+ }
700723 }
701724
702725 fn inject_panic_runtime ( & mut self , krate : & ast:: Crate ) {
@@ -1141,6 +1164,30 @@ fn format_dlopen_err(e: &(dyn std::error::Error + 'static)) -> String {
11411164 e. sources ( ) . map ( |e| format ! ( ": {e}" ) ) . collect ( )
11421165}
11431166
1167+ fn attempt_load_dylib ( path : & Path ) -> Result < libloading:: Library , libloading:: Error > {
1168+ if let Some ( ext) = path. extension ( )
1169+ && cfg ! ( target_os = "aix" )
1170+ && ext. eq ( "a" )
1171+ {
1172+ // On AIX, we ship all libraries as .a big_af archive
1173+ // the expected format is lib<name>.a(libname.so) for the actual
1174+ // dynamic library
1175+ let library_name = path. file_stem ( ) . expect ( "expect a library name" ) ;
1176+ let mut archive_member = OsString :: from ( "a(" ) ;
1177+ archive_member. push ( library_name) ;
1178+ archive_member. push ( ".so)" ) ;
1179+ let new_path = path. with_extension ( archive_member) ;
1180+
1181+ // On AIX, we need RTLD_MEMBER to dlopen an archived shared
1182+ // flags = RTLD_LAZY | RTLD_LOCAL | RTLD_MEMBER
1183+ // these are not yet in libc https://github.com/rust-lang/libc/pull/4044
1184+ let flags = 0x4 | 0x80000 | 0x40000 ;
1185+ unsafe { libloading:: os:: unix:: Library :: open ( Some ( & new_path) , flags) } . map ( |lib| lib. into ( ) )
1186+ } else {
1187+ unsafe { libloading:: Library :: new ( & path) }
1188+ }
1189+ }
1190+
11441191// On Windows the compiler would sometimes intermittently fail to open the
11451192// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
11461193// system still holds a lock on the file, so we retry a few times before calling it
@@ -1151,7 +1198,8 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, S
11511198 let mut last_error = None ;
11521199
11531200 for attempt in 0 ..max_attempts {
1154- match unsafe { libloading:: Library :: new ( & path) } {
1201+ debug ! ( "Attempt to load proc-macro `{}`." , path. display( ) ) ;
1202+ match attempt_load_dylib ( path) {
11551203 Ok ( lib) => {
11561204 if attempt > 0 {
11571205 debug ! (
@@ -1165,6 +1213,7 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, S
11651213 Err ( err) => {
11661214 // Only try to recover from this specific error.
11671215 if !matches ! ( err, libloading:: Error :: LoadLibraryExW { .. } ) {
1216+ debug ! ( "Failed to load proc-macro `{}`. Not retrying" , path. display( ) ) ;
11681217 let err = format_dlopen_err ( & err) ;
11691218 // We include the path of the dylib in the error ourselves, so
11701219 // if it's in the error, we strip it.
0 commit comments