1
1
#![ allow( dead_code) ]
2
2
3
+ use core:: fmt;
3
4
use std:: collections:: HashMap ;
4
5
use std:: env;
5
6
use std:: fs;
@@ -26,9 +27,38 @@ struct RunCommandMock {
26
27
responses : HashMap < Vec < String > , String > ,
27
28
}
28
29
30
+
31
+ #[ derive( Copy , Clone , Debug ) ]
32
+ enum Arch {
33
+ ARM64 ,
34
+ X86 ,
35
+ X86_64 ,
36
+ }
37
+
38
+ impl Arch {
39
+ fn pe_machine_type ( self ) -> u16 {
40
+ match self {
41
+ Arch :: ARM64 => 0xAA64 ,
42
+ Arch :: X86 => 0x014C ,
43
+ Arch :: X86_64 => 0x8664 ,
44
+ }
45
+ }
46
+ }
47
+
48
+ impl fmt:: Display for Arch {
49
+ fn fmt ( & self , f : & mut fmt:: Formatter ) -> fmt:: Result {
50
+ match self {
51
+ Arch :: ARM64 => write ! ( f, "aarch64" ) ,
52
+ Arch :: X86 => write ! ( f, "x86" ) ,
53
+ Arch :: X86_64 => write ! ( f, "x86_64" ) ,
54
+ }
55
+ }
56
+ }
57
+
29
58
#[ derive( Debug ) ]
30
59
struct Env {
31
60
os : String ,
61
+ arch : Arch ,
32
62
pointer_width : String ,
33
63
env : Option < String > ,
34
64
vars : HashMap < String , ( Option < String > , Option < String > ) > ,
@@ -39,9 +69,10 @@ struct Env {
39
69
}
40
70
41
71
impl Env {
42
- fn new ( os : & str , pointer_width : & str ) -> Self {
72
+ fn new ( os : & str , arch : Arch , pointer_width : & str ) -> Self {
43
73
Env {
44
74
os : os. into ( ) ,
75
+ arch,
45
76
pointer_width : pointer_width. into ( ) ,
46
77
env : None ,
47
78
vars : HashMap :: new ( ) ,
@@ -84,11 +115,12 @@ impl Env {
84
115
self
85
116
}
86
117
87
- fn dll ( self , path : & str , pointer_width : & str ) -> Self {
118
+ fn dll ( self , path : & str , arch : Arch , pointer_width : & str ) -> Self {
88
119
// PE header.
89
120
let mut contents = [ 0 ; 64 ] ;
90
121
contents[ 0x3C ..0x3C + 4 ] . copy_from_slice ( & i32:: to_le_bytes ( 10 ) ) ;
91
122
contents[ 10 ..14 ] . copy_from_slice ( & [ b'P' , b'E' , 0 , 0 ] ) ;
123
+ contents[ 14 ..16 ] . copy_from_slice ( & u16:: to_le_bytes ( arch. pe_machine_type ( ) ) ) ;
92
124
let magic = if pointer_width == "64" { 523 } else { 267 } ;
93
125
contents[ 34 ..36 ] . copy_from_slice ( & u16:: to_le_bytes ( magic) ) ;
94
126
@@ -117,6 +149,7 @@ impl Env {
117
149
fn enable ( self ) -> Self {
118
150
env:: set_var ( "_CLANG_SYS_TEST" , "yep" ) ;
119
151
env:: set_var ( "_CLANG_SYS_TEST_OS" , & self . os ) ;
152
+ env:: set_var ( "_CLANG_SYS_TEST_ARCH" , & format ! ( "{}" , self . arch) ) ;
120
153
env:: set_var ( "_CLANG_SYS_TEST_POINTER_WIDTH" , & self . pointer_width ) ;
121
154
if let Some ( env) = & self . env {
122
155
env:: set_var ( "_CLANG_SYS_TEST_ENV" , env) ;
@@ -155,6 +188,7 @@ impl Drop for Env {
155
188
fn drop ( & mut self ) {
156
189
env:: remove_var ( "_CLANG_SYS_TEST" ) ;
157
190
env:: remove_var ( "_CLANG_SYS_TEST_OS" ) ;
191
+ env:: remove_var ( "_CLANG_SYS_TEST_ARCH" ) ;
158
192
env:: remove_var ( "_CLANG_SYS_TEST_POINTER_WIDTH" ) ;
159
193
env:: remove_var ( "_CLANG_SYS_TEST_ENV" ) ;
160
194
@@ -185,17 +219,31 @@ fn test_all() {
185
219
test_windows_bin_sibling ( ) ;
186
220
test_windows_mingw_gnu ( ) ;
187
221
test_windows_mingw_msvc ( ) ;
222
+ test_windows_arm64_on_x86_64 ( ) ;
223
+ test_windows_x86_64_on_arm64 ( ) ;
188
224
}
189
225
}
190
226
227
+ macro_rules! assert_error {
228
+ ( $result: expr, $contents: expr $( , ) ?) => {
229
+ if let Err ( error) = $result {
230
+ if !error. contains( $contents) {
231
+ panic!( "expected error to contain {:?}, received: {error:?}" , $contents) ;
232
+ }
233
+ } else {
234
+ panic!( "expected error, received: {:?}" , $result) ;
235
+ }
236
+ } ;
237
+ }
238
+
191
239
//================================================
192
240
// Dynamic
193
241
//================================================
194
242
195
243
// Linux -----------------------------------------
196
244
197
245
fn test_linux_directory_preference ( ) {
198
- let _env = Env :: new ( "linux" , "64" )
246
+ let _env = Env :: new ( "linux" , Arch :: X86_64 , "64" )
199
247
. so ( "usr/lib/libclang.so.1" , "64" )
200
248
. so ( "usr/local/lib/libclang.so.1" , "64" )
201
249
. enable ( ) ;
@@ -207,7 +255,7 @@ fn test_linux_directory_preference() {
207
255
}
208
256
209
257
fn test_linux_version_preference ( ) {
210
- let _env = Env :: new ( "linux" , "64" )
258
+ let _env = Env :: new ( "linux" , Arch :: X86_64 , "64" )
211
259
. so ( "usr/lib/libclang-3.so" , "64" )
212
260
. so ( "usr/lib/libclang-3.5.so" , "64" )
213
261
. so ( "usr/lib/libclang-3.5.0.so" , "64" )
@@ -220,7 +268,7 @@ fn test_linux_version_preference() {
220
268
}
221
269
222
270
fn test_linux_directory_and_version_preference ( ) {
223
- let _env = Env :: new ( "linux" , "64" )
271
+ let _env = Env :: new ( "linux" , Arch :: X86_64 , "64" )
224
272
. so ( "usr/local/llvm/lib/libclang-3.so" , "64" )
225
273
. so ( "usr/local/lib/libclang-3.5.so" , "64" )
226
274
. so ( "usr/lib/libclang-3.5.0.so" , "64" )
@@ -236,9 +284,9 @@ fn test_linux_directory_and_version_preference() {
236
284
237
285
#[ cfg( target_os = "windows" ) ]
238
286
fn test_windows_bin_sibling ( ) {
239
- let _env = Env :: new ( "windows" , "64" )
287
+ let _env = Env :: new ( "windows" , Arch :: X86_64 , "64" )
240
288
. dir ( "Program Files\\ LLVM\\ lib" )
241
- . dll ( "Program Files\\ LLVM\\ bin\\ libclang.dll" , "64" )
289
+ . dll ( "Program Files\\ LLVM\\ bin\\ libclang.dll" , Arch :: X86_64 , "64" )
242
290
. enable ( ) ;
243
291
244
292
assert_eq ! (
@@ -249,12 +297,12 @@ fn test_windows_bin_sibling() {
249
297
250
298
#[ cfg( target_os = "windows" ) ]
251
299
fn test_windows_mingw_gnu ( ) {
252
- let _env = Env :: new ( "windows" , "64" )
300
+ let _env = Env :: new ( "windows" , Arch :: X86_64 , "64" )
253
301
. env ( "gnu" )
254
302
. dir ( "MSYS\\ MinGW\\ lib" )
255
- . dll ( "MSYS\\ MinGW\\ bin\\ clang.dll" , "64" )
303
+ . dll ( "MSYS\\ MinGW\\ bin\\ clang.dll" , Arch :: X86_64 , "64" )
256
304
. dir ( "Program Files\\ LLVM\\ lib" )
257
- . dll ( "Program Files\\ LLVM\\ bin\\ libclang.dll" , "64" )
305
+ . dll ( "Program Files\\ LLVM\\ bin\\ libclang.dll" , Arch :: X86_64 , "64" )
258
306
. enable ( ) ;
259
307
260
308
assert_eq ! (
@@ -265,16 +313,44 @@ fn test_windows_mingw_gnu() {
265
313
266
314
#[ cfg( target_os = "windows" ) ]
267
315
fn test_windows_mingw_msvc ( ) {
268
- let _env = Env :: new ( "windows" , "64" )
316
+ let _env = Env :: new ( "windows" , Arch :: X86_64 , "64" )
269
317
. env ( "msvc" )
270
318
. dir ( "MSYS\\ MinGW\\ lib" )
271
- . dll ( "MSYS\\ MinGW\\ bin\\ clang.dll" , "64" )
319
+ . dll ( "MSYS\\ MinGW\\ bin\\ clang.dll" , Arch :: X86_64 , "64" )
272
320
. dir ( "Program Files\\ LLVM\\ lib" )
273
- . dll ( "Program Files\\ LLVM\\ bin\\ libclang.dll" , "64" )
321
+ . dll ( "Program Files\\ LLVM\\ bin\\ libclang.dll" , Arch :: X86_64 , "64" )
274
322
. enable ( ) ;
275
323
276
324
assert_eq ! (
277
325
dynamic:: find( true ) ,
278
326
Ok ( ( "Program Files\\ LLVM\\ bin" . into( ) , "libclang.dll" . into( ) ) ) ,
279
327
) ;
280
328
}
329
+
330
+ #[ cfg( target_os = "windows" ) ]
331
+ fn test_windows_arm64_on_x86_64 ( ) {
332
+ let _env = Env :: new ( "windows" , Arch :: X86_64 , "64" )
333
+ . env ( "msvc" )
334
+ . dir ( "Program Files\\ LLVM\\ lib" )
335
+ . dll ( "Program Files\\ LLVM\\ bin\\ libclang.dll" , Arch :: ARM64 , "64" )
336
+ . enable ( ) ;
337
+
338
+ assert_error ! (
339
+ dynamic:: find( true ) ,
340
+ "invalid: [(Program Files\\ LLVM\\ bin\\ libclang.dll: invalid DLL (ARM64)" ,
341
+ ) ;
342
+ }
343
+
344
+ #[ cfg( target_os = "windows" ) ]
345
+ fn test_windows_x86_64_on_arm64 ( ) {
346
+ let _env = Env :: new ( "windows" , Arch :: ARM64 , "64" )
347
+ . env ( "msvc" )
348
+ . dir ( "Program Files\\ LLVM\\ lib" )
349
+ . dll ( "Program Files\\ LLVM\\ bin\\ libclang.dll" , Arch :: X86_64 , "64" )
350
+ . enable ( ) ;
351
+
352
+ assert_error ! (
353
+ dynamic:: find( true ) ,
354
+ "invalid: [(Program Files\\ LLVM\\ bin\\ libclang.dll: invalid DLL (x86-64)" ,
355
+ ) ;
356
+ }
0 commit comments