@@ -692,20 +692,8 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
692
692
path : & Path ,
693
693
stable_crate_id : StableCrateId ,
694
694
) -> Result < & ' static [ ProcMacro ] , CrateError > {
695
- // Make sure the path contains a / or the linker will search for it.
696
- let path = try_canonicalize ( path) . unwrap ( ) ;
697
- let lib = load_dylib ( & path, 5 ) . map_err ( |err| CrateError :: DlOpen ( err) ) ?;
698
-
699
695
let sym_name = self . sess . generate_proc_macro_decls_symbol ( stable_crate_id) ;
700
- let sym = unsafe { lib. get :: < * const & [ ProcMacro ] > ( sym_name. as_bytes ( ) ) }
701
- . map_err ( |err| CrateError :: DlSym ( err. to_string ( ) ) ) ?;
702
-
703
- // Intentionally leak the dynamic library. We can't ever unload it
704
- // since the library can make things that will live arbitrarily long.
705
- let sym = unsafe { sym. into_raw ( ) } ;
706
- std:: mem:: forget ( lib) ;
707
-
708
- Ok ( unsafe { * * sym } )
696
+ Ok ( unsafe { * load_symbol_from_dylib :: < * const & [ ProcMacro ] > ( path, & sym_name) ? } )
709
697
}
710
698
711
699
fn inject_panic_runtime ( & mut self , krate : & ast:: Crate ) {
@@ -1116,6 +1104,10 @@ fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> {
1116
1104
f. spans
1117
1105
}
1118
1106
1107
+ fn format_dlopen_err ( e : & ( dyn std:: error:: Error + ' static ) ) -> String {
1108
+ e. sources ( ) . map ( |e| format ! ( ": {e}" ) ) . collect ( )
1109
+ }
1110
+
1119
1111
// On Windows the compiler would sometimes intermittently fail to open the
1120
1112
// proc-macro DLL with `Error::LoadLibraryExW`. It is suspected that something in the
1121
1113
// system still holds a lock on the file, so we retry a few times before calling it
@@ -1154,9 +1146,43 @@ fn load_dylib(path: &Path, max_attempts: usize) -> Result<libloading::Library, S
1154
1146
1155
1147
let last_error = last_error. unwrap ( ) ;
1156
1148
let message = if let Some ( src) = last_error. source ( ) {
1157
- format ! ( "{last_error } ({src}) (retried {max_attempts} times)" )
1149
+ format ! ( "{} ({src}) (retried {max_attempts} times)" , format_dlopen_err ( & last_error ) )
1158
1150
} else {
1159
- format ! ( "{last_error } (retried {max_attempts} times)" )
1151
+ format ! ( "{} (retried {max_attempts} times)" , format_dlopen_err ( & last_error ) )
1160
1152
} ;
1161
1153
Err ( message)
1162
1154
}
1155
+
1156
+ pub enum DylibError {
1157
+ DlOpen ( String , String ) ,
1158
+ DlSym ( String , String ) ,
1159
+ }
1160
+
1161
+ impl From < DylibError > for CrateError {
1162
+ fn from ( err : DylibError ) -> CrateError {
1163
+ match err {
1164
+ DylibError :: DlOpen ( path, err) => CrateError :: DlOpen ( path, err) ,
1165
+ DylibError :: DlSym ( path, err) => CrateError :: DlSym ( path, err) ,
1166
+ }
1167
+ }
1168
+ }
1169
+
1170
+ pub unsafe fn load_symbol_from_dylib < T : Copy > (
1171
+ path : & Path ,
1172
+ sym_name : & str ,
1173
+ ) -> Result < T , DylibError > {
1174
+ // Make sure the path contains a / or the linker will search for it.
1175
+ let path = try_canonicalize ( path) . unwrap ( ) ;
1176
+ let lib =
1177
+ load_dylib ( & path, 5 ) . map_err ( |err| DylibError :: DlOpen ( path. display ( ) . to_string ( ) , err) ) ?;
1178
+
1179
+ let sym = unsafe { lib. get :: < T > ( sym_name. as_bytes ( ) ) }
1180
+ . map_err ( |err| DylibError :: DlSym ( path. display ( ) . to_string ( ) , format_dlopen_err ( & err) ) ) ?;
1181
+
1182
+ // Intentionally leak the dynamic library. We can't ever unload it
1183
+ // since the library can make things that will live arbitrarily long.
1184
+ let sym = unsafe { sym. into_raw ( ) } ;
1185
+ std:: mem:: forget ( lib) ;
1186
+
1187
+ Ok ( * sym)
1188
+ }
0 commit comments