From 5f8d06ff55679f81d007fe6aed2e7e0d9e9e3181 Mon Sep 17 00:00:00 2001 From: Matthieu Darbois Date: Mon, 28 Apr 2025 18:05:03 +0200 Subject: [PATCH] feat: initial support for riscv64 (#2366) * feat: initial support for riscv64 * use enable for riscv64 * Apply review suggestion Co-authored-by: Joe Rickerby * update documentation --------- Co-authored-by: Joe Rickerby --- bin/generate_schema.py | 7 +++ bin/update_docker.py | 3 + cibuildwheel/architecture.py | 2 + cibuildwheel/logger.py | 2 + cibuildwheel/oci_container.py | 1 + cibuildwheel/options.py | 2 + cibuildwheel/platforms/linux.py | 1 + cibuildwheel/resources/build-platforms.toml | 14 +++++ .../resources/cibuildwheel.schema.json | 60 ++++++++++++++++--- cibuildwheel/resources/defaults.toml | 2 + .../resources/pinned_docker_images.cfg | 2 + cibuildwheel/selector.py | 5 ++ docs/options.md | 34 +++++++---- test/test_emulation.py | 13 +++- test/utils.py | 1 + unit_test/build_selector_test.py | 9 +++ unit_test/main_tests/main_platform_test.py | 1 + unit_test/oci_container_test.py | 6 +- 18 files changed, 139 insertions(+), 26 deletions(-) diff --git a/bin/generate_schema.py b/bin/generate_schema.py index 8ca6a1a7..728a5a56 100755 --- a/bin/generate_schema.py +++ b/bin/generate_schema.py @@ -31,6 +31,7 @@ $defs: - cpython-freethreading - cpython-prerelease - pypy + - cpython-experimental-riscv64 description: A Python version or flavor to enable. additionalProperties: false description: cibuildwheel's settings. @@ -157,6 +158,9 @@ properties: manylinux-pypy_x86_64-image: type: string description: Specify alternative manylinux / musllinux container images + manylinux-riscv64-image: + type: string + description: Specify alternative manylinux / musllinux container images manylinux-s390x-image: type: string description: Specify alternative manylinux / musllinux container images @@ -175,6 +179,9 @@ properties: musllinux-ppc64le-image: type: string description: Specify alternative manylinux / musllinux container images + musllinux-riscv64-image: + type: string + description: Specify alternative manylinux / musllinux container images musllinux-s390x-image: type: string description: Specify alternative manylinux / musllinux container images diff --git a/bin/update_docker.py b/bin/update_docker.py index 3f23d75d..efb90154 100755 --- a/bin/update_docker.py +++ b/bin/update_docker.py @@ -116,5 +116,8 @@ for image in images: suffix = f"_{platform.removeprefix('pypy_')}" config[platform][image.manylinux_version] = f"{image.image_name}{suffix}:{tag_name}" +if not config.has_section("riscv64"): + config["riscv64"] = {} + with open(RESOURCES / "pinned_docker_images.cfg", "w") as f: config.write(f) diff --git a/cibuildwheel/architecture.py b/cibuildwheel/architecture.py index de17c75d..0ac2f1a1 100644 --- a/cibuildwheel/architecture.py +++ b/cibuildwheel/architecture.py @@ -51,6 +51,7 @@ class Architecture(StrEnum): ppc64le = auto() s390x = auto() armv7l = auto() + riscv64 = auto() # mac archs universal2 = auto() @@ -167,6 +168,7 @@ class Architecture(StrEnum): Architecture.ppc64le, Architecture.s390x, Architecture.armv7l, + Architecture.riscv64, }, "macos": {Architecture.x86_64, Architecture.arm64, Architecture.universal2}, "windows": {Architecture.x86, Architecture.AMD64, Architecture.ARM64}, diff --git a/cibuildwheel/logger.py b/cibuildwheel/logger.py index 391786a0..321352e8 100644 --- a/cibuildwheel/logger.py +++ b/cibuildwheel/logger.py @@ -22,12 +22,14 @@ PLATFORM_IDENTIFIER_DESCRIPTIONS: Final[dict[str, str]] = { "manylinux_ppc64le": "manylinux ppc64le", "manylinux_s390x": "manylinux s390x", "manylinux_armv7l": "manylinux armv7l", + "manylinux_riscv64": "manylinux riscv64", "musllinux_x86_64": "musllinux x86_64", "musllinux_i686": "musllinux i686", "musllinux_aarch64": "musllinux aarch64", "musllinux_ppc64le": "musllinux ppc64le", "musllinux_s390x": "musllinux s390x", "musllinux_armv7l": "musllinux armv7l", + "musllinux_riscv64": "musllinux riscv64", "win32": "Windows 32bit", "win_amd64": "Windows 64bit", "win_arm64": "Windows on ARM 64bit", diff --git a/cibuildwheel/oci_container.py b/cibuildwheel/oci_container.py index 3a4a4995..fa3d7704 100644 --- a/cibuildwheel/oci_container.py +++ b/cibuildwheel/oci_container.py @@ -33,6 +33,7 @@ class OCIPlatform(Enum): ARMV7 = "linux/arm/v7" ARM64 = "linux/arm64" PPC64LE = "linux/ppc64le" + RISCV64 = "linux/riscv64" S390X = "linux/s390x" diff --git a/cibuildwheel/options.py b/cibuildwheel/options.py index b0177e0c..283f48f7 100644 --- a/cibuildwheel/options.py +++ b/cibuildwheel/options.py @@ -35,6 +35,7 @@ MANYLINUX_ARCHS: Final[tuple[str, ...]] = ( "ppc64le", "s390x", "armv7l", + "riscv64", "pypy_aarch64", "pypy_i686", ) @@ -46,6 +47,7 @@ MUSLLINUX_ARCHS: Final[tuple[str, ...]] = ( "ppc64le", "s390x", "armv7l", + "riscv64", ) diff --git a/cibuildwheel/platforms/linux.py b/cibuildwheel/platforms/linux.py index 4932298a..e39a24e0 100644 --- a/cibuildwheel/platforms/linux.py +++ b/cibuildwheel/platforms/linux.py @@ -28,6 +28,7 @@ ARCHITECTURE_OCI_PLATFORM_MAP = { Architecture.ppc64le: OCIPlatform.PPC64LE, Architecture.s390x: OCIPlatform.S390X, Architecture.armv7l: OCIPlatform.ARMV7, + Architecture.riscv64: OCIPlatform.RISCV64, } diff --git a/cibuildwheel/resources/build-platforms.toml b/cibuildwheel/resources/build-platforms.toml index d8bf3833..d2ad15e0 100644 --- a/cibuildwheel/resources/build-platforms.toml +++ b/cibuildwheel/resources/build-platforms.toml @@ -46,6 +46,13 @@ python_configurations = [ { identifier = "cp312-manylinux_armv7l", version = "3.12", path_str = "/opt/python/cp312-cp312" }, { identifier = "cp313-manylinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313" }, { identifier = "cp313t-manylinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313t" }, + { identifier = "cp38-manylinux_riscv64", version = "3.8", path_str = "/opt/python/cp38-cp38" }, + { identifier = "cp39-manylinux_riscv64", version = "3.9", path_str = "/opt/python/cp39-cp39" }, + { identifier = "cp310-manylinux_riscv64", version = "3.10", path_str = "/opt/python/cp310-cp310" }, + { identifier = "cp311-manylinux_riscv64", version = "3.11", path_str = "/opt/python/cp311-cp311" }, + { identifier = "cp312-manylinux_riscv64", version = "3.12", path_str = "/opt/python/cp312-cp312" }, + { identifier = "cp313-manylinux_riscv64", version = "3.13", path_str = "/opt/python/cp313-cp313" }, + { identifier = "cp313t-manylinux_riscv64", version = "3.13", path_str = "/opt/python/cp313-cp313t" }, { identifier = "pp38-manylinux_aarch64", version = "3.8", path_str = "/opt/python/pp38-pypy38_pp73" }, { identifier = "pp39-manylinux_aarch64", version = "3.9", path_str = "/opt/python/pp39-pypy39_pp73" }, { identifier = "pp310-manylinux_aarch64", version = "3.10", path_str = "/opt/python/pp310-pypy310_pp73" }, @@ -96,6 +103,13 @@ python_configurations = [ { identifier = "cp312-musllinux_armv7l", version = "3.12", path_str = "/opt/python/cp312-cp312" }, { identifier = "cp313-musllinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313" }, { identifier = "cp313t-musllinux_armv7l", version = "3.13", path_str = "/opt/python/cp313-cp313t" }, + { identifier = "cp38-musllinux_riscv64", version = "3.8", path_str = "/opt/python/cp38-cp38" }, + { identifier = "cp39-musllinux_ricv64", version = "3.9", path_str = "/opt/python/cp39-cp39" }, + { identifier = "cp310-musllinux_riscv64", version = "3.10", path_str = "/opt/python/cp310-cp310" }, + { identifier = "cp311-musllinux_riscv64", version = "3.11", path_str = "/opt/python/cp311-cp311" }, + { identifier = "cp312-musllinux_riscv64", version = "3.12", path_str = "/opt/python/cp312-cp312" }, + { identifier = "cp313-musllinux_riscv64", version = "3.13", path_str = "/opt/python/cp313-cp313" }, + { identifier = "cp313t-musllinux_riscv64", version = "3.13", path_str = "/opt/python/cp313-cp313t" }, ] [macos] diff --git a/cibuildwheel/resources/cibuildwheel.schema.json b/cibuildwheel/resources/cibuildwheel.schema.json index 10e07cc1..46ad0020 100644 --- a/cibuildwheel/resources/cibuildwheel.schema.json +++ b/cibuildwheel/resources/cibuildwheel.schema.json @@ -15,7 +15,8 @@ "enum": [ "cpython-freethreading", "cpython-prerelease", - "pypy" + "pypy", + "cpython-experimental-riscv64" ] }, "description": "A Python version or flavor to enable." @@ -357,6 +358,11 @@ "description": "Specify alternative manylinux / musllinux container images", "title": "CIBW_MANYLINUX_PYPY_X86_64_IMAGE" }, + "manylinux-riscv64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MANYLINUX_RISCV64_IMAGE" + }, "manylinux-s390x-image": { "type": "string", "description": "Specify alternative manylinux / musllinux container images", @@ -387,6 +393,11 @@ "description": "Specify alternative manylinux / musllinux container images", "title": "CIBW_MUSLLINUX_PPC64LE_IMAGE" }, + "musllinux-riscv64-image": { + "type": "string", + "description": "Specify alternative manylinux / musllinux container images", + "title": "CIBW_MUSLLINUX_RISCV64_IMAGE" + }, "musllinux-s390x-image": { "type": "string", "description": "Specify alternative manylinux / musllinux container images", @@ -566,6 +577,9 @@ "before-build": { "$ref": "#/$defs/inherit" }, + "xbuild-tools": { + "$ref": "#/$defs/inherit" + }, "before-test": { "$ref": "#/$defs/inherit" }, @@ -581,9 +595,6 @@ "environment-pass": { "$ref": "#/$defs/inherit" }, - "xbuild-tools": { - "$ref": "#/$defs/inherit" - }, "repair-wheel-command": { "$ref": "#/$defs/inherit" }, @@ -652,6 +663,9 @@ "manylinux-pypy_x86_64-image": { "$ref": "#/properties/manylinux-pypy_x86_64-image" }, + "manylinux-riscv64-image": { + "$ref": "#/properties/manylinux-riscv64-image" + }, "manylinux-s390x-image": { "$ref": "#/properties/manylinux-s390x-image" }, @@ -670,12 +684,18 @@ "musllinux-ppc64le-image": { "$ref": "#/properties/musllinux-ppc64le-image" }, + "musllinux-riscv64-image": { + "$ref": "#/properties/musllinux-riscv64-image" + }, "musllinux-s390x-image": { "$ref": "#/properties/musllinux-s390x-image" }, "musllinux-x86_64-image": { "$ref": "#/properties/musllinux-x86_64-image" }, + "xbuild-tools": { + "$ref": "#/properties/xbuild-tools" + }, "repair-wheel-command": { "$ref": "#/properties/repair-wheel-command" }, @@ -752,6 +772,9 @@ "manylinux-pypy_x86_64-image": { "$ref": "#/properties/manylinux-pypy_x86_64-image" }, + "manylinux-riscv64-image": { + "$ref": "#/properties/manylinux-riscv64-image" + }, "manylinux-s390x-image": { "$ref": "#/properties/manylinux-s390x-image" }, @@ -770,12 +793,18 @@ "musllinux-ppc64le-image": { "$ref": "#/properties/musllinux-ppc64le-image" }, + "musllinux-riscv64-image": { + "$ref": "#/properties/musllinux-riscv64-image" + }, "musllinux-s390x-image": { "$ref": "#/properties/musllinux-s390x-image" }, "musllinux-x86_64-image": { "$ref": "#/properties/musllinux-x86_64-image" }, + "xbuild-tools": { + "$ref": "#/properties/xbuild-tools" + }, "repair-wheel-command": { "description": "Execute a shell command to repair each built wheel.", "oneOf": [ @@ -840,6 +869,9 @@ "environment": { "$ref": "#/properties/environment" }, + "xbuild-tools": { + "$ref": "#/properties/xbuild-tools" + }, "repair-wheel-command": { "$ref": "#/properties/repair-wheel-command" }, @@ -891,6 +923,9 @@ "environment": { "$ref": "#/properties/environment" }, + "xbuild-tools": { + "$ref": "#/properties/xbuild-tools" + }, "repair-wheel-command": { "description": "Execute a shell command to repair each built wheel.", "oneOf": [ @@ -955,6 +990,9 @@ "environment": { "$ref": "#/properties/environment" }, + "xbuild-tools": { + "$ref": "#/properties/xbuild-tools" + }, "repair-wheel-command": { "$ref": "#/properties/repair-wheel-command" }, @@ -1006,22 +1044,28 @@ "environment": { "$ref": "#/properties/environment" }, - "repair-wheel-command": { - "$ref": "#/properties/repair-wheel-command" - }, "xbuild-tools": { "$ref": "#/properties/xbuild-tools" }, + "repair-wheel-command": { + "$ref": "#/properties/repair-wheel-command" + }, "test-command": { "$ref": "#/properties/test-command" }, "test-extras": { "$ref": "#/properties/test-extras" }, + "test-sources": { + "$ref": "#/properties/test-sources" + }, + "test-groups": { + "$ref": "#/properties/test-groups" + }, "test-requires": { "$ref": "#/properties/test-requires" } - } + } } } } diff --git a/cibuildwheel/resources/defaults.toml b/cibuildwheel/resources/defaults.toml index 8ca42455..4d03394f 100644 --- a/cibuildwheel/resources/defaults.toml +++ b/cibuildwheel/resources/defaults.toml @@ -33,6 +33,7 @@ manylinux-aarch64-image = "manylinux_2_28" manylinux-ppc64le-image = "manylinux_2_28" manylinux-s390x-image = "manylinux_2_28" manylinux-armv7l-image = "manylinux_2_31" +manylinux-riscv64-image = "ghcr.io/pypa/cibuildwheel/no_default_image:please_use_override" manylinux-pypy_x86_64-image = "manylinux_2_28" manylinux-pypy_i686-image = "manylinux2014" manylinux-pypy_aarch64-image = "manylinux_2_28" @@ -43,6 +44,7 @@ musllinux-aarch64-image = "musllinux_1_2" musllinux-ppc64le-image = "musllinux_1_2" musllinux-s390x-image = "musllinux_1_2" musllinux-armv7l-image = "musllinux_1_2" +musllinux-riscv64-image = "ghcr.io/pypa/cibuildwheel/no_default_image:please_use_override" [tool.cibuildwheel.linux] diff --git a/cibuildwheel/resources/pinned_docker_images.cfg b/cibuildwheel/resources/pinned_docker_images.cfg index 528a4eeb..7a9962a3 100644 --- a/cibuildwheel/resources/pinned_docker_images.cfg +++ b/cibuildwheel/resources/pinned_docker_images.cfg @@ -43,3 +43,5 @@ manylinux_2_34 = quay.io/pypa/manylinux_2_34_aarch64:2025.04.19-1 manylinux_2_31 = quay.io/pypa/manylinux_2_31_armv7l:2025.04.19-1 musllinux_1_2 = quay.io/pypa/musllinux_1_2_armv7l:2025.04.19-1 +[riscv64] + diff --git a/cibuildwheel/selector.py b/cibuildwheel/selector.py index 0e9736f5..98c7a660 100644 --- a/cibuildwheel/selector.py +++ b/cibuildwheel/selector.py @@ -32,6 +32,7 @@ class EnableGroup(StrEnum): CPythonFreeThreading = "cpython-freethreading" CPythonPrerelease = "cpython-prerelease" PyPy = "pypy" + CPythonExperimentalRiscV64 = "cpython-experimental-riscv64" @classmethod def all_groups(cls) -> frozenset["EnableGroup"]: @@ -70,6 +71,10 @@ class BuildSelector: return False if EnableGroup.PyPy not in self.enable and fnmatch(build_id, "pp*"): return False + if EnableGroup.CPythonExperimentalRiscV64 not in self.enable and fnmatch( + build_id, "*_riscv64" + ): + return False should_build = selector_matches(self.build_config, build_id) should_skip = selector_matches(self.skip_config, build_id) diff --git a/docs/options.md b/docs/options.md index de4317b4..9d906b0c 100644 --- a/docs/options.md +++ b/docs/options.md @@ -50,23 +50,24 @@ When setting the options, you can use shell-style globbing syntax, as per [fnmat
-| | macOS | Windows | Linux Intel | Linux Other | iOS | -|---------------|------------------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------| -| Python 3.8 | cp38-macosx_x86_64
cp38-macosx_universal2
cp38-macosx_arm64 | cp38-win_amd64
cp38-win32 | cp38-manylinux_x86_64
cp38-manylinux_i686
cp38-musllinux_x86_64
cp38-musllinux_i686 | cp38-manylinux_aarch64
cp38-manylinux_ppc64le
cp38-manylinux_s390x
cp38-manylinux_armv7l
cp38-musllinux_aarch64
cp38-musllinux_ppc64le
cp38-musllinux_s390x
cp38-musllinux_armv7l | | -| Python 3.9 | cp39-macosx_x86_64
cp39-macosx_universal2
cp39-macosx_arm64 | cp39-win_amd64
cp39-win32
cp39-win_arm64 | cp39-manylinux_x86_64
cp39-manylinux_i686
cp39-musllinux_x86_64
cp39-musllinux_i686 | cp39-manylinux_aarch64
cp39-manylinux_ppc64le
cp39-manylinux_s390x
cp39-manylinux_armv7l
cp39-musllinux_aarch64
cp39-musllinux_ppc64le
cp39-musllinux_s390x
cp39-musllinux_armv7l | | -| Python 3.10 | cp310-macosx_x86_64
cp310-macosx_universal2
cp310-macosx_arm64 | cp310-win_amd64
cp310-win32
cp310-win_arm64 | cp310-manylinux_x86_64
cp310-manylinux_i686
cp310-musllinux_x86_64
cp310-musllinux_i686 | cp310-manylinux_aarch64
cp310-manylinux_ppc64le
cp310-manylinux_s390x
cp310-manylinux_armv7l
cp310-musllinux_aarch64
cp310-musllinux_ppc64le
cp310-musllinux_s390x
cp310-musllinux_armv7l | | -| Python 3.11 | cp311-macosx_x86_64
cp311-macosx_universal2
cp311-macosx_arm64 | cp311-win_amd64
cp311-win32
cp311-win_arm64 | cp311-manylinux_x86_64
cp311-manylinux_i686
cp311-musllinux_x86_64
cp311-musllinux_i686 | cp311-manylinux_aarch64
cp311-manylinux_ppc64le
cp311-manylinux_s390x
cp311-manylinux_armv7l
cp311-musllinux_aarch64
cp311-musllinux_ppc64le
cp311-musllinux_s390x
cp311-musllinux_armv7l | | -| Python 3.12 | cp312-macosx_x86_64
cp312-macosx_universal2
cp312-macosx_arm64 | cp312-win_amd64
cp312-win32
cp312-win_arm64 | cp312-manylinux_x86_64
cp312-manylinux_i686
cp312-musllinux_x86_64
cp312-musllinux_i686 | cp312-manylinux_aarch64
cp312-manylinux_ppc64le
cp312-manylinux_s390x
cp312-musllinux_armv7l
cp312-musllinux_ppc64le
cp312-musllinux_s390x
cp312-musllinux_armv7l | | -| Python 3.13 | cp313-macosx_x86_64
cp313-macosx_universal2
cp313-macosx_arm64 | cp313-win_amd64
cp313-win32
cp313-win_arm64 | cp313-manylinux_x86_64
cp313-manylinux_i686
cp313-musllinux_x86_64
cp313-musllinux_i686 | cp313-manylinux_aarch64
cp313-manylinux_ppc64le
cp313-manylinux_s390x
cp313-manylinux_armv7l
cp313-musllinux_aarch64
cp313-musllinux_ppc64le
cp313-musllinux_s390x
cp313-musllinux_armv7l | cp313-ios_arm64_iphoneos
cp313-ios_arm64_iphonesimulator
cp313-ios_x86_64_iphonesimulator | -| PyPy3.8 v7.3 | pp38-macosx_x86_64
pp38-macosx_arm64 | pp38-win_amd64 | pp38-manylinux_x86_64
pp38-manylinux_i686 | pp38-manylinux_aarch64 | | -| PyPy3.9 v7.3 | pp39-macosx_x86_64
pp39-macosx_arm64 | pp39-win_amd64 | pp39-manylinux_x86_64
pp39-manylinux_i686 | pp39-manylinux_aarch64 | | -| PyPy3.10 v7.3 | pp310-macosx_x86_64
pp310-macosx_arm64 | pp310-win_amd64 | pp310-manylinux_x86_64
pp310-manylinux_i686 | pp310-manylinux_aarch64 | | -| PyPy3.11 v7.3 | pp311-macosx_x86_64
pp311-macosx_arm64 | pp311-win_amd64 | pp311-manylinux_x86_64
pp311-manylinux_i686 | pp311-manylinux_aarch64 | | +| | macOS | Windows | Linux Intel | Linux Other | iOS | +|---------------|------------------------------------------------------------------------|-----------------------------------------------------|-----------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------| +| Python 3.8 | cp38-macosx_x86_64
cp38-macosx_universal2
cp38-macosx_arm64 | cp38-win_amd64
cp38-win32 | cp38-manylinux_x86_64
cp38-manylinux_i686
cp38-musllinux_x86_64
cp38-musllinux_i686 | cp38-manylinux_aarch64
cp38-manylinux_ppc64le
cp38-manylinux_s390x
cp38-manylinux_armv7l
cp38-manylinux_riscv64
cp38-musllinux_aarch64
cp38-musllinux_ppc64le
cp38-musllinux_s390x
cp38-musllinux_armv7l
cp38-musllinux_riscv64 | | +| Python 3.9 | cp39-macosx_x86_64
cp39-macosx_universal2
cp39-macosx_arm64 | cp39-win_amd64
cp39-win32
cp39-win_arm64 | cp39-manylinux_x86_64
cp39-manylinux_i686
cp39-musllinux_x86_64
cp39-musllinux_i686 | cp39-manylinux_aarch64
cp39-manylinux_ppc64le
cp39-manylinux_s390x
cp39-manylinux_armv7l
cp39-manylinux_riscv64
cp39-musllinux_aarch64
cp39-musllinux_ppc64le
cp39-musllinux_s390x
cp39-musllinux_armv7l
cp39-musllinux_riscv64 | | +| Python 3.10 | cp310-macosx_x86_64
cp310-macosx_universal2
cp310-macosx_arm64 | cp310-win_amd64
cp310-win32
cp310-win_arm64 | cp310-manylinux_x86_64
cp310-manylinux_i686
cp310-musllinux_x86_64
cp310-musllinux_i686 | cp310-manylinux_aarch64
cp310-manylinux_ppc64le
cp310-manylinux_s390x
cp310-manylinux_armv7l
cp310-manylinux_riscv64
cp310-musllinux_aarch64
cp310-musllinux_ppc64le
cp310-musllinux_s390x
cp310-musllinux_armv7l
cp310-musllinux_riscv64 | | +| Python 3.11 | cp311-macosx_x86_64
cp311-macosx_universal2
cp311-macosx_arm64 | cp311-win_amd64
cp311-win32
cp311-win_arm64 | cp311-manylinux_x86_64
cp311-manylinux_i686
cp311-musllinux_x86_64
cp311-musllinux_i686 | cp311-manylinux_aarch64
cp311-manylinux_ppc64le
cp311-manylinux_s390x
cp311-manylinux_armv7l
cp311-manylinux_riscv64
cp311-musllinux_aarch64
cp311-musllinux_ppc64le
cp311-musllinux_s390x
cp311-musllinux_armv7l
cp311-musllinux_riscv64 | | +| Python 3.12 | cp312-macosx_x86_64
cp312-macosx_universal2
cp312-macosx_arm64 | cp312-win_amd64
cp312-win32
cp312-win_arm64 | cp312-manylinux_x86_64
cp312-manylinux_i686
cp312-musllinux_x86_64
cp312-musllinux_i686 | cp312-manylinux_aarch64
cp312-manylinux_ppc64le
cp312-manylinux_s390x
cp312-manylinux_armv7l
cp312-manylinux_riscv64
cp312-musllinux_aarch64
cp312-musllinux_ppc64le
cp312-musllinux_s390x
cp312-musllinux_armv7l
cp312-musllinux_riscv64 | | +| Python 3.13 | cp313-macosx_x86_64
cp313-macosx_universal2
cp313-macosx_arm64 | cp313-win_amd64
cp313-win32
cp313-win_arm64 | cp313-manylinux_x86_64
cp313-manylinux_i686
cp313-musllinux_x86_64
cp313-musllinux_i686 | cp313-manylinux_aarch64
cp313-manylinux_ppc64le
cp313-manylinux_s390x
cp313-manylinux_armv7l
cp313-manylinux_riscv64
cp313-musllinux_aarch64
cp313-musllinux_ppc64le
cp313-musllinux_s390x
cp313-musllinux_armv7l
cp313-musllinux_riscv64 | cp313-ios_arm64_iphoneos
cp313-ios_arm64_iphonesimulator
cp313-ios_x86_64_iphonesimulator | +| PyPy3.8 v7.3 | pp38-macosx_x86_64
pp38-macosx_arm64 | pp38-win_amd64 | pp38-manylinux_x86_64
pp38-manylinux_i686 | pp38-manylinux_aarch64 | | +| PyPy3.9 v7.3 | pp39-macosx_x86_64
pp39-macosx_arm64 | pp39-win_amd64 | pp39-manylinux_x86_64
pp39-manylinux_i686 | pp39-manylinux_aarch64 | | +| PyPy3.10 v7.3 | pp310-macosx_x86_64
pp310-macosx_arm64 | pp310-win_amd64 | pp310-manylinux_x86_64
pp310-manylinux_i686 | pp310-manylinux_aarch64 | | +| PyPy3.11 v7.3 | pp311-macosx_x86_64
pp311-macosx_arm64 | pp311-win_amd64 | pp311-manylinux_x86_64
pp311-manylinux_i686 | pp311-manylinux_aarch64 | | The list of supported and currently selected build identifiers can also be retrieved by passing the `--print-build-identifiers` flag to cibuildwheel. The format is `python_tag-platform_tag`, with tags similar to those in [PEP 425](https://www.python.org/dev/peps/pep-0425/#details). Windows arm64 platform support is experimental. +Linux riscv64 platform support is experimental and requires an explicit opt-in through [CIBW_ENABLE](#enable). For an experimental WebAssembly build with `--platform pyodide`, `cp312-pyodide_wasm32` is the only platform identifier. @@ -178,7 +179,7 @@ On Windows, this option can be used to [compile for `ARM64` from an Intel machin Options: -- Linux: `x86_64` `i686` `aarch64` `ppc64le` `s390x` `armv7l` +- Linux: `x86_64` `i686` `aarch64` `ppc64le` `s390x` `armv7l` `riscv64` - macOS: `x86_64` `arm64` `universal2` - Windows: `AMD64` `x86` `ARM64` - Pyodide: `wasm32` @@ -191,6 +192,8 @@ Options: to use [CIBW_BUILD](#build-skip) with this option to target specific architectures via build selectors. +Linux riscv64 platform support is experimental and requires an explicit opt-in through [CIBW_ENABLE](#enable). + Default: `auto` | Runner | `native` | `auto` | `auto64` | `auto32` | @@ -317,6 +320,9 @@ values are: The build identifiers for those variants have a `t` suffix in their `python_tag` (e.g. `cp313t-manylinux_x86_64`). - `pypy`: Enable PyPy. +- `cpython-experimental-riscv64`: Enable experimental riscv64 builds. Those builds + are disabled by default as they can't be uploaded to PyPI and a PEP will most likely + be required before this can happen. !!! caution @@ -972,6 +978,7 @@ The available options are: | CIBW_MANYLINUX_PPC64LE_IMAGE | [`manylinux_2_28`](https://quay.io/pypa/manylinux_2_28_ppc64le) | | CIBW_MANYLINUX_S390X_IMAGE | [`manylinux_2_28`](https://quay.io/pypa/manylinux_2_28_s390x) | | CIBW_MANYLINUX_ARMV7L_IMAGE | [`manylinux_2_31`](https://quay.io/pypa/manylinux_2_31_armv7l) | +| CIBW_MANYLINUX_RISCV64_IMAGE | No default | | CIBW_MANYLINUX_PYPY_AARCH64_IMAGE | [`manylinux_2_28`](https://quay.io/pypa/manylinux_2_28_aarch64) | | CIBW_MANYLINUX_PYPY_I686_IMAGE | [`manylinux2014`](https://quay.io/pypa/manylinux2014_i686) | | CIBW_MUSLLINUX_X86_64_IMAGE | [`musllinux_1_2`](https://quay.io/pypa/musllinux_1_2_x86_64) | @@ -980,6 +987,7 @@ The available options are: | CIBW_MUSLLINUX_PPC64LE_IMAGE | [`musllinux_1_2`](https://quay.io/pypa/musllinux_1_2_ppc64le) | | CIBW_MUSLLINUX_S390X_IMAGE | [`musllinux_1_2`](https://quay.io/pypa/musllinux_1_2_s390x) | | CIBW_MUSLLINUX_ARMV7L_IMAGE | [`musllinux_1_2`](https://quay.io/pypa/musllinux_1_2_armv7l) | +| CIBW_MUSLLINUX_RISCV64_IMAGE | No default | Set the Docker image to be used for building [manylinux / musllinux](https://github.com/pypa/manylinux) wheels. diff --git a/test/test_emulation.py b/test/test_emulation.py index 4bdc0a31..0d218b00 100644 --- a/test/test_emulation.py +++ b/test/test_emulation.py @@ -34,14 +34,21 @@ def test(tmp_path, request): "CIBW_TEST_REQUIRES": "pytest", "CIBW_TEST_COMMAND": "pytest ./test", "CIBW_ARCHS": archs, + # TODO remove me once proper support is added + "CIBW_MANYLINUX_RISCV64_IMAGE": "ghcr.io/mayeut/manylinux_2_31:2025.03.02-1", + "CIBW_SKIP": "*-musllinux_riscv64", }, ) # also check that we got the right wheels - expected_wheels = itertools.chain.from_iterable( - utils.expected_wheels("spam", "0.1.0", machine_arch=arch, single_arch=True) - for arch in archs.split(" ") + expected_wheels = list( + itertools.chain.from_iterable( + utils.expected_wheels("spam", "0.1.0", machine_arch=arch, single_arch=True) + for arch in archs.split(" ") + ) ) + # TODO remove me once proper support is added + expected_wheels = [wheel for wheel in expected_wheels if "musllinux_1_2_riscv64" not in wheel] assert set(actual_wheels) == set(expected_wheels) diff --git a/test/utils.py b/test/utils.py index b3d2b172..e05d3a2d 100644 --- a/test/utils.py +++ b/test/utils.py @@ -227,6 +227,7 @@ def _expected_wheels( "armv7l": ["manylinux_2_17", "manylinux2014", "manylinux_2_31"], "i686": ["manylinux_2_5", "manylinux1", "manylinux_2_17", "manylinux2014"], "x86_64": ["manylinux_2_5", "manylinux1", "manylinux_2_28"], + "riscv64": ["manylinux_2_31"], }.get(machine_arch, ["manylinux_2_17", "manylinux2014", "manylinux_2_28"]) if musllinux_versions is None: diff --git a/unit_test/build_selector_test.py b/unit_test/build_selector_test.py index 992677ed..ea72bf7c 100644 --- a/unit_test/build_selector_test.py +++ b/unit_test/build_selector_test.py @@ -158,6 +158,15 @@ def test_build_free_threaded_python(): assert build_selector("cp313t-manylinux_x86_64") +def test_build_riscv64_enable(): + build_selector = BuildSelector(build_config="*", skip_config="") + assert not build_selector("cp313-manylinux_riscv64") + build_selector = BuildSelector( + build_config="*", skip_config="", enable=frozenset([EnableGroup.CPythonExperimentalRiscV64]) + ) + assert build_selector("cp313-manylinux_riscv64") + + def test_testing_selector(): # local import to avoid pytest trying to collect this as a test class! from cibuildwheel.selector import TestSelector diff --git a/unit_test/main_tests/main_platform_test.py b/unit_test/main_tests/main_platform_test.py index 7ccfab6b..08420736 100644 --- a/unit_test/main_tests/main_platform_test.py +++ b/unit_test/main_tests/main_platform_test.py @@ -179,6 +179,7 @@ def test_archs_platform_all(platform, intercepted_build_args, monkeypatch): Architecture.ppc64le, Architecture.s390x, Architecture.armv7l, + Architecture.riscv64, } elif platform == "windows": assert options.globals.architectures == { diff --git a/unit_test/oci_container_test.py b/unit_test/oci_container_test.py index 24466023..c6ea3b64 100644 --- a/unit_test/oci_container_test.py +++ b/unit_test/oci_container_test.py @@ -552,7 +552,7 @@ def test_local_image( # both GHA & local macOS arm64 podman desktop are failing pytest.xfail("podman fails with armv7l images") - remote_image = "debian:12-slim" + remote_image = "debian:trixie-slim" platform_name = platform.value.replace("/", "_") local_image = f"cibw_{container_engine.name}_{platform_name}_local:latest" dockerfile = tmp_path / "Dockerfile" @@ -582,7 +582,7 @@ def test_multiarch_image(container_engine, platform): # both GHA & local macOS arm64 podman desktop are failing pytest.xfail("podman fails with armv7l images") with OCIContainer( - engine=container_engine, image="debian:12-slim", oci_platform=platform + engine=container_engine, image="debian:trixie-slim", oci_platform=platform ) as container: output = container.call(["uname", "-m"], capture_output=True) output_map_kernel = { @@ -591,6 +591,7 @@ def test_multiarch_image(container_engine, platform): OCIPlatform.ARMV7: ("armv7l", "armv8l"), OCIPlatform.ARM64: ("aarch64",), OCIPlatform.PPC64LE: ("ppc64le",), + OCIPlatform.RISCV64: ("riscv64",), OCIPlatform.S390X: ("s390x",), } assert output.strip() in output_map_kernel[platform] @@ -601,6 +602,7 @@ def test_multiarch_image(container_engine, platform): OCIPlatform.ARMV7: "armhf", OCIPlatform.ARM64: "arm64", OCIPlatform.PPC64LE: "ppc64el", + OCIPlatform.RISCV64: "riscv64", OCIPlatform.S390X: "s390x", } assert output_map_dpkg[platform] == output.strip()