Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use arm64 MSVC on arm64 Windows #285

Merged
merged 12 commits into from
Aug 27, 2024
49 changes: 37 additions & 12 deletions distutils/_msvccompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
LibError,
LinkError,
)
from .util import get_platform
from .util import get_host_platform, get_platform


def _find_vc2015():
Expand Down Expand Up @@ -178,17 +178,43 @@ def _find_exe(exe, paths=None):
return exe


# A map keyed by get_platform() return values to values accepted by
jaraco marked this conversation as resolved.
Show resolved Hide resolved
# 'vcvarsall.bat'. Always cross-compile from x86 to work with the
# lighter-weight MSVC installs that do not include native 64-bit tools.
PLAT_TO_VCVARS = {
_vcvars_names = {
'win32': 'x86',
'win-amd64': 'x86_amd64',
'win-arm32': 'x86_arm',
'win-arm64': 'x86_arm64',
'win-amd64': 'amd64',
'win-arm32': 'arm',
'win-arm64': 'arm64',
}


def _get_vcvars_spec(host_platform, platform):
"""
Given a host platform and platform, determine the spec for vcvarsall.

Uses the native MSVC host if the host platform would need expensive
emulation for x86.

>>> _get_vcvars_spec('win-arm64', 'win32')
'arm64_x86'
>>> _get_vcvars_spec('win-arm64', 'win-amd64')
'arm64_amd64'

Always cross-compile from x86 to work with the lighter-weight MSVC
jaraco marked this conversation as resolved.
Show resolved Hide resolved
installs that do not include native 64-bit tools.

>>> _get_vcvars_spec('win32', 'win32')
'x86'
>>> _get_vcvars_spec('win-arm32', 'win-arm32')
'x86_arm'
>>> _get_vcvars_spec('win-amd64', 'win-arm64')
'x86_arm64'
"""
if host_platform != 'win-arm64':
host_platform = 'win32'
vc_hp = _vcvars_names[host_platform]
vc_plat = _vcvars_names[platform]
return vc_hp if vc_hp == vc_plat else f'{vc_hp}_{vc_plat}'


class MSVCCompiler(CCompiler):
"""Concrete class that implements an interface to Microsoft Visual C++,
as defined by the CCompiler abstract class."""
Expand Down Expand Up @@ -242,13 +268,12 @@ def initialize(self, plat_name=None):
if plat_name is None:
plat_name = get_platform()
# sanity check for platforms to prevent obscure errors later.
if plat_name not in PLAT_TO_VCVARS:
if plat_name not in _vcvars_names:
raise DistutilsPlatformError(
f"--plat-name must be one of {tuple(PLAT_TO_VCVARS)}"
f"--plat-name must be one of {tuple(_vcvars_names)}"
)

# Get the vcvarsall.bat spec for the requested platform.
plat_spec = PLAT_TO_VCVARS[plat_name]
plat_spec = _get_vcvars_spec(get_host_platform(), get_platform())
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems the bug is in line 276 where it's ignoring the plat_name parameter and instead calling get_platform() again. 👀

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you're right, the following is enough of a change:

Suggested change
plat_spec = _get_vcvars_spec(get_host_platform(), get_platform())
plat_spec = _get_vcvars_spec(get_host_platform(), plat_name)


vc_env = _get_vc_env(plat_spec)
if not vc_env:
Expand Down