Skip to content
Draft
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
141 changes: 141 additions & 0 deletions .github/workflows/build-pyboolector.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
#
# This workflow is based on the PyPi_Linux_x86_64 job of upstream's own
# pypi/azure-pipelines-pypi.yml, which drives pypi/build.sh inside a manylinux
# container. No cp314t leg: pypi/build.sh resolves an interpreter at
# /opt/python/${py}-${py} (patched below to match exactly instead of globbing,
# see the patch), and the riscv64 image has no such directory for a
# free-threaded build (it lives at cp314-cp314t).
name: Build pyboolector wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'Version glob to (re)build; empty builds every version of docs/packages/pyboolector.yaml not released yet'
required: false
default: ''
pull_request:
branches: [main]
paths:
- '.github/workflows/build-pyboolector.yml'
- 'docs/packages/pyboolector.yaml'
- 'patches/pyboolector/**'
push:
branches: [main]
paths:
- '.github/workflows/build-pyboolector.yml'
- 'docs/packages/pyboolector.yaml'
- 'patches/pyboolector/**'

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: pyboolector
version: ${{ inputs.version }}

build_wheels:
needs: [setup]
if: needs.setup.outputs.versions != '[]'
name: Build pyboolector ${{ matrix.version }} ${{ matrix.python }}-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
timeout-minutes: 90
strategy:
fail-fast: false
matrix:
version: ${{ fromJSON(needs.setup.outputs.versions) }}
python:
- "cp312"
- "cp313"
- "cp314"

env:
PYBOOLECTOR_VERSION: ${{ matrix.version }}

steps:
- id: ref
run: |
echo "tag=${PYBOOLECTOR_VERSION%.*}" >> "$GITHUB_OUTPUT"
echo "build_num=${PYBOOLECTOR_VERSION##*.}" >> "$GITHUB_OUTPUT"

- name: Checkout boolector ${{ steps.ref.outputs.tag }}
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: boolector/boolector
ref: ${{ steps.ref.outputs.tag }}
path: boolector
persist-credentials: false

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

- name: Patch boolector source
working-directory: boolector
run: git apply ../python-wheels/patches/pyboolector/${{ env.PYBOOLECTOR_VERSION }}/*.patch

- name: Build wheel
run: |
# CMAKE_POLICY_VERSION_MINIMUM=3.5 (gotcha 257) works around btor2tools'
# cmake_minimum_required(VERSION 3.3): btor2tools is fetched fresh by
# boolector's own contrib/setup-btor2tools.sh inside build.sh, so its
# configure.sh's `cmake ..` call isn't a line we control to add a `-D` flag
# to; setting the floor as an env var reaches it anyway. CMake 4 (shipped in
# manylinux_2_39_riscv64) otherwise hard-fails with "Compatibility with
# CMake < 3.5 has been removed".
docker run --rm \
-e BUILD_NUM="${{ steps.ref.outputs.build_num }}" \
-e PYTHON_VERSIONS="${{ matrix.python }}" \
-e CMAKE_POLICY_VERSION_MINIMUM=3.5 \
-v "$(pwd)/boolector":/boolector \
"${{ env.MANYLINUX_RISCV64_IMAGE }}" \
/boolector/pypi/build.sh

- name: Test wheel
run: |
docker run --rm \
-v "$(pwd)/boolector":/boolector \
"${{ env.MANYLINUX_RISCV64_IMAGE }}" \
bash -c '
set -e
python=/opt/python/${{ matrix.python }}-${{ matrix.python }}/bin/python
"$python" -m pip install /boolector/result/dist/*.whl
"$python" /boolector/examples/api/python/quickstart.py
'

- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: pyboolector-${{ env.PYBOOLECTOR_VERSION }}-${{ matrix.python }}-manylinux_riscv64
path: boolector/result/dist/*.whl
if-no-files-found: error

publish:
name: Publish pyboolector ${{ 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: pyboolector-${{ matrix.version }}-*-manylinux_riscv64
6 changes: 6 additions & 0 deletions docs/packages/pyboolector.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package-name: pyboolector
source-code: https://github.com/boolector/boolector
license: MIT
versions:
- version: 3.2.4.19342042739
patched: true
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Tue, 13 Oct 2026 00:00:00 +0000
Subject: [PATCH] pypi/build.sh: match the interpreter dir exactly

pypi/build.sh resolves each requested interpreter with
`ls /opt/python/${py}-*/bin/python`, which assumed exactly one `/opt/python`
entry per short tag (`cp312-cp312`). The riscv64 manylinux image also ships a
free-threaded build alongside the regular one under a shared prefix
(`cp314-cp314` and `cp314-cp314t`), so for `py=cp314` the glob matches both
directories and `ls` returns two lines, which `python=$(...)` collapses into
one broken multi-line value and aborts the build.

Build the exact path instead of globbing: `/opt/python/${py}-${py}/bin/python`
resolves unambiguously for every tag this workflow passes (cp312, cp313,
cp314), matching how the project's own later CI runs already invoke it in
practice (observed in the pyboolector-3.2.4.19342042739 sdist on PyPI, which
carries this same fix though it was never committed to this git repository).

Upstream-Status: Inappropriate [riscv64 image splits cp314/cp314t under one shared /opt/python prefix]

Signed-off-by: Ludovic Henry <git@ludovic.dev>
---
diff --git a/pypi/build.sh b/pypi/build.sh
index 0000000..0000000 100644
--- a/pypi/build.sh
+++ b/pypi/build.sh
@@ -56,7 +56,7 @@
cd pyboolector

for py in $PYTHON_VERSIONS; do
- python=$(ls /opt/python/${py}-*/bin/python)
+ python=/opt/python/${py}-${py}/bin/python
echo "Python: ${python}"
${python} -m pip install cython wheel
cd ${BUILD_DIR}/pyboolector
Loading