Skip to content

Commit 20ed5d9

Browse files
authored
Merge pull request #3010 from arlosi/aarch64
Fix detection of aarch64 host on Windows
2 parents 3277323 + 4871a38 commit 20ed5d9

File tree

1 file changed

+72
-18
lines changed

1 file changed

+72
-18
lines changed

src/dist/dist.rs

Lines changed: 72 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -229,27 +229,80 @@ impl TargetTriple {
229229
#[cfg(windows)]
230230
fn inner() -> Option<TargetTriple> {
231231
use std::mem;
232-
use winapi::um::sysinfoapi::GetNativeSystemInfo;
233232

234-
// First detect architecture
235-
const PROCESSOR_ARCHITECTURE_AMD64: u16 = 9;
236-
const PROCESSOR_ARCHITECTURE_INTEL: u16 = 0;
237-
const PROCESSOR_ARCHITECTURE_ARM64: u16 = 12;
233+
/// Get the host architecture using `IsWow64Process2`. This function
234+
/// produces the most accurate results (supports detecting aarch64), but
235+
/// it is only available on Windows 10 1511+, so we use `GetProcAddress`
236+
/// to maintain backward compatibility with older Windows versions.
237+
fn arch_primary() -> Option<&'static str> {
238+
use winapi::shared::minwindef::BOOL;
239+
use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress};
240+
use winapi::um::processthreadsapi::GetCurrentProcess;
241+
use winapi::um::winnt::HANDLE;
242+
243+
const IMAGE_FILE_MACHINE_ARM64: u16 = 0xAA64;
244+
const IMAGE_FILE_MACHINE_AMD64: u16 = 0x8664;
245+
const IMAGE_FILE_MACHINE_I386: u16 = 0x014c;
246+
247+
#[allow(non_snake_case)]
248+
let IsWow64Process2: unsafe extern "system" fn(
249+
HANDLE,
250+
*mut u16,
251+
*mut u16,
252+
)
253+
-> BOOL = unsafe {
254+
let module = GetModuleHandleA(b"kernel32.dll\0" as *const u8 as *const i8);
255+
if module.is_null() {
256+
return None;
257+
}
258+
let process =
259+
GetProcAddress(module, b"IsWow64Process2\0" as *const u8 as *const i8);
260+
if process.is_null() {
261+
return None;
262+
}
263+
mem::transmute(process)
264+
};
238265

239-
let mut sys_info;
240-
unsafe {
241-
sys_info = mem::zeroed();
242-
GetNativeSystemInfo(&mut sys_info);
266+
let mut _machine = 0;
267+
let mut native_machine = 0;
268+
unsafe {
269+
// cannot fail; handle does not need to be closed.
270+
let process = GetCurrentProcess();
271+
if IsWow64Process2(process, &mut _machine, &mut native_machine) == 0 {
272+
return None;
273+
}
274+
};
275+
match native_machine {
276+
IMAGE_FILE_MACHINE_AMD64 => Some("x86_64"),
277+
IMAGE_FILE_MACHINE_I386 => Some("i686"),
278+
IMAGE_FILE_MACHINE_ARM64 => Some("aarch64"),
279+
_ => None,
280+
}
243281
}
244282

245-
let arch = match unsafe { sys_info.u.s() }.wProcessorArchitecture {
246-
PROCESSOR_ARCHITECTURE_AMD64 => "x86_64",
247-
PROCESSOR_ARCHITECTURE_INTEL => "i686",
248-
PROCESSOR_ARCHITECTURE_ARM64 => "aarch64",
249-
_ => return None,
250-
};
283+
/// Get the host architecture using `GetNativeSystemInfo`.
284+
/// Does not support detecting aarch64.
285+
fn arch_fallback() -> Option<&'static str> {
286+
use winapi::um::sysinfoapi::GetNativeSystemInfo;
287+
288+
const PROCESSOR_ARCHITECTURE_AMD64: u16 = 9;
289+
const PROCESSOR_ARCHITECTURE_INTEL: u16 = 0;
290+
291+
let mut sys_info;
292+
unsafe {
293+
sys_info = mem::zeroed();
294+
GetNativeSystemInfo(&mut sys_info);
295+
}
296+
297+
match unsafe { sys_info.u.s() }.wProcessorArchitecture {
298+
PROCESSOR_ARCHITECTURE_AMD64 => Some("x86_64"),
299+
PROCESSOR_ARCHITECTURE_INTEL => Some("i686"),
300+
_ => None,
301+
}
302+
}
251303

252304
// Default to msvc
305+
let arch = arch_primary().or_else(arch_fallback)?;
253306
let msvc_triple = format!("{}-pc-windows-msvc", arch);
254307
Some(TargetTriple(msvc_triple))
255308
}
@@ -328,12 +381,13 @@ impl TargetTriple {
328381
let ret = if partial_self.os != partial_other.os {
329382
false
330383
} else if partial_self.os.as_deref() == Some("pc-windows") {
331-
// Windows is a special case here, we know we can run 32bit on 64bit
332-
// and we know we can run gnu and msvc on the same system
333-
// We don't immediately assume we can cross between x86 and aarch64 though
384+
// Windows is a special case here: we can run gnu and msvc on the same system,
385+
// x86_64 can run i686, and aarch64 can run i686 through emulation
334386
(partial_self.arch == partial_other.arch)
335387
|| (partial_self.arch.as_deref() == Some("x86_64")
336388
&& partial_other.arch.as_deref() == Some("i686"))
389+
|| (partial_self.arch.as_deref() == Some("aarch64")
390+
&& partial_other.arch.as_deref() == Some("i686"))
337391
} else {
338392
// For other OSes, for now, we assume other toolchains won't run
339393
false

0 commit comments

Comments
 (0)