Fix native compilation on ARM64 Windows

Move `detect_native_windows_arch()` to `mesonlib/universal.py` and
rename it to `windows_detect_native_arch()`
Use `IsWow64Process2()` to detect native architecture if available
Use native `vcvarsarm64.bat` to initialize vsenv if available
pull/10958/head
GustavoLCR 2 years ago committed by Jussi Pakkanen
parent 3c0ac626d7
commit 32bc64e632
  1. 22
      mesonbuild/environment.py
  2. 37
      mesonbuild/utils/universal.py
  3. 9
      mesonbuild/utils/vsenv.py

@ -20,7 +20,7 @@ import collections
from . import coredata
from . import mesonlib
from .mesonlib import (
MesonException, EnvironmentException, MachineChoice, Popen_safe, PerMachine,
MesonException, MachineChoice, Popen_safe, PerMachine,
PerMachineDefaultable, PerThreeMachineDefaultable, split_args, quote_arg, OptionKey,
search_version, MesonBugException
)
@ -228,22 +228,6 @@ def detect_clangformat() -> T.List[str]:
return [path]
return []
def detect_native_windows_arch():
"""
The architecture of Windows itself: x86, amd64 or arm64
"""
# These env variables are always available. See:
# https://msdn.microsoft.com/en-us/library/aa384274(VS.85).aspx
# https://blogs.msdn.microsoft.com/david.wang/2006/03/27/howto-detect-process-bitness/
arch = os.environ.get('PROCESSOR_ARCHITEW6432', '').lower()
if not arch:
try:
# If this doesn't exist, something is messing with the environment
arch = os.environ['PROCESSOR_ARCHITECTURE'].lower()
except KeyError:
raise EnvironmentException('Unable to detect native OS architecture')
return arch
def detect_windows_arch(compilers: CompilersDict) -> str:
"""
Detecting the 'native' architecture of Windows is not a trivial task. We
@ -268,7 +252,7 @@ def detect_windows_arch(compilers: CompilersDict) -> str:
3. Otherwise, use the actual Windows architecture
"""
os_arch = detect_native_windows_arch()
os_arch = mesonlib.windows_detect_native_arch()
if os_arch == 'x86':
return os_arch
# If we're on 64-bit Windows, 32-bit apps can be compiled without
@ -375,7 +359,7 @@ def detect_cpu(compilers: CompilersDict) -> str:
# Same check as above for cpu_family
if any_compiler_has_define(compilers, '__i386__'):
trial = 'i686' # All 64 bit cpus have at least this level of x86 support.
elif trial.startswith('aarch64'):
elif trial.startswith('aarch64') or trial.startswith('arm64'):
# Same check as above for cpu_family
if any_compiler_has_define(compilers, '__arm__'):
trial = 'arm'

@ -17,6 +17,7 @@
from __future__ import annotations
from pathlib import Path
import argparse
import ctypes
import enum
import sys
import stat
@ -141,6 +142,7 @@ __all__ = [
'version_compare_condition_with_min',
'version_compare_many',
'search_version',
'windows_detect_native_arch',
'windows_proof_rm',
'windows_proof_rmtree',
]
@ -689,6 +691,41 @@ def darwin_get_object_archs(objpath: str) -> 'ImmutableListProtocol[str]':
stdo += ' arm'
return stdo.split()
def windows_detect_native_arch() -> str:
"""
The architecture of Windows itself: x86, amd64 or arm64
"""
if sys.platform != 'win32':
return ''
try:
process_arch = ctypes.c_ushort()
native_arch = ctypes.c_ushort()
kernel32 = ctypes.windll.kernel32
process = ctypes.c_void_p(kernel32.GetCurrentProcess())
# This is the only reliable way to detect an arm system if we are an x86/x64 process being emulated
if kernel32.IsWow64Process2(process, ctypes.byref(process_arch), ctypes.byref(native_arch)):
# https://docs.microsoft.com/en-us/windows/win32/sysinfo/image-file-machine-constants
if native_arch.value == 0x8664:
return 'amd64'
elif native_arch.value == 0x014C:
return 'x86'
elif native_arch.value == 0xAA64:
return 'arm64'
elif native_arch.value == 0x01C4:
return 'arm'
except (OSError, AttributeError):
pass
# These env variables are always available. See:
# https://msdn.microsoft.com/en-us/library/aa384274(VS.85).aspx
# https://blogs.msdn.microsoft.com/david.wang/2006/03/27/howto-detect-process-bitness/
arch = os.environ.get('PROCESSOR_ARCHITEW6432', '').lower()
if not arch:
try:
# If this doesn't exist, something is messing with the environment
arch = os.environ['PROCESSOR_ARCHITECTURE'].lower()
except KeyError:
raise EnvironmentException('Unable to detect native OS architecture')
return arch
def detect_vcs(source_dir: T.Union[str, Path]) -> T.Optional[T.Dict[str, str]]:
vcs_systems = [

@ -2,12 +2,11 @@ import os
import subprocess
import json
import pathlib
import platform
import shutil
import tempfile
from .. import mlog
from .universal import MesonException, is_windows
from .universal import MesonException, is_windows, windows_detect_native_arch
__all__ = [
@ -72,8 +71,10 @@ def _setup_vsenv(force: bool) -> bool:
# VS installer instelled but not VS itself maybe?
raise MesonException('Could not parse vswhere.exe output')
bat_root = pathlib.Path(bat_info[0]['installationPath'])
if platform.machine() == 'ARM64':
bat_path = bat_root / 'VC/Auxiliary/Build/vcvarsx86_arm64.bat'
if windows_detect_native_arch() == 'arm64':
bat_path = bat_root / 'VC/Auxiliary/Build/vcvarsarm64.bat'
if not bat_path.exists():
bat_path = bat_root / 'VC/Auxiliary/Build/vcvarsx86_arm64.bat'
else:
bat_path = bat_root / 'VC/Auxiliary/Build/vcvars64.bat'
# if VS is not found try VS Express

Loading…
Cancel
Save