add support for building wheels for windows on arm64 (#920)
* add support for building wheels for windows on arm64 * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fix main_platform_test.py * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Remove unrequired explicit nuget source * add python arm64 3.9.9 version * extend update_pythons.py to add win/arm64 support * update documentation for new win/arm64 platform * style: include ARM64 in literal * Fix python 3.9 identifier for win_arm64 * Fix table layout issues in README and add note about arm64 pip issue Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com>
This commit is contained in:
co-authored by
pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Henry Schreiner
parent
59b157f333
commit
594d89f6f7
@@ -22,16 +22,17 @@ Python wheels are great. Building them across **Mac, Linux, Windows**, on **mult
|
|||||||
What does it do?
|
What does it do?
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
| | macOS Intel | macOS Apple Silicon | Windows 64bit | Windows 32bit | manylinux<br/>musllinux x86_64 | manylinux<br/>musllinux i686 | manylinux<br/>musllinux aarch64 | manylinux<br/>musllinux ppc64le | manylinux<br/>musllinux s390x |
|
| | macOS Intel | macOS Apple Silicon | Windows 64bit | Windows 32bit | Windows Arm64 | manylinux<br/>musllinux x86_64 | manylinux<br/>musllinux i686 | manylinux<br/>musllinux aarch64 | manylinux<br/>musllinux ppc64le | manylinux<br/>musllinux s390x |
|
||||||
|---------------|----|-----|-----|-----|----|-----|----|-----|-----|
|
|---------------|----|-----|-----|-----|-----|----|-----|----|-----|-----|
|
||||||
| CPython 3.6 | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
| CPython 3.6 | ✅ | N/A | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
| CPython 3.7 | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
| CPython 3.7 | ✅ | N/A | ✅ | ✅ | N/A | ✅ |✅ | ✅ | ✅ | ✅ |
|
||||||
| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
| CPython 3.8 | ✅ | ✅ | ✅ | ✅ | N/A | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
| CPython 3.9 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
|
| CPython 3.10 | ✅ | ✅ | ✅ | ✅ | ✅² | ✅ | ✅ | ✅ | ✅ | ✅ |
|
||||||
| PyPy 3.7 v7.3 | ✅ | N/A | ✅ | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A |
|
| PyPy 3.7 v7.3 | ✅ | N/A | ✅ | N/A | N/A | ✅¹ | ✅¹ | ✅¹ | N/A | N/A |
|
||||||
|
|
||||||
<sup>¹ PyPy is only supported for manylinux wheels.</sup><br>
|
<sup>¹ PyPy is only supported for manylinux wheels.</sup><br>
|
||||||
|
<sup>² Windows arm64 support is experimental.</sup><br>
|
||||||
|
|
||||||
- Builds manylinux, musllinux, macOS 10.9+, and Windows wheels for CPython and PyPy
|
- Builds manylinux, musllinux, macOS 10.9+, and Windows wheels for CPython and PyPy
|
||||||
- Works on GitHub Actions, Azure Pipelines, Travis CI, AppVeyor, CircleCI, and GitLab CI
|
- Works on GitHub Actions, Azure Pipelines, Travis CI, AppVeyor, CircleCI, and GitLab CI
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ DIR: Final[Path] = Path(__file__).parent.parent.resolve()
|
|||||||
RESOURCES_DIR: Final[Path] = DIR / "cibuildwheel/resources"
|
RESOURCES_DIR: Final[Path] = DIR / "cibuildwheel/resources"
|
||||||
|
|
||||||
|
|
||||||
ArchStr = Literal["32", "64"]
|
ArchStr = Literal["32", "64", "ARM64"]
|
||||||
|
|
||||||
|
|
||||||
class ConfigWinCP(TypedDict):
|
class ConfigWinCP(TypedDict):
|
||||||
@@ -68,8 +68,8 @@ class WindowsVersions:
|
|||||||
if resource["@type"] == "PackageBaseAddress/3.0.0":
|
if resource["@type"] == "PackageBaseAddress/3.0.0":
|
||||||
endpoint = resource["@id"]
|
endpoint = resource["@id"]
|
||||||
|
|
||||||
ARCH_DICT = {"32": "win32", "64": "win_amd64"}
|
ARCH_DICT = {"32": "win32", "64": "win_amd64", "ARM64": "win_arm64"}
|
||||||
PACKAGE_DICT = {"32": "pythonx86", "64": "python"}
|
PACKAGE_DICT = {"32": "pythonx86", "64": "python", "ARM64": "pythonarm64"}
|
||||||
|
|
||||||
self.arch_str = arch_str
|
self.arch_str = arch_str
|
||||||
self.arch = ARCH_DICT[arch_str]
|
self.arch = ARCH_DICT[arch_str]
|
||||||
@@ -237,6 +237,7 @@ class AllVersions:
|
|||||||
def __init__(self) -> None:
|
def __init__(self) -> None:
|
||||||
self.windows_32 = WindowsVersions("32")
|
self.windows_32 = WindowsVersions("32")
|
||||||
self.windows_64 = WindowsVersions("64")
|
self.windows_64 = WindowsVersions("64")
|
||||||
|
self.windows_arm64 = WindowsVersions("ARM64")
|
||||||
self.windows_pypy_64 = PyPyVersions("64")
|
self.windows_pypy_64 = PyPyVersions("64")
|
||||||
|
|
||||||
self.macos_cpython = CPythonVersions()
|
self.macos_cpython = CPythonVersions()
|
||||||
@@ -264,6 +265,9 @@ class AllVersions:
|
|||||||
config_update = self.windows_64.update_version_windows(spec)
|
config_update = self.windows_64.update_version_windows(spec)
|
||||||
elif identifier.startswith("pp"):
|
elif identifier.startswith("pp"):
|
||||||
config_update = self.windows_pypy_64.update_version_windows(spec)
|
config_update = self.windows_pypy_64.update_version_windows(spec)
|
||||||
|
elif "win_arm64" in identifier:
|
||||||
|
if identifier.startswith("cp"):
|
||||||
|
config_update = self.windows_arm64.update_version_windows(spec)
|
||||||
|
|
||||||
assert config_update is not None, f"{identifier} not found!"
|
assert config_update is not None, f"{identifier} not found!"
|
||||||
config.update(**config_update)
|
config.update(**config_update)
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ class Architecture(Enum):
|
|||||||
# windows archs
|
# windows archs
|
||||||
x86 = "x86"
|
x86 = "x86"
|
||||||
AMD64 = "AMD64"
|
AMD64 = "AMD64"
|
||||||
|
ARM64 = "ARM64"
|
||||||
|
|
||||||
# Allow this to be sorted
|
# Allow this to be sorted
|
||||||
def __lt__(self, other: "Architecture") -> bool:
|
def __lt__(self, other: "Architecture") -> bool:
|
||||||
@@ -83,7 +84,7 @@ class Architecture(Enum):
|
|||||||
elif platform == "macos":
|
elif platform == "macos":
|
||||||
return {Architecture.x86_64, Architecture.arm64, Architecture.universal2}
|
return {Architecture.x86_64, Architecture.arm64, Architecture.universal2}
|
||||||
elif platform == "windows":
|
elif platform == "windows":
|
||||||
return {Architecture.x86, Architecture.AMD64}
|
return {Architecture.x86, Architecture.AMD64, Architecture.ARM64}
|
||||||
else:
|
else:
|
||||||
assert_never(platform)
|
assert_never(platform)
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ PLATFORM_IDENTIFIER_DESCIPTIONS = {
|
|||||||
"musllinux_s390x": "manylinux s390x",
|
"musllinux_s390x": "manylinux s390x",
|
||||||
"win32": "Windows 32bit",
|
"win32": "Windows 32bit",
|
||||||
"win_amd64": "Windows 64bit",
|
"win_amd64": "Windows 64bit",
|
||||||
|
"win_arm64": "Windows on ARM 64bit",
|
||||||
"macosx_x86_64": "macOS x86_64",
|
"macosx_x86_64": "macOS x86_64",
|
||||||
"macosx_universal2": "macOS Universal 2 - x86_64 and arm64",
|
"macosx_universal2": "macOS Universal 2 - x86_64 and arm64",
|
||||||
"macosx_arm64": "macOS arm64 - Apple Silicon",
|
"macosx_arm64": "macOS arm64 - Apple Silicon",
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ python_configurations = [
|
|||||||
{ identifier = "cp39-win_amd64", version = "3.9.8", arch = "64" },
|
{ identifier = "cp39-win_amd64", version = "3.9.8", arch = "64" },
|
||||||
{ identifier = "cp310-win32", version = "3.10.0", arch = "32" },
|
{ identifier = "cp310-win32", version = "3.10.0", arch = "32" },
|
||||||
{ identifier = "cp310-win_amd64", version = "3.10.0", arch = "64" },
|
{ identifier = "cp310-win_amd64", version = "3.10.0", arch = "64" },
|
||||||
|
{ identifier = "cp39-win_arm64", version = "3.9.9", arch = "ARM64" },
|
||||||
|
{ identifier = "cp310-win_arm64", version = "3.10.0", arch = "ARM64" },
|
||||||
{ identifier = "pp37-win_amd64", version = "3.7", arch = "64", url = "https://downloads.python.org/pypy/pypy3.7-v7.3.7-win64.zip" },
|
{ identifier = "pp37-win_amd64", version = "3.7", arch = "64", url = "https://downloads.python.org/pypy/pypy3.7-v7.3.7-win64.zip" },
|
||||||
{ identifier = "pp38-win_amd64", version = "3.8", arch = "64", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.7-win64.zip" },
|
{ identifier = "pp38-win_amd64", version = "3.8", arch = "64", url = "https://downloads.python.org/pypy/pypy3.8-v7.3.7-win64.zip" },
|
||||||
]
|
]
|
||||||
|
|||||||
+28
-7
@@ -7,6 +7,8 @@ from pathlib import Path
|
|||||||
from typing import Dict, List, NamedTuple, Optional, Sequence, Set
|
from typing import Dict, List, NamedTuple, Optional, Sequence, Set
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
|
from packaging.version import Version
|
||||||
|
|
||||||
from .architecture import Architecture
|
from .architecture import Architecture
|
||||||
from .environment import ParsedEnvironment
|
from .environment import ParsedEnvironment
|
||||||
from .logger import log
|
from .logger import log
|
||||||
@@ -43,9 +45,8 @@ def shell(
|
|||||||
|
|
||||||
|
|
||||||
def get_nuget_args(version: str, arch: str) -> List[str]:
|
def get_nuget_args(version: str, arch: str) -> List[str]:
|
||||||
python_name = "python"
|
platform_suffix = {"32": "x86", "64": "", "ARM64": "arm64"}
|
||||||
if arch == "32":
|
python_name = "python" + platform_suffix[arch]
|
||||||
python_name += "x86"
|
|
||||||
return [
|
return [
|
||||||
python_name,
|
python_name,
|
||||||
"-Version",
|
"-Version",
|
||||||
@@ -73,10 +74,7 @@ def get_python_configurations(
|
|||||||
|
|
||||||
python_configurations = [PythonConfiguration(**item) for item in full_python_configs]
|
python_configurations = [PythonConfiguration(**item) for item in full_python_configs]
|
||||||
|
|
||||||
map_arch = {
|
map_arch = {"32": Architecture.x86, "64": Architecture.AMD64, "ARM64": Architecture.ARM64}
|
||||||
"32": Architecture.x86,
|
|
||||||
"64": Architecture.AMD64,
|
|
||||||
}
|
|
||||||
|
|
||||||
# skip builds as required
|
# skip builds as required
|
||||||
python_configurations = [
|
python_configurations = [
|
||||||
@@ -189,10 +187,33 @@ def setup_python(
|
|||||||
# Install pip
|
# Install pip
|
||||||
|
|
||||||
requires_reinstall = not (installation_path / "Scripts" / "pip.exe").exists()
|
requires_reinstall = not (installation_path / "Scripts" / "pip.exe").exists()
|
||||||
|
|
||||||
if requires_reinstall:
|
if requires_reinstall:
|
||||||
# maybe pip isn't installed at all. ensurepip resolves that.
|
# maybe pip isn't installed at all. ensurepip resolves that.
|
||||||
call(["python", "-m", "ensurepip"], env=env, cwd=CIBW_INSTALL_PATH)
|
call(["python", "-m", "ensurepip"], env=env, cwd=CIBW_INSTALL_PATH)
|
||||||
|
|
||||||
|
# pip older than 21.3 builds executables such as pip.exe for x64 platform.
|
||||||
|
# The first re-install of pip updates pip module but builds pip.exe using
|
||||||
|
# the old pip which still generates x64 executable. But the second
|
||||||
|
# re-install uses updated pip and correctly builds pip.exe for the target.
|
||||||
|
# This can be removed once ARM64 Pythons (currently 3.9 and 3.10) bundle
|
||||||
|
# pip versions newer than 21.3.
|
||||||
|
if python_configuration.arch == "ARM64" and Version(get_pip_version(env)) < Version("21.3"):
|
||||||
|
call(
|
||||||
|
[
|
||||||
|
"python",
|
||||||
|
"-m",
|
||||||
|
"pip",
|
||||||
|
"install",
|
||||||
|
"--force-reinstall",
|
||||||
|
"--upgrade",
|
||||||
|
"pip",
|
||||||
|
*dependency_constraint_flags,
|
||||||
|
],
|
||||||
|
env=env,
|
||||||
|
cwd=CIBW_INSTALL_PATH,
|
||||||
|
)
|
||||||
|
|
||||||
# upgrade pip to the version matching our constraints
|
# upgrade pip to the version matching our constraints
|
||||||
# if necessary, reinstall it to ensure that it's available on PATH as 'pip.exe'
|
# if necessary, reinstall it to ensure that it's available on PATH as 'pip.exe'
|
||||||
call(
|
call(
|
||||||
|
|||||||
+4
-2
@@ -207,8 +207,8 @@ When setting the options, you can use shell-style globbing syntax, as per [fnmat
|
|||||||
| Python 3.6 | cp36-macosx_x86_64 | cp36-win_amd64<br/>cp36-win32 | cp36-manylinux_x86_64<br/>cp36-manylinux_i686<br/>cp36-musllinux_x86_64<br/>cp36-musllinux_i686 | cp36-manylinux_aarch64<br/>cp36-manylinux_ppc64le<br/>cp36-manylinux_s390x<br/>cp36-musllinux_aarch64<br/>cp36-musllinux_ppc64le<br/>cp36-musllinux_s390x |
|
| Python 3.6 | cp36-macosx_x86_64 | cp36-win_amd64<br/>cp36-win32 | cp36-manylinux_x86_64<br/>cp36-manylinux_i686<br/>cp36-musllinux_x86_64<br/>cp36-musllinux_i686 | cp36-manylinux_aarch64<br/>cp36-manylinux_ppc64le<br/>cp36-manylinux_s390x<br/>cp36-musllinux_aarch64<br/>cp36-musllinux_ppc64le<br/>cp36-musllinux_s390x |
|
||||||
| Python 3.7 | cp37-macosx_x86_64 | cp37-win_amd64<br/>cp37-win32 | cp37-manylinux_x86_64<br/>cp37-manylinux_i686<br/>cp37-musllinux_x86_64<br/>cp37-musllinux_i686 | cp37-manylinux_aarch64<br/>cp37-manylinux_ppc64le<br/>cp37-manylinux_s390x<br/>cp37-musllinux_aarch64<br/>cp37-musllinux_ppc64le<br/>cp37-musllinux_s390x |
|
| Python 3.7 | cp37-macosx_x86_64 | cp37-win_amd64<br/>cp37-win32 | cp37-manylinux_x86_64<br/>cp37-manylinux_i686<br/>cp37-musllinux_x86_64<br/>cp37-musllinux_i686 | cp37-manylinux_aarch64<br/>cp37-manylinux_ppc64le<br/>cp37-manylinux_s390x<br/>cp37-musllinux_aarch64<br/>cp37-musllinux_ppc64le<br/>cp37-musllinux_s390x |
|
||||||
| Python 3.8 | cp38-macosx_x86_64<br/>cp38-macosx_universal2<br/>cp38-macosx_arm64 | cp38-win_amd64<br/>cp38-win32 | cp38-manylinux_x86_64<br/>cp38-manylinux_i686<br/>cp38-musllinux_x86_64<br/>cp38-musllinux_i686 | cp38-manylinux_aarch64<br/>cp38-manylinux_ppc64le<br/>cp38-manylinux_s390x<br/>cp38-musllinux_aarch64<br/>cp38-musllinux_ppc64le<br/>cp38-musllinux_s390x |
|
| Python 3.8 | cp38-macosx_x86_64<br/>cp38-macosx_universal2<br/>cp38-macosx_arm64 | cp38-win_amd64<br/>cp38-win32 | cp38-manylinux_x86_64<br/>cp38-manylinux_i686<br/>cp38-musllinux_x86_64<br/>cp38-musllinux_i686 | cp38-manylinux_aarch64<br/>cp38-manylinux_ppc64le<br/>cp38-manylinux_s390x<br/>cp38-musllinux_aarch64<br/>cp38-musllinux_ppc64le<br/>cp38-musllinux_s390x |
|
||||||
| Python 3.9 | cp39-macosx_x86_64<br/>cp39-macosx_universal2<br/>cp39-macosx_arm64 | cp39-win_amd64<br/>cp39-win32 | cp39-manylinux_x86_64<br/>cp39-manylinux_i686<br/>cp39-musllinux_x86_64<br/>cp39-musllinux_i686 | cp39-manylinux_aarch64<br/>cp39-manylinux_ppc64le<br/>cp39-manylinux_s390x<br/>cp39-musllinux_aarch64<br/>cp39-musllinux_ppc64le<br/>cp39-musllinux_s390x |
|
| Python 3.9 | cp39-macosx_x86_64<br/>cp39-macosx_universal2<br/>cp39-macosx_arm64 | cp39-win_amd64<br/>cp39-win32<br/>cp39-win_arm64 | cp39-manylinux_x86_64<br/>cp39-manylinux_i686<br/>cp39-musllinux_x86_64<br/>cp39-musllinux_i686 | cp39-manylinux_aarch64<br/>cp39-manylinux_ppc64le<br/>cp39-manylinux_s390x<br/>cp39-musllinux_aarch64<br/>cp39-musllinux_ppc64le<br/>cp39-musllinux_s390x |
|
||||||
| Python 3.10 | cp310-macosx_x86_64<br/>cp310-macosx_universal2<br/>cp310-macosx_arm64 | cp310-win_amd64<br/>cp310-win32 | cp310-manylinux_x86_64<br/>cp310-manylinux_i686<br/>cp310-musllinux_x86_64<br/>cp310-musllinux_i686 | cp310-manylinux_aarch64<br/>cp310-manylinux_ppc64le<br/>cp310-manylinux_s390x<br/>cp310-musllinux_aarch64<br/>cp310-musllinux_ppc64le<br/>cp310-musllinux_s390x |
|
| Python 3.10 | cp310-macosx_x86_64<br/>cp310-macosx_universal2<br/>cp310-macosx_arm64 | cp310-win_amd64<br/>cp310-win32<br/>cp310-win_arm64 | cp310-manylinux_x86_64<br/>cp310-manylinux_i686<br/>cp310-musllinux_x86_64<br/>cp310-musllinux_i686 | cp310-manylinux_aarch64<br/>cp310-manylinux_ppc64le<br/>cp310-manylinux_s390x<br/>cp310-musllinux_aarch64<br/>cp310-musllinux_ppc64le<br/>cp310-musllinux_s390x |
|
||||||
| PyPy3.7 v7.3 | pp37-macosx_x86_64 | pp37-win_amd64 | pp37-manylinux_x86_64<br/>pp37-manylinux_i686 | pp37-manylinux_aarch64 |
|
| PyPy3.7 v7.3 | pp37-macosx_x86_64 | pp37-win_amd64 | pp37-manylinux_x86_64<br/>pp37-manylinux_i686 | pp37-manylinux_aarch64 |
|
||||||
| PyPy3.8 v7.3 | pp38-macosx_x86_64 | pp38-win_amd64 | pp38-manylinux_x86_64<br/>pp38-manylinux_i686 | pp38-manylinux_aarch64 |
|
| PyPy3.8 v7.3 | pp38-macosx_x86_64 | pp38-win_amd64 | pp38-manylinux_x86_64<br/>pp38-manylinux_i686 | pp38-manylinux_aarch64 |
|
||||||
|
|
||||||
@@ -217,6 +217,8 @@ The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425]
|
|||||||
|
|
||||||
For CPython, the minimally supported macOS version is 10.9; for PyPy 3.7, macOS 10.13 or higher is required.
|
For CPython, the minimally supported macOS version is 10.9; for PyPy 3.7, macOS 10.13 or higher is required.
|
||||||
|
|
||||||
|
Windows arm64 platform support is experimental.
|
||||||
|
|
||||||
See the [cibuildwheel 1 documentation](https://cibuildwheel.readthedocs.io/en/1.x/) for past end of life versions of Python, and PyPy2.7.
|
See the [cibuildwheel 1 documentation](https://cibuildwheel.readthedocs.io/en/1.x/) for past end of life versions of Python, and PyPy2.7.
|
||||||
|
|
||||||
#### Examples
|
#### Examples
|
||||||
|
|||||||
@@ -178,7 +178,11 @@ def test_archs_platform_all(platform, intercepted_build_args, monkeypatch):
|
|||||||
Architecture.s390x,
|
Architecture.s390x,
|
||||||
}
|
}
|
||||||
elif platform == "windows":
|
elif platform == "windows":
|
||||||
assert options.globals.architectures == {Architecture.x86, Architecture.AMD64}
|
assert options.globals.architectures == {
|
||||||
|
Architecture.x86,
|
||||||
|
Architecture.AMD64,
|
||||||
|
Architecture.ARM64,
|
||||||
|
}
|
||||||
elif platform == "macos":
|
elif platform == "macos":
|
||||||
assert options.globals.architectures == {
|
assert options.globals.architectures == {
|
||||||
Architecture.x86_64,
|
Architecture.x86_64,
|
||||||
|
|||||||
Reference in New Issue
Block a user