2
2
3
3
use crate :: { proc_macro:: bridge, rustc_server:: TokenStream } ;
4
4
use std:: fs:: File ;
5
- use std:: path:: Path ;
5
+ use std:: path:: { Path , PathBuf } ;
6
6
7
7
use goblin:: { mach:: Mach , Object } ;
8
8
use libloading:: Library ;
9
9
use memmap:: Mmap ;
10
10
use ra_proc_macro:: ProcMacroKind ;
11
-
12
11
use std:: io;
13
12
14
13
const NEW_REGISTRAR_SYMBOL : & str = "_rustc_proc_macro_decls_" ;
@@ -109,23 +108,21 @@ impl ProcMacroLibraryLibloading {
109
108
}
110
109
}
111
110
112
- type ProcMacroLibraryImpl = ProcMacroLibraryLibloading ;
113
-
114
111
pub struct Expander {
115
- libs : Vec < ProcMacroLibraryImpl > ,
112
+ inner : ProcMacroLibraryLibloading ,
116
113
}
117
114
118
115
impl Expander {
119
- pub fn new ( lib : & Path ) -> Result < Expander , String > {
116
+ pub fn new ( lib : & Path ) -> io :: Result < Expander > {
120
117
// Some libraries for dynamic loading require canonicalized path even when it is
121
118
// already absolute
122
- let lib = lib
123
- . canonicalize ( )
124
- . unwrap_or_else ( |err| panic ! ( "Cannot canonicalize {}: {:?}" , lib. display ( ) , err ) ) ;
119
+ let lib = lib. canonicalize ( ) ? ;
120
+
121
+ let lib = ensure_file_with_lock_free_access ( & lib) ? ;
125
122
126
- let library = ProcMacroLibraryImpl :: open ( & lib) . map_err ( |e| e . to_string ( ) ) ?;
123
+ let library = ProcMacroLibraryLibloading :: open ( & lib) ?;
127
124
128
- Ok ( Expander { libs : vec ! [ library] } )
125
+ Ok ( Expander { inner : library } )
129
126
}
130
127
131
128
pub fn expand (
@@ -141,48 +138,46 @@ impl Expander {
141
138
TokenStream :: with_subtree ( attr. clone ( ) )
142
139
} ) ;
143
140
144
- for lib in & self . libs {
145
- for proc_macro in & lib. exported_macros {
146
- match proc_macro {
147
- bridge:: client:: ProcMacro :: CustomDerive { trait_name, client, .. }
148
- if * trait_name == macro_name =>
149
- {
150
- let res = client. run (
151
- & crate :: proc_macro:: bridge:: server:: SameThread ,
152
- crate :: rustc_server:: Rustc :: default ( ) ,
153
- parsed_body,
154
- ) ;
155
- return res. map ( |it| it. subtree ) ;
156
- }
157
- bridge:: client:: ProcMacro :: Bang { name, client } if * name == macro_name => {
158
- let res = client. run (
159
- & crate :: proc_macro:: bridge:: server:: SameThread ,
160
- crate :: rustc_server:: Rustc :: default ( ) ,
161
- parsed_body,
162
- ) ;
163
- return res. map ( |it| it. subtree ) ;
164
- }
165
- bridge:: client:: ProcMacro :: Attr { name, client } if * name == macro_name => {
166
- let res = client. run (
167
- & crate :: proc_macro:: bridge:: server:: SameThread ,
168
- crate :: rustc_server:: Rustc :: default ( ) ,
169
- parsed_attributes,
170
- parsed_body,
171
- ) ;
172
- return res. map ( |it| it. subtree ) ;
173
- }
174
- _ => continue ,
141
+ for proc_macro in & self . inner . exported_macros {
142
+ match proc_macro {
143
+ bridge:: client:: ProcMacro :: CustomDerive { trait_name, client, .. }
144
+ if * trait_name == macro_name =>
145
+ {
146
+ let res = client. run (
147
+ & crate :: proc_macro:: bridge:: server:: SameThread ,
148
+ crate :: rustc_server:: Rustc :: default ( ) ,
149
+ parsed_body,
150
+ ) ;
151
+ return res. map ( |it| it. subtree ) ;
152
+ }
153
+ bridge:: client:: ProcMacro :: Bang { name, client } if * name == macro_name => {
154
+ let res = client. run (
155
+ & crate :: proc_macro:: bridge:: server:: SameThread ,
156
+ crate :: rustc_server:: Rustc :: default ( ) ,
157
+ parsed_body,
158
+ ) ;
159
+ return res. map ( |it| it. subtree ) ;
160
+ }
161
+ bridge:: client:: ProcMacro :: Attr { name, client } if * name == macro_name => {
162
+ let res = client. run (
163
+ & crate :: proc_macro:: bridge:: server:: SameThread ,
164
+ crate :: rustc_server:: Rustc :: default ( ) ,
165
+ parsed_attributes,
166
+ parsed_body,
167
+ ) ;
168
+ return res. map ( |it| it. subtree ) ;
175
169
}
170
+ _ => continue ,
176
171
}
177
172
}
178
173
179
174
Err ( bridge:: PanicMessage :: String ( "Nothing to expand" . to_string ( ) ) )
180
175
}
181
176
182
177
pub fn list_macros ( & self ) -> Vec < ( String , ProcMacroKind ) > {
183
- self . libs
178
+ self . inner
179
+ . exported_macros
184
180
. iter ( )
185
- . flat_map ( |it| & it. exported_macros )
186
181
. map ( |proc_macro| match proc_macro {
187
182
bridge:: client:: ProcMacro :: CustomDerive { trait_name, .. } => {
188
183
( trait_name. to_string ( ) , ProcMacroKind :: CustomDerive )
@@ -197,3 +192,33 @@ impl Expander {
197
192
. collect ( )
198
193
}
199
194
}
195
+
196
+ /// Copy the dylib to temp directory to prevent locking in Windows
197
+ #[ cfg( windows) ]
198
+ fn ensure_file_with_lock_free_access ( path : & Path ) -> io:: Result < PathBuf > {
199
+ use std:: { ffi:: OsString , time:: SystemTime } ;
200
+
201
+ let mut to = std:: env:: temp_dir ( ) ;
202
+
203
+ let file_name = path. file_name ( ) . ok_or_else ( || {
204
+ io:: Error :: new (
205
+ io:: ErrorKind :: InvalidInput ,
206
+ format ! ( "File path is invalid: {}" , path. display( ) ) ,
207
+ )
208
+ } ) ?;
209
+
210
+ // generate a time deps unique number
211
+ let t = SystemTime :: now ( ) . duration_since ( std:: time:: UNIX_EPOCH ) . expect ( "Time went backwards" ) ;
212
+
213
+ let mut unique_name = OsString :: from ( t. as_millis ( ) . to_string ( ) ) ;
214
+ unique_name. push ( file_name) ;
215
+
216
+ to. push ( unique_name) ;
217
+ std:: fs:: copy ( path, & to) . unwrap ( ) ;
218
+ Ok ( to)
219
+ }
220
+
221
+ #[ cfg( unix) ]
222
+ fn ensure_file_with_lock_free_access ( path : & Path ) -> io:: Result < PathBuf > {
223
+ Ok ( path. to_path_buf ( ) )
224
+ }
0 commit comments