diff --git a/.github/workflows/build-parasail.yml b/.github/workflows/build-parasail.yml new file mode 100644 index 000000000000..3ec5cda9f6e6 --- /dev/null +++ b/.github/workflows/build-parasail.yml @@ -0,0 +1,114 @@ +# SPDX-FileCopyrightText: 2026 The RISE Project +# SPDX-License-Identifier: MIT +--- +# This workflow is based on: https://github.com/jeffdaily/parasail-python/blob/v1.3.4c1/.github/workflows/wheels.yml +name: Build parasail wheels (riscv64) + +on: + workflow_dispatch: + inputs: + version: + description: 'Version glob to (re)build; empty builds every version of docs/packages/parasail.yaml not released yet' + required: false + default: '' + pull_request: + branches: [main] + paths: + - '.github/workflows/build-parasail.yml' + - 'docs/packages/parasail.yaml' + - 'patches/parasail/**' + push: + branches: [main] + paths: + - '.github/workflows/build-parasail.yml' + - 'docs/packages/parasail.yaml' + - 'patches/parasail/**' + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +permissions: + contents: read # to fetch code (actions/checkout) + +env: + MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64 + +jobs: + setup: + uses: $/.github/workflows/_setup.yml + with: + package: parasail + version: ${{ inputs.version }} + + build_wheels: + needs: [setup] + if: needs.setup.outputs.versions != '[]' + name: Build parasail ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64 + runs-on: ubuntu-24.04-riscv + timeout-minutes: 60 + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + # Upstream builds one interpreter only: bdist_wheel.finalize_options() forces + # self.universal = True, so every build produces the same py2.py3-none wheel. + python: + - "cp312" + + env: + PARASAIL_VERSION: ${{ matrix.version }} + + steps: + # The 1.3.4 release was never retagged off its "c1" candidate tag. + - name: Checkout parasail-python v${{ env.PARASAIL_VERSION }}c1 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + repository: jeffdaily/parasail-python + ref: v${{ env.PARASAIL_VERSION }}c1 + persist-credentials: false + + - name: Checkout python-wheels + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + path: python-wheels + persist-credentials: false + + - name: Apply patches + run: git apply python-wheels/patches/parasail/${{ env.PARASAIL_VERSION }}/*.patch + + - name: Build wheels + uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0 + with: + output-dir: wheelhouse/ + only: ${{ matrix.python }}-manylinux_riscv64 + env: + CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }} + CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ + # setup.py fetches jeffdaily/parasail's C library from GitHub at build + # time (upstream has no version pin here either - it always builds + # against the C library's master branch, even for tagged releases). + CIBW_TEST_COMMAND: python -m unittest discover {project}/tests + + - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: parasail-${{ env.PARASAIL_VERSION }}-${{ matrix.python }}-manylinux_riscv64 + path: ./wheelhouse/*.whl + if-no-files-found: error + + publish: + name: Publish parasail ${{ matrix.version }} + needs: [setup, build_wheels] + if: needs.setup.outputs.versions != '[]' + strategy: + fail-fast: false + matrix: + version: ${{ fromJSON(needs.setup.outputs.versions) }} + permissions: + contents: write + pull-requests: write + uses: $/.github/workflows/_publish-wheel.yml + secrets: + app-private-key: ${{ secrets.RISEPROJECT_APP_PRIVATE_KEY }} + with: + artifact-pattern: parasail-${{ matrix.version }}-*-manylinux_riscv64 diff --git a/docs/packages/parasail.yaml b/docs/packages/parasail.yaml new file mode 100644 index 000000000000..9e0770d688ca --- /dev/null +++ b/docs/packages/parasail.yaml @@ -0,0 +1,5 @@ +package-name: parasail +source-code: https://github.com/jeffdaily/parasail-python +license: BSD-3-Clause +versions: +- version: 1.3.4 diff --git a/patches/parasail/1.3.4/0001-setup-refresh-config.guess-config.sub-for-riscv64.patch b/patches/parasail/1.3.4/0001-setup-refresh-config.guess-config.sub-for-riscv64.patch new file mode 100644 index 000000000000..263c4abb7665 --- /dev/null +++ b/patches/parasail/1.3.4/0001-setup-refresh-config.guess-config.sub-for-riscv64.patch @@ -0,0 +1,57 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Ludovic Henry +Date: Thu, 15 Oct 2026 00:00:00 +0000 +Subject: [PATCH] setup: refresh config.guess/config.sub for riscv64 + +Upstream-Status: Inappropriate [riscv64 build infra, irrelevant to jeffdaily/parasail-python] + +build_parasail() downloads a plain GitHub archive snapshot of +jeffdaily/parasail's master branch (not a `make dist` release tarball), +so it carries no generated `configure` and falls back to `autoreconf +-fi`. That only installs *missing* auxiliary files; it does not +overwrite the config.guess/config.sub already committed to the C +library's tree, and those predate riscv64 (added to config.sub in +2017), so `./configure` dies with "cannot guess build type; you must +specify one" on the riscv64 manylinux runner -- the exact shape of +CLAUDE.md gotcha 138 (libspatialite's 2009-dated pair hitting the same +wall on aarch64/riscv64). + +The manylinux_riscv64 image already carries a current automake, whose +own config.guess/config.sub do recognise riscv64 (gotcha 138's fix), so +copy those over the stale ones before configure runs. + +Signed-off-by: Ludovic Henry +--- + setup.py | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/setup.py b/setup.py +index 1111111..2222222 100644 +--- a/setup.py ++++ b/setup.py +@@ -1,4 +1,5 @@ + import codecs ++import glob + import os + import platform + import re +@@ -313,9 +314,17 @@ def build_parasail(libname): + if not os.access(os.path.join(parasail_root,'version.sh'), os.X_OK): + print("fixing executable bits after unzipping") + fix_permissions(parasail_root) + else: + print("parasail archive executable permissions ok") + ++ # gotcha 138 (manylinux-image-and-toolchain.md): the committed ++ # config.guess/config.sub predate riscv64; refresh them from automake's ++ # copy, which the manylinux image already carries. ++ for config_aux in ('config.guess', 'config.sub'): ++ found = glob.glob('/usr/share/automake-*/{}'.format(config_aux)) ++ if found: ++ shutil.copy(found[0], os.path.join(parasail_root, config_aux)) ++ + root = find_file('configure', parasail_root) + if root is None: + print("Unable to find parasail configure script") +-- +2.50.1