feat: remove 32-bit linux from auto arch, fix auto32 on linux aarch64 (#2458)
* feat: remove 32-bit linux from auto arch, fix auto32 on linux aarch64 Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> * Apply suggestions from code review Co-authored-by: Joe Rickerby <joerick@mac.com> * Update cibuildwheel/architecture.py --------- Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com> Co-authored-by: Joe Rickerby <joerick@mac.com>
This commit is contained in:
co-authored by
Joe Rickerby
parent
3fa7bd1e72
commit
e188d9e260
@@ -75,24 +75,24 @@ class Architecture(StrEnum):
|
|||||||
def parse_config(config: str, platform: PlatformName) -> "set[Architecture]":
|
def parse_config(config: str, platform: PlatformName) -> "set[Architecture]":
|
||||||
result = set()
|
result = set()
|
||||||
for arch_str in re.split(r"[\s,]+", config):
|
for arch_str in re.split(r"[\s,]+", config):
|
||||||
if arch_str == "auto":
|
match arch_str:
|
||||||
result |= Architecture.auto_archs(platform=platform)
|
case "auto":
|
||||||
elif arch_str == "native":
|
result |= Architecture.auto_archs(platform=platform)
|
||||||
native_arch = Architecture.native_arch(platform=platform)
|
case "native":
|
||||||
if native_arch:
|
if native_arch := Architecture.native_arch(platform=platform):
|
||||||
result.add(native_arch)
|
result.add(native_arch)
|
||||||
elif arch_str == "all":
|
case "all":
|
||||||
result |= Architecture.all_archs(platform=platform)
|
result |= Architecture.all_archs(platform=platform)
|
||||||
elif arch_str == "auto64":
|
case "auto64":
|
||||||
result |= Architecture.bitness_archs(platform=platform, bitness="64")
|
result |= Architecture.bitness_archs(platform=platform, bitness="64")
|
||||||
elif arch_str == "auto32":
|
case "auto32":
|
||||||
result |= Architecture.bitness_archs(platform=platform, bitness="32")
|
result |= Architecture.bitness_archs(platform=platform, bitness="32")
|
||||||
else:
|
case _:
|
||||||
try:
|
try:
|
||||||
result.add(Architecture(arch_str))
|
result.add(Architecture(arch_str))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
msg = f"Invalid architecture '{arch_str}'"
|
msg = f"Invalid architecture '{arch_str}'"
|
||||||
raise errors.ConfigurationError(msg) from e
|
raise errors.ConfigurationError(msg) from e
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -142,19 +142,12 @@ class Architecture(StrEnum):
|
|||||||
return set() # can't build anything on this platform
|
return set() # can't build anything on this platform
|
||||||
result = {native_arch}
|
result = {native_arch}
|
||||||
|
|
||||||
if platform == "linux":
|
match platform:
|
||||||
if Architecture.x86_64 in result:
|
case "windows" if Architecture.AMD64 in result:
|
||||||
# x86_64 machines can run i686 containers
|
result.add(Architecture.x86)
|
||||||
result.add(Architecture.i686)
|
case "ios" if native_arch == Architecture.arm64_iphonesimulator:
|
||||||
elif Architecture.aarch64 in result and _check_aarch32_el0():
|
# Also build the device wheel if we're on ARM64.
|
||||||
result.add(Architecture.armv7l)
|
result.add(Architecture.arm64_iphoneos)
|
||||||
|
|
||||||
elif platform == "windows" and Architecture.AMD64 in result:
|
|
||||||
result.add(Architecture.x86)
|
|
||||||
|
|
||||||
elif platform == "ios" and native_arch == Architecture.arm64_iphonesimulator:
|
|
||||||
# Also build the device wheel if we're on ARM64.
|
|
||||||
result.add(Architecture.arm64_iphoneos)
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -183,14 +176,35 @@ class Architecture(StrEnum):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def bitness_archs(platform: PlatformName, bitness: Literal["64", "32"]) -> "set[Architecture]":
|
def bitness_archs(platform: PlatformName, bitness: Literal["64", "32"]) -> "set[Architecture]":
|
||||||
archs_32 = {Architecture.i686, Architecture.x86, Architecture.armv7l}
|
# This map maps 64-bit architectures to their 32-bit equivalents.
|
||||||
auto_archs = Architecture.auto_archs(platform)
|
archs_map = {
|
||||||
|
Architecture.x86_64: Architecture.i686,
|
||||||
|
Architecture.AMD64: Architecture.x86,
|
||||||
|
Architecture.aarch64: Architecture.armv7l,
|
||||||
|
}
|
||||||
|
native_arch = Architecture.native_arch(platform)
|
||||||
|
|
||||||
if bitness == "64":
|
if native_arch is None:
|
||||||
return auto_archs - archs_32
|
return set() # can't build anything on this platform
|
||||||
if bitness == "32":
|
|
||||||
return auto_archs & archs_32
|
if native_arch == Architecture.wasm32:
|
||||||
typing.assert_never(bitness)
|
return {native_arch} if bitness == "32" else set()
|
||||||
|
|
||||||
|
match bitness:
|
||||||
|
case "64":
|
||||||
|
return {native_arch} if native_arch not in archs_map.values() else set()
|
||||||
|
case "32":
|
||||||
|
if native_arch in archs_map.values():
|
||||||
|
return {native_arch}
|
||||||
|
elif native_arch in archs_map and platform in {"linux", "windows"}:
|
||||||
|
if native_arch == Architecture.aarch64 and not _check_aarch32_el0():
|
||||||
|
# If we're on aarch64, skip if we cannot build armv7l wheels.
|
||||||
|
return set()
|
||||||
|
return {archs_map[native_arch]}
|
||||||
|
else:
|
||||||
|
return set()
|
||||||
|
case _:
|
||||||
|
typing.assert_never(bitness)
|
||||||
|
|
||||||
|
|
||||||
def allowed_architectures_check(
|
def allowed_architectures_check(
|
||||||
|
|||||||
+31
-8
@@ -191,10 +191,10 @@ Options:
|
|||||||
- Windows: `AMD64` `x86` `ARM64`
|
- Windows: `AMD64` `x86` `ARM64`
|
||||||
- Pyodide: `wasm32`
|
- Pyodide: `wasm32`
|
||||||
- iOS: `arm64_iphoneos` `arm64_iphonesimulator` `x86_64_iphonesimulator`
|
- iOS: `arm64_iphoneos` `arm64_iphonesimulator` `x86_64_iphonesimulator`
|
||||||
- `auto`: The default archs for your machine - see the table below.
|
- `auto`: The recommended archs for your machine - see the table below.
|
||||||
- `auto64`: Just the 64-bit auto archs
|
- `auto64`: The 64-bit arch(s) supported by your machine (includes device and simulator for iOS)
|
||||||
- `auto32`: Just the 32-bit auto archs
|
- `auto32`: The 32-bit arch supported by your machine
|
||||||
- `native`: the native arch of the build machine - Matches [`platform.machine()`](https://docs.python.org/3/library/platform.html#platform.machine).
|
- `native`: the native arch of the build machine - matches [`platform.machine()`](https://docs.python.org/3/library/platform.html#platform.machine).
|
||||||
- `all` : expands to all the architectures supported on this OS. You may want
|
- `all` : expands to all the architectures supported on this OS. You may want
|
||||||
to use [`build`](#build-skip) with this option to target specific
|
to use [`build`](#build-skip) with this option to target specific
|
||||||
architectures via build selectors.
|
architectures via build selectors.
|
||||||
@@ -205,16 +205,34 @@ Default: `auto`
|
|||||||
|
|
||||||
| Runner | `native` | `auto` | `auto64` | `auto32` |
|
| Runner | `native` | `auto` | `auto64` | `auto32` |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| Linux / Intel | `x86_64` | `x86_64` `i686` | `x86_64` | `i686` |
|
| Linux / Intel 64-bit | `x86_64` | `x86_64` | `x86_64` | `i686` |
|
||||||
| Windows / Intel | `AMD64` | `AMD64` `x86` | `AMD64` | `x86` |
|
| Linux / Intel 32-bit | `i686` | `i686` | | `i686` |
|
||||||
|
| Linux / Arm 64-bit | `aarch64` | `aarch64` | `aarch64` | `armv7l`¹ |
|
||||||
|
| Linux / Arm 32-bit | `armv7l` | `armv7l` | | `armv7l` |
|
||||||
|
| Windows / Intel 64-bit | `AMD64` | `AMD64` `x86` | `AMD64` | `x86` |
|
||||||
|
| Windows / Intel 32-bit | `x86` | `x86` | | `x86` |
|
||||||
| Windows / ARM64 | `ARM64` | `ARM64` | `ARM64` | |
|
| Windows / ARM64 | `ARM64` | `ARM64` | `ARM64` | |
|
||||||
| macOS / Intel | `x86_64` | `x86_64` | `x86_64` | |
|
| macOS / Intel | `x86_64` | `x86_64` | `x86_64` | |
|
||||||
| macOS / Apple Silicon | `arm64` | `arm64` | `arm64` | |
|
| macOS / Apple Silicon | `arm64` | `arm64` | `arm64` | |
|
||||||
| iOS on macOS / Intel | `x86_64_iphonesimulator` | `x86_64_iphonesimulator` | `x86_64_iphonesimulator` | |
|
| iOS on macOS / Intel | `x86_64_iphonesimulator` | `x86_64_iphonesimulator` | `x86_64_iphonesimulator` | |
|
||||||
| iOS on macOS / Apple Silicon | `arm64_iphonesimulator` | `arm64_iphoneos` `arm64_iphonesimulator` | `arm64_iphoneos` `arm64_iphonesimulator` |
|
| iOS on macOS / Apple Silicon | `arm64_iphonesimulator` | `arm64_iphoneos` `arm64_iphonesimulator` | `arm64_iphoneos` `arm64_iphonesimulator` |
|
||||||
|
|
||||||
|
¹: This will only be included if the runner supports it.
|
||||||
|
|
||||||
If not listed above, `auto` is the same as `native`.
|
If not listed above, `auto` is the same as `native`.
|
||||||
|
|
||||||
|
!!! warning
|
||||||
|
The `auto` option only includes 32-bit architectures if they are
|
||||||
|
commonly built. `cibuildwheel` 3.0 removed 32-bit Linux builds from `auto`,
|
||||||
|
and a future release may remove 32-bit Windows builds from `auto` as well.
|
||||||
|
If you know you need them, please include `auto32`. Note that modern
|
||||||
|
manylinux image do not support 32-bit builds. If you want to avoid 32-bit
|
||||||
|
Windows builds today, feel free to use `auto64`.
|
||||||
|
|
||||||
|
!!! note
|
||||||
|
Pyodide currently ignores the architecture setting, as it always builds for
|
||||||
|
`wasm32`.
|
||||||
|
|
||||||
[setup-qemu-action]: https://github.com/docker/setup-qemu-action
|
[setup-qemu-action]: https://github.com/docker/setup-qemu-action
|
||||||
[binfmt]: https://hub.docker.com/r/tonistiigi/binfmt
|
[binfmt]: https://hub.docker.com/r/tonistiigi/binfmt
|
||||||
|
|
||||||
@@ -238,6 +256,10 @@ This option can also be set using the [command-line option](#command-line)
|
|||||||
# On an Linux Intel runner with qemu installed, build Intel and ARM wheels
|
# On an Linux Intel runner with qemu installed, build Intel and ARM wheels
|
||||||
[tool.cibuildwheel.linux]
|
[tool.cibuildwheel.linux]
|
||||||
archs = ["auto", "aarch64"]
|
archs = ["auto", "aarch64"]
|
||||||
|
|
||||||
|
# Build all 32-bit and 64-bit wheels natively buildable on the image
|
||||||
|
[tool.cibuildwheel]
|
||||||
|
archs = ["auto64", "auto32"]
|
||||||
```
|
```
|
||||||
|
|
||||||
!!! tab examples "Environment variables"
|
!!! tab examples "Environment variables"
|
||||||
@@ -250,12 +272,13 @@ This option can also be set using the [command-line option](#command-line)
|
|||||||
|
|
||||||
# On an Linux Intel runner with qemu installed, build Intel and ARM wheels
|
# On an Linux Intel runner with qemu installed, build Intel and ARM wheels
|
||||||
CIBW_ARCHS_LINUX: "auto aarch64"
|
CIBW_ARCHS_LINUX: "auto aarch64"
|
||||||
|
|
||||||
|
# Build all 32-bit and 64-bit wheels natively buildable on the image
|
||||||
|
CIBW_ARCHS: "auto64 auto32"
|
||||||
```
|
```
|
||||||
|
|
||||||
Separate multiple archs with a space.
|
Separate multiple archs with a space.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
It is generally recommended to use the environment variable or
|
It is generally recommended to use the environment variable or
|
||||||
command-line option for Linux, as selecting archs often depends
|
command-line option for Linux, as selecting archs often depends
|
||||||
on your specific runner having qemu installed.
|
on your specific runner having qemu installed.
|
||||||
|
|||||||
+2
-1
@@ -175,6 +175,7 @@ def expected_wheels(
|
|||||||
include_universal2: bool = False,
|
include_universal2: bool = False,
|
||||||
single_python: bool = False,
|
single_python: bool = False,
|
||||||
single_arch: bool = False,
|
single_arch: bool = False,
|
||||||
|
full_auto: bool = False,
|
||||||
) -> list[str]:
|
) -> list[str]:
|
||||||
"""
|
"""
|
||||||
Returns the expected wheels from a run of cibuildwheel.
|
Returns the expected wheels from a run of cibuildwheel.
|
||||||
@@ -194,7 +195,7 @@ def expected_wheels(
|
|||||||
|
|
||||||
architectures = [machine_arch]
|
architectures = [machine_arch]
|
||||||
if not single_arch:
|
if not single_arch:
|
||||||
if platform == "linux":
|
if platform == "linux" and full_auto:
|
||||||
if machine_arch == "x86_64":
|
if machine_arch == "x86_64":
|
||||||
architectures.append("i686")
|
architectures.append("i686")
|
||||||
elif (
|
elif (
|
||||||
|
|||||||
@@ -34,8 +34,8 @@ def test_arch_auto(platform_machine):
|
|||||||
arch_set = Architecture.auto_archs("linux")
|
arch_set = Architecture.auto_archs("linux")
|
||||||
expected = {
|
expected = {
|
||||||
"32": {Architecture.i686},
|
"32": {Architecture.i686},
|
||||||
"64": {Architecture.x86_64, Architecture.i686},
|
"64": {Architecture.x86_64},
|
||||||
"arm": {Architecture.aarch64, Architecture.armv7l},
|
"arm": {Architecture.aarch64},
|
||||||
}
|
}
|
||||||
assert arch_set == expected[machine_name]
|
assert arch_set == expected[machine_name]
|
||||||
|
|
||||||
@@ -94,5 +94,24 @@ def test_arch_auto_no_aarch32(monkeypatch):
|
|||||||
arch_set = Architecture.parse_config("auto64", "linux")
|
arch_set = Architecture.parse_config("auto64", "linux")
|
||||||
assert arch_set == {Architecture.aarch64}
|
assert arch_set == {Architecture.aarch64}
|
||||||
|
|
||||||
|
monkeypatch.setattr(cibuildwheel.architecture, "_check_aarch32_el0", lambda: True)
|
||||||
arch_set = Architecture.parse_config("auto32", "linux")
|
arch_set = Architecture.parse_config("auto32", "linux")
|
||||||
assert len(arch_set) == 0
|
assert arch_set == {Architecture.armv7l}
|
||||||
|
|
||||||
|
monkeypatch.setattr(cibuildwheel.architecture, "_check_aarch32_el0", lambda: False)
|
||||||
|
arch_set = Architecture.parse_config("auto32", "linux")
|
||||||
|
assert arch_set == set()
|
||||||
|
|
||||||
|
|
||||||
|
def test_arch_native_on_ios(monkeypatch):
|
||||||
|
monkeypatch.setattr(sys, "platform", "darwin")
|
||||||
|
monkeypatch.setattr(platform_module, "machine", lambda: "arm64")
|
||||||
|
arch_set = Architecture.parse_config("native", platform="ios")
|
||||||
|
assert arch_set == {Architecture.arm64_iphonesimulator}
|
||||||
|
|
||||||
|
|
||||||
|
def test_arch_auto_on_ios(monkeypatch):
|
||||||
|
monkeypatch.setattr(sys, "platform", "darwin")
|
||||||
|
monkeypatch.setattr(platform_module, "machine", lambda: "arm64")
|
||||||
|
arch_set = Architecture.parse_config("auto", platform="ios")
|
||||||
|
assert arch_set == {Architecture.arm64_iphonesimulator, Architecture.arm64_iphoneos}
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ def test_archs_default(platform, intercepted_build_args):
|
|||||||
options = intercepted_build_args.args[0]
|
options = intercepted_build_args.args[0]
|
||||||
|
|
||||||
if platform == "linux":
|
if platform == "linux":
|
||||||
assert options.globals.architectures == {Architecture.x86_64, Architecture.i686}
|
assert options.globals.architectures == {Architecture.x86_64}
|
||||||
elif platform == "windows":
|
elif platform == "windows":
|
||||||
assert options.globals.architectures == {Architecture.AMD64, Architecture.x86}
|
assert options.globals.architectures == {Architecture.AMD64, Architecture.x86}
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ def mock_build_container(monkeypatch):
|
|||||||
@pytest.mark.usefixtures("mock_build_container", "fake_package_dir")
|
@pytest.mark.usefixtures("mock_build_container", "fake_package_dir")
|
||||||
def test_build_default_launches(monkeypatch):
|
def test_build_default_launches(monkeypatch):
|
||||||
monkeypatch.setattr(sys, "argv", [*sys.argv, "--platform=linux"])
|
monkeypatch.setattr(sys, "argv", [*sys.argv, "--platform=linux"])
|
||||||
|
monkeypatch.setenv("CIBW_ARCHS", "auto64 auto32")
|
||||||
monkeypatch.delenv("CIBW_ENABLE", raising=False)
|
monkeypatch.delenv("CIBW_ENABLE", raising=False)
|
||||||
|
|
||||||
main()
|
main()
|
||||||
@@ -105,6 +106,7 @@ def test_build_with_override_launches(monkeypatch, tmp_path):
|
|||||||
manylinux-x86_64-image = "manylinux_2_28"
|
manylinux-x86_64-image = "manylinux_2_28"
|
||||||
musllinux-x86_64-image = "musllinux_1_2"
|
musllinux-x86_64-image = "musllinux_1_2"
|
||||||
enable = ["pypy", "pypy-eol", "graalpy", "cpython-freethreading"]
|
enable = ["pypy", "pypy-eol", "graalpy", "cpython-freethreading"]
|
||||||
|
archs = ["auto64", "auto32"]
|
||||||
|
|
||||||
# Before Python 3.10, use manylinux2014
|
# Before Python 3.10, use manylinux2014
|
||||||
[[tool.cibuildwheel.overrides]]
|
[[tool.cibuildwheel.overrides]]
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ PYPROJECT_1 = """
|
|||||||
[tool.cibuildwheel]
|
[tool.cibuildwheel]
|
||||||
build = ["cp38-*", "cp313-*"]
|
build = ["cp38-*", "cp313-*"]
|
||||||
skip = ["*musllinux*"]
|
skip = ["*musllinux*"]
|
||||||
|
archs = ["auto64", "auto32"]
|
||||||
environment = {FOO="BAR"}
|
environment = {FOO="BAR"}
|
||||||
|
|
||||||
test-command = "pyproject"
|
test-command = "pyproject"
|
||||||
|
|||||||
Reference in New Issue
Block a user