1
1
//! Handles dynamic library loading for proc macro
2
2
3
+ mod proc_macros;
3
4
mod version;
4
5
5
6
use proc_macro:: bridge;
@@ -10,57 +11,56 @@ use libloading::Library;
10
11
use object:: Object ;
11
12
use paths:: { Utf8Path , Utf8PathBuf } ;
12
13
13
- use crate :: { ProcMacroKind , ProcMacroSrvSpan , proc_macros:: ProcMacros , server_impl:: TopSubtree } ;
14
+ use crate :: {
15
+ PanicMessage , ProcMacroKind , ProcMacroSrvSpan , dylib:: proc_macros:: ProcMacros ,
16
+ server_impl:: TopSubtree ,
17
+ } ;
14
18
15
- /// Loads dynamic library in platform dependent manner.
16
- ///
17
- /// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
18
- /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
19
- /// and [here](https://github.com/rust-lang/rust/issues/60593).
20
- ///
21
- /// Usage of RTLD_DEEPBIND
22
- /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
23
- ///
24
- /// It seems that on Windows that behaviour is default, so we do nothing in that case.
25
- ///
26
- /// # Safety
27
- ///
28
- /// The caller is responsible for ensuring that the path is valid proc-macro library
29
- #[ cfg( windows) ]
30
- unsafe fn load_library ( file : & Utf8Path ) -> Result < Library , libloading:: Error > {
31
- // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library
32
- unsafe { Library :: new ( file) }
19
+ pub ( crate ) struct Expander {
20
+ inner : ProcMacroLibrary ,
21
+ modified_time : SystemTime ,
33
22
}
34
23
35
- /// Loads dynamic library in platform dependent manner.
36
- ///
37
- /// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
38
- /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
39
- /// and [here](https://github.com/rust-lang/rust/issues/60593).
40
- ///
41
- /// Usage of RTLD_DEEPBIND
42
- /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
43
- ///
44
- /// It seems that on Windows that behaviour is default, so we do nothing in that case.
45
- ///
46
- /// # Safety
47
- ///
48
- /// The caller is responsible for ensuring that the path is valid proc-macro library
49
- #[ cfg( unix) ]
50
- unsafe fn load_library ( file : & Utf8Path ) -> Result < Library , libloading:: Error > {
51
- // not defined by POSIX, different values on mips vs other targets
52
- #[ cfg( target_env = "gnu" ) ]
53
- use libc:: RTLD_DEEPBIND ;
54
- use libloading:: os:: unix:: Library as UnixLibrary ;
55
- // defined by POSIX
56
- use libloading:: os:: unix:: RTLD_NOW ;
24
+ impl Expander {
25
+ pub ( crate ) fn new (
26
+ temp_dir : & TempDir ,
27
+ lib : & Utf8Path ,
28
+ ) -> Result < Expander , LoadProcMacroDylibError > {
29
+ // Some libraries for dynamic loading require canonicalized path even when it is
30
+ // already absolute
31
+ let lib = lib. canonicalize_utf8 ( ) ?;
32
+ let modified_time = fs:: metadata ( & lib) . and_then ( |it| it. modified ( ) ) ?;
57
33
58
- // MUSL and bionic don't have it..
59
- #[ cfg( not( target_env = "gnu" ) ) ]
60
- const RTLD_DEEPBIND : std:: os:: raw:: c_int = 0x0 ;
34
+ let path = ensure_file_with_lock_free_access ( temp_dir, & lib) ?;
35
+ let library = ProcMacroLibrary :: open ( path. as_ref ( ) ) ?;
61
36
62
- // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library
63
- unsafe { UnixLibrary :: open ( Some ( file) , RTLD_NOW | RTLD_DEEPBIND ) . map ( |lib| lib. into ( ) ) }
37
+ Ok ( Expander { inner : library, modified_time } )
38
+ }
39
+
40
+ pub ( crate ) fn expand < S : ProcMacroSrvSpan > (
41
+ & self ,
42
+ macro_name : & str ,
43
+ macro_body : TopSubtree < S > ,
44
+ attributes : Option < TopSubtree < S > > ,
45
+ def_site : S ,
46
+ call_site : S ,
47
+ mixed_site : S ,
48
+ ) -> Result < TopSubtree < S > , PanicMessage >
49
+ where
50
+ <S :: Server as bridge:: server:: Types >:: TokenStream : Default ,
51
+ {
52
+ self . inner
53
+ . proc_macros
54
+ . expand ( macro_name, macro_body, attributes, def_site, call_site, mixed_site)
55
+ }
56
+
57
+ pub ( crate ) fn list_macros ( & self ) -> impl Iterator < Item = ( & str , ProcMacroKind ) > {
58
+ self . inner . proc_macros . list_macros ( )
59
+ }
60
+
61
+ pub ( crate ) fn modified_time ( & self ) -> SystemTime {
62
+ self . modified_time
63
+ }
64
64
}
65
65
66
66
#[ derive( Debug ) ]
@@ -134,57 +134,6 @@ impl ProcMacroLibrary {
134
134
}
135
135
}
136
136
137
- // Drop order matters as we can't remove the dylib before the library is unloaded
138
- pub ( crate ) struct Expander {
139
- inner : ProcMacroLibrary ,
140
- _remove_on_drop : RemoveFileOnDrop ,
141
- modified_time : SystemTime ,
142
- }
143
-
144
- impl Expander {
145
- pub ( crate ) fn new (
146
- temp_dir : & TempDir ,
147
- lib : & Utf8Path ,
148
- ) -> Result < Expander , LoadProcMacroDylibError > {
149
- // Some libraries for dynamic loading require canonicalized path even when it is
150
- // already absolute
151
- let lib = lib. canonicalize_utf8 ( ) ?;
152
- let modified_time = fs:: metadata ( & lib) . and_then ( |it| it. modified ( ) ) ?;
153
-
154
- let path = ensure_file_with_lock_free_access ( temp_dir, & lib) ?;
155
- let library = ProcMacroLibrary :: open ( path. as_ref ( ) ) ?;
156
-
157
- Ok ( Expander { inner : library, _remove_on_drop : RemoveFileOnDrop ( path) , modified_time } )
158
- }
159
-
160
- pub ( crate ) fn expand < S : ProcMacroSrvSpan > (
161
- & self ,
162
- macro_name : & str ,
163
- macro_body : TopSubtree < S > ,
164
- attributes : Option < TopSubtree < S > > ,
165
- def_site : S ,
166
- call_site : S ,
167
- mixed_site : S ,
168
- ) -> Result < TopSubtree < S > , String >
169
- where
170
- <S :: Server as bridge:: server:: Types >:: TokenStream : Default ,
171
- {
172
- let result = self
173
- . inner
174
- . proc_macros
175
- . expand ( macro_name, macro_body, attributes, def_site, call_site, mixed_site) ;
176
- result. map_err ( |e| e. into_string ( ) . unwrap_or_default ( ) )
177
- }
178
-
179
- pub ( crate ) fn list_macros ( & self ) -> Vec < ( String , ProcMacroKind ) > {
180
- self . inner . proc_macros . list_macros ( )
181
- }
182
-
183
- pub ( crate ) fn modified_time ( & self ) -> SystemTime {
184
- self . modified_time
185
- }
186
- }
187
-
188
137
fn invalid_data_err ( e : impl Into < Box < dyn std:: error:: Error + Send + Sync > > ) -> io:: Error {
189
138
io:: Error :: new ( io:: ErrorKind :: InvalidData , e)
190
139
}
@@ -214,15 +163,6 @@ fn find_registrar_symbol(obj: &object::File<'_>) -> object::Result<Option<String
214
163
} ) )
215
164
}
216
165
217
- struct RemoveFileOnDrop ( Utf8PathBuf ) ;
218
- impl Drop for RemoveFileOnDrop {
219
- fn drop ( & mut self ) {
220
- #[ cfg( windows) ]
221
- std:: fs:: remove_file ( & self . 0 ) . unwrap ( ) ;
222
- _ = self . 0 ;
223
- }
224
- }
225
-
226
166
/// Copy the dylib to temp directory to prevent locking in Windows
227
167
#[ cfg( windows) ]
228
168
fn ensure_file_with_lock_free_access (
@@ -259,3 +199,54 @@ fn ensure_file_with_lock_free_access(
259
199
) -> io:: Result < Utf8PathBuf > {
260
200
Ok ( path. to_owned ( ) )
261
201
}
202
+
203
+ /// Loads dynamic library in platform dependent manner.
204
+ ///
205
+ /// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
206
+ /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
207
+ /// and [here](https://github.com/rust-lang/rust/issues/60593).
208
+ ///
209
+ /// Usage of RTLD_DEEPBIND
210
+ /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
211
+ ///
212
+ /// It seems that on Windows that behaviour is default, so we do nothing in that case.
213
+ ///
214
+ /// # Safety
215
+ ///
216
+ /// The caller is responsible for ensuring that the path is valid proc-macro library
217
+ #[ cfg( windows) ]
218
+ unsafe fn load_library ( file : & Utf8Path ) -> Result < Library , libloading:: Error > {
219
+ // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library
220
+ unsafe { Library :: new ( file) }
221
+ }
222
+
223
+ /// Loads dynamic library in platform dependent manner.
224
+ ///
225
+ /// For unix, you have to use RTLD_DEEPBIND flag to escape problems described
226
+ /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample)
227
+ /// and [here](https://github.com/rust-lang/rust/issues/60593).
228
+ ///
229
+ /// Usage of RTLD_DEEPBIND
230
+ /// [here](https://github.com/fedochet/rust-proc-macro-panic-inside-panic-expample/issues/1)
231
+ ///
232
+ /// It seems that on Windows that behaviour is default, so we do nothing in that case.
233
+ ///
234
+ /// # Safety
235
+ ///
236
+ /// The caller is responsible for ensuring that the path is valid proc-macro library
237
+ #[ cfg( unix) ]
238
+ unsafe fn load_library ( file : & Utf8Path ) -> Result < Library , libloading:: Error > {
239
+ // not defined by POSIX, different values on mips vs other targets
240
+ #[ cfg( target_env = "gnu" ) ]
241
+ use libc:: RTLD_DEEPBIND ;
242
+ use libloading:: os:: unix:: Library as UnixLibrary ;
243
+ // defined by POSIX
244
+ use libloading:: os:: unix:: RTLD_NOW ;
245
+
246
+ // MUSL and bionic don't have it..
247
+ #[ cfg( not( target_env = "gnu" ) ) ]
248
+ const RTLD_DEEPBIND : std:: os:: raw:: c_int = 0x0 ;
249
+
250
+ // SAFETY: The caller is responsible for ensuring that the path is valid proc-macro library
251
+ unsafe { UnixLibrary :: open ( Some ( file) , RTLD_NOW | RTLD_DEEPBIND ) . map ( |lib| lib. into ( ) ) }
252
+ }
0 commit comments