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 3 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 coredata
from . import mesonlib from . import mesonlib
from .mesonlib import ( from .mesonlib import (
MesonException, EnvironmentException, MachineChoice, Popen_safe, PerMachine, MesonException, MachineChoice, Popen_safe, PerMachine,
PerMachineDefaultable, PerThreeMachineDefaultable, split_args, quote_arg, OptionKey, PerMachineDefaultable, PerThreeMachineDefaultable, split_args, quote_arg, OptionKey,
search_version, MesonBugException search_version, MesonBugException
) )
@ -228,22 +228,6 @@ def detect_clangformat() -> T.List[str]:
return [path] return [path]
return [] 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: def detect_windows_arch(compilers: CompilersDict) -> str:
""" """
Detecting the 'native' architecture of Windows is not a trivial task. We 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 3. Otherwise, use the actual Windows architecture
""" """
os_arch = detect_native_windows_arch() os_arch = mesonlib.windows_detect_native_arch()
if os_arch == 'x86': if os_arch == 'x86':
return os_arch return os_arch
# If we're on 64-bit Windows, 32-bit apps can be compiled without # 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 # Same check as above for cpu_family
if any_compiler_has_define(compilers, '__i386__'): if any_compiler_has_define(compilers, '__i386__'):
trial = 'i686' # All 64 bit cpus have at least this level of x86 support. 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 # Same check as above for cpu_family
if any_compiler_has_define(compilers, '__arm__'): if any_compiler_has_define(compilers, '__arm__'):
trial = 'arm' trial = 'arm'

@ -17,6 +17,7 @@
from __future__ import annotations from __future__ import annotations
from pathlib import Path from pathlib import Path
import argparse import argparse
import ctypes
import enum import enum
import sys import sys
import stat import stat
@ -141,6 +142,7 @@ __all__ = [
'version_compare_condition_with_min', 'version_compare_condition_with_min',
'version_compare_many', 'version_compare_many',
'search_version', 'search_version',
'windows_detect_native_arch',
'windows_proof_rm', 'windows_proof_rm',
'windows_proof_rmtree', 'windows_proof_rmtree',
] ]
@ -689,6 +691,41 @@ def darwin_get_object_archs(objpath: str) -> 'ImmutableListProtocol[str]':
stdo += ' arm' stdo += ' arm'
return stdo.split() 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]]: def detect_vcs(source_dir: T.Union[str, Path]) -> T.Optional[T.Dict[str, str]]:
vcs_systems = [ vcs_systems = [

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

Loading…
Cancel
Save