Skip to content
Merged
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
153 changes: 153 additions & 0 deletions .github/workflows/build-gpiod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
name: Build gpiod wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'gpiod (Python bindings) version/tag to build, e.g. 2.5.0'
required: true
default: '2.5.0'
libgpiod_version:
description: 'libgpiod C library source version to vendor (LIBGPIOD_VERSION)'
required: true
default: '2.3'
pull_request:
paths:
- '.github/workflows/build-gpiod.yml'

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

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

env:
GPIOD_VERSION: ${{ inputs.version || '2.5.0' }}
LIBGPIOD_VERSION: ${{ inputs.libgpiod_version || '2.3' }}
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

python_sdist:
needs: [setup]
# Upstream's own generate_pypi_artifacts.sh builds the sdist with
# LIBGPIOD_VERSION set, then feeds *that* sdist to cibuildwheel. Doing the
# same matters: setup.py's fetch_tarball wrapper only skips its
# post-build cleanup (which deletes LICENSE/lib/include again) when
# libgpiod-version.txt is already present and matches -- true for a wheel
# built from this sdist, false for a wheel built straight from a checkout.
runs-on: ubuntu-24.04-riscv
outputs:
sdist_artifact_name: ${{ steps.build_sdist.outputs.sdist_artifact_name }}
package_version: ${{ steps.build_sdist.outputs.package_version }}
steps:
# The Python bindings live in git.kernel.org/libgpiod, tagged
# python-v<version>; that tag isn't mirrored to github.com/brgl/libgpiod,
# so actions/checkout can't reach it.
- name: Checkout gpiod python-v${{ env.GPIOD_VERSION }}
run: |
git clone --depth 1 --branch "python-v${{ env.GPIOD_VERSION }}" \
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git gpiod-src

- name: setup uv
uses: astral-sh/setup-uv@20cfd1bf945f4377ade1205e4dbc17946fc9a30d # v10.0.1
with:
python-version: '3.12'
activate-environment: true
enable-cache: false

- name: build sdist
id: build_sdist
working-directory: gpiod-src/bindings/python
env:
LIBGPIOD_VERSION: ${{ env.LIBGPIOD_VERSION }}
run: |
rm -rf dist/
uv pip install build packaging
python -m build --sdist

echo "sdist_artifact_name=$(ls ./dist)" >> "$GITHUB_OUTPUT"
echo "package_version=$(ls ./dist | sed -En 's/gpiod-(.+)\.tar\.gz/\1/p')" >> "$GITHUB_OUTPUT"

- name: upload sdist artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ steps.build_sdist.outputs.sdist_artifact_name }}
path: gpiod-src/bindings/python/dist/${{ steps.build_sdist.outputs.sdist_artifact_name }}
if-no-files-found: error

build_wheels:
needs: [setup, python_sdist]
name: Build gpiod ${{ inputs.version || '2.5.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: fetch sdist artifact
id: fetch_sdist
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: ${{ needs.python_sdist.outputs.sdist_artifact_name }}

- name: Build wheels
uses: pypa/cibuildwheel@1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
with:
# cibuildwheel accepts an sdist tarball directly and extracts it.
package-dir: ${{ steps.fetch_sdist.outputs.download-path }}/${{ needs.python_sdist.outputs.sdist_artifact_name }}
output-dir: wheelhouse/
env:
CIBW_ARCHS: riscv64
CIBW_BUILD: ${{ matrix.python }}-${{ matrix.libc }}_riscv64
CIBW_MANYLINUX_RISCV64_IMAGE: ${{ env.MANYLINUX_RISCV64_IMAGE }}
CIBW_MUSLLINUX_RISCV64_IMAGE: ${{ env.MUSLLINUX_RISCV64_IMAGE }}
# lib/uapi/gpio.h pulls in the system linux/const.h,linux/ioctl.h,
# linux/types.h; musllinux's Alpine base needs linux-headers for
# those, manylinux already has them via glibc-devel.
CIBW_BEFORE_ALL_LINUX: (command -v apk && apk add linux-headers) || true
# Upstream's own generate_pypi_artifacts.sh builds wheels with no test
# step at all: the real test suite needs a gpio-sim kernel module and
# the separately-built libgpiosim helper library (tests/gpiosim/,
# tests/system/), neither available in the build container. Exercise
# the compiled extension and the real chip-open/ioctl error path instead.
CIBW_TEST_COMMAND: |
python3 - <<'PYEOF'
import gpiod
from gpiod import _ext
assert _ext.__file__.endswith(".so"), _ext.__file__
assert gpiod.__version__ == "${{ env.GPIOD_VERSION }}", gpiod.__version__
assert gpiod.api_version == "${{ env.LIBGPIOD_VERSION }}", gpiod.api_version
try:
gpiod.Chip("/dev/null")
except OSError:
pass
else:
raise SystemExit("expected OSError for a non-gpiochip device")
PYEOF

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

publish:
name: Publish gpiod ${{ inputs.version || '2.5.0' }}
needs: [setup, build_wheels]
permissions:
contents: write
pull-requests: write
uses: $/.github/workflows/_publish-wheel.yml
with:
artifact-pattern: gpiod-${{ inputs.version || '2.5.0' }}-*riscv64
Loading