From 8c3035c3bdcf353f8cb1a85c3a33cad6eee3856f Mon Sep 17 00:00:00 2001 From: Bruno Verachten Date: Tue, 8 Sep 2026 21:52:09 +0200 Subject: [PATCH] ci: add riscv64 manylinux wheels on native runners riscv64 is the last mainstream Linux architecture without cffi wheels on PyPI, so anything downstream of it has to compile from sdist. That bites hardest in the maturin/Rust-to-Python toolchain, where cffi and patchelf are the two remaining source builds. The matrix entries follow the x86_64/aarch64 shape rather than the s390x/ppc64le one: no test_args trimming and gated on skip_ci_redundant_jobs instead of skip_slow_jobs, because these run on real hardware and are not slow. Note that anything gated on skip_slow_jobs never runs on a pull_request or push at all, since ci.yaml sets that variable true for both events and dynamatrix drops the entry. Two riscv64-specific wrinkles in the linux job: - docker/setup-qemu-action is skipped, since the host is already riscv64 and there is nothing to emulate. - actions/setup-python publishes no riscv64 builds, so cibuildwheel is driven by an interpreter that uv fetches instead. The alternative, apt-installing a system python, ties the tool interpreter to whatever the runner image ships. manylinux_2_39 is the first manylinux spec with riscv64 images, hence the differing default for CIBW_MANYLINUX_RISCV64_IMAGE. The runner label ubuntu-24.04-riscv comes from the RISE runners GitHub App (https://github.com/apps/rise-risc-v-runners), which the organisation would need installed before these jobs can pick up a machine. Builds on the riscv64 matrix entries proposed by @justeph in python-cffi/cffi#227. Signed-off-by: Bruno Verachten --- .github/workflows/ci.yaml | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 78944d4f..e6434de5 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -143,9 +143,20 @@ jobs: - { spec: cp315-manylinux_s390x, arch: s390x, test_args: '{package}/src/c', omit: ${{ env.skip_slow_jobs }} } - { spec: cp315t-manylinux_s390x, arch: s390x, test_args: '{package}/src/c', omit: ${{ env.skip_slow_jobs }} } + # riscv64 manylinux (native runners, so no need to trim the test suite + # or gate these behind skip_slow_jobs the way the emulated arches are) + - { spec: cp310-manylinux_riscv64, arch: riscv64, omit: ${{ env.skip_ci_redundant_jobs }} } + - { spec: cp311-manylinux_riscv64, arch: riscv64, omit: ${{ env.skip_ci_redundant_jobs }} } + - { spec: cp312-manylinux_riscv64, arch: riscv64, omit: ${{ env.skip_ci_redundant_jobs }} } + - { spec: cp313-manylinux_riscv64, arch: riscv64, omit: ${{ env.skip_ci_redundant_jobs }} } + - { spec: cp314-manylinux_riscv64, arch: riscv64, omit: ${{ env.skip_ci_redundant_jobs }} } + - { spec: cp314t-manylinux_riscv64, arch: riscv64, omit: ${{ env.skip_ci_redundant_jobs }} } + - { spec: cp315-manylinux_riscv64, arch: riscv64 } + - { spec: cp315t-manylinux_riscv64, arch: riscv64 } + linux: needs: [python_sdist, make_linux_matrix] - runs-on: ${{ (matrix.arch == 'aarch64') && 'ubuntu-24.04-arm' || 'ubuntu-24.04' }} + runs-on: ${{ (matrix.arch == 'aarch64') && 'ubuntu-24.04-arm' || (matrix.arch == 'riscv64') && 'ubuntu-24.04-riscv' || 'ubuntu-24.04' }} strategy: fail-fast: false matrix: ${{ fromJSON(needs.make_linux_matrix.outputs.matrix_json) }} @@ -159,7 +170,13 @@ jobs: - name: configure docker foreign arch support uses: docker/setup-qemu-action@v4.2.0 - if: matrix.arch != 'x86_64' && matrix.arch != 'i686' && matrix.arch != 'aarch64' + if: matrix.arch != 'x86_64' && matrix.arch != 'i686' && matrix.arch != 'aarch64' && matrix.arch != 'riscv64' + + # the riscv64 runners have no preinstalled python that actions/setup-python + # can provide either, so fetch one with uv to drive cibuildwheel + - name: install uv (riscv64) + uses: astral-sh/setup-uv@v10.0.1 + if: matrix.arch == 'riscv64' - name: build/test wheels id: build @@ -184,6 +201,8 @@ jobs: CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.manylinux_img || 'manylinux2014' }} CIBW_MANYLINUX_PPC64LE_IMAGE: ${{ matrix.manylinux_img || 'manylinux2014' }} CIBW_MANYLINUX_S390X_IMAGE: ${{ matrix.manylinux_img || 'manylinux2014' }} + # manylinux_2_39 is the first manylinux spec with riscv64 images + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ matrix.manylinux_img || 'manylinux_2_39' }} CIBW_MUSLLINUX_X86_64_IMAGE: ${{ matrix.musllinux_img || 'musllinux_1_2' }} CIBW_MUSLLINUX_I686_IMAGE: ${{ matrix.musllinux_img || 'musllinux_1_2' }} CIBW_MUSLLINUX_AARCH64_IMAGE: ${{ matrix.musllinux_img || 'musllinux_1_2' }} @@ -195,10 +214,14 @@ jobs: mkdir cffi tar zxf ${{ steps.fetch_sdist.outputs.download-path }}/cffi*.tar.gz --strip-components=1 -C cffi - python -m pip install --upgrade "${{ matrix.cibw_version || 'cibuildwheel' }}" # actually build libffi + wheel (using env tweaks above) - python -m cibuildwheel --output-dir dist ./cffi + if [ "${{ matrix.arch }}" = "riscv64" ]; then + uvx --python 3.14 "${{ matrix.cibw_version || 'cibuildwheel' }}" --output-dir dist ./cffi + else + python -m pip install --upgrade "${{ matrix.cibw_version || 'cibuildwheel' }}" + python -m cibuildwheel --output-dir dist ./cffi + fi echo "artifact_name=$(ls ./dist/)" >> "$GITHUB_OUTPUT"