Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions .github/workflows/build-zlib-ng.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# Based on upstream's own deploy job:
# https://github.com/pycompression/python-zlib-ng/blob/v1.0.0/.github/workflows/ci.yml
name: Build zlib-ng wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'zlib-ng version to build (git tag without the leading v, e.g. 1.0.0)'
required: true
default: '1.0.0'
pull_request:
paths:
- '.github/workflows/build-zlib-ng.yml'

concurrency:
group: ${{ github.workflow }}-${{ inputs.version || '1.0.0' }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true

permissions:
contents: read # to fetch code (actions/checkout)

env:
# `inputs.version` is empty on pull_request events; default to 1.0.0 there.
ZLIB_NG_VERSION: ${{ inputs.version || '1.0.0' }}
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64
MUSLLINUX_RISCV64_IMAGE: quay.io/pypa/musllinux_1_2_riscv64

jobs:
setup:
uses: $/.github/workflows/_setup.yml

build_wheels:
needs: [setup]
name: Build zlib-ng ${{ inputs.version || '1.0.0' }} ${{ matrix.python }}-${{ matrix.libc }}_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
python: ["cp312", "cp313", "cp314", "cp314t"]
libc: [manylinux, musllinux]

steps:
- name: Checkout zlib-ng v${{ env.ZLIB_NG_VERSION }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: pycompression/python-zlib-ng
ref: v${{ env.ZLIB_NG_VERSION }}
submodules: recursive
persist-credentials: false

- name: Checkout python-wheels
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
path: python-wheels
persist-credentials: false

- name: Patch zlib-ng source
run: git apply python-wheels/patches/zlib-ng/${{ env.ZLIB_NG_VERSION }}/00*.patch

- name: Build wheels
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
output-dir: wheelhouse/
env:
CIBW_BUILD: ${{ matrix.python }}-${{ matrix.libc }}_riscv64
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
CIBW_MUSLLINUX_RISCV64_IMAGE: ${{ env.MUSLLINUX_RISCV64_IMAGE }}
CIBW_ENVIRONMENT: CFLAGS="-O3 -DNDEBUG"
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: >-
pytest {project}/tests/test_zlib_compliance.py
{project}/tests/test_gzip_compliance.py
{project}/tests/test_gzip_ng.py

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: zlib-ng-${{ env.ZLIB_NG_VERSION }}-${{ matrix.python }}-${{ matrix.libc }}_riscv64
path: wheelhouse/*.whl
if-no-files-found: error

publish:
name: Publish zlib-ng ${{ inputs.version || '1.0.0' }}
needs: [setup, build_wheels]
permissions:
contents: write
pull-requests: write
uses: $/.github/workflows/_publish-wheel.yml
with:
artifact-pattern: zlib-ng-${{ inputs.version || '1.0.0' }}-*riscv64
65 changes: 65 additions & 0 deletions patches/zlib-ng/1.0.0/0001-setup-disable-RVV-on-riscv64.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Sun, 6 Sep 2026 14:10:34 +0200
Subject: [PATCH] setup: disable RVV on riscv64
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

zlib-ng's riscv_check_features() runtime-detects the V extension via
getauxval(AT_HWCAP), and when it believes V is present it executes an
inline vsetvli/csrr probe to confirm vector length and tail/mask-agnostic
support before turning on the RVV-accelerated deflate/inflate paths
(adler32_rvv, chunkset_rvv, compare256_rvv, slide_hash_rvv).

On the riscv64 CI hardware this repo builds wheels on, that vsetvli probe
itself raises SIGILL (Illegal instruction) — the very first RVV
instruction zlib-ng's own feature check executes crashes the process,
before any deflate/inflate call is made. Every test that imports
zlib_ng (test_zlib_compliance.py, test_gzip_compliance.py,
test_gzip_ng.py) segfaults the same way at zng_deflateInit2.

setup.py's Linux build path drives zlib-ng's autoconf-style ./configure
script directly (not CMake — that path is Windows-only) and exposes no
environment-variable hook to pass extra configure flags, so the only way
to reach configure's own --without-rvv switch is to have setup.py add it
itself. Guard it on platform.machine() so non-riscv builds (and riscv
hardware where this is eventually fixed/verified) are unaffected.

This falls back zlib-ng to its portable C RVV-free code paths, still
much faster than not shipping zlib-ng-accelerated zlib/gzip at all.

Upstream-Status: Inappropriate [riscv64 CI-hardware-only RVV runtime-detection SIGILL; not a defect in this project]
---
setup.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/setup.py b/setup.py
index f58cbf8..d9d3109 100644
--- a/setup.py
+++ b/setup.py
@@ -7,6 +7,7 @@

import functools
import os
+import platform
import shutil
import subprocess
import sys
@@ -108,7 +109,12 @@ def build_zlib_ng():
make_program = "gmake" if shutil.which("gmake") else "make"
subprocess.run([make_program, "libz-ng.a"], **run_args)
elif sys.platform == "linux":
- subprocess.run([os.path.join(build_dir, "configure")], **run_args)
+ configure_args = [os.path.join(build_dir, "configure")]
+ if platform.machine() in ("riscv64", "riscv32"):
+ # riscv_check_features()'s vsetvli runtime probe SIGILLs on
+ # this hardware; disable RVV rather than crash every caller.
+ configure_args.append("--without-rvv")
+ subprocess.run(configure_args, **run_args)
subprocess.run(["make", "libz-ng.a", "-j", str(cpu_count)], **run_args)
else:
subprocess.run(["cmake", build_dir], **run_args)
--
2.50.1 (Apple Git-155)