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
142 changes: 142 additions & 0 deletions .github/workflows/build-gevent.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# SPDX-FileCopyrightText: 2026 The RISE Project
# SPDX-License-Identifier: MIT
---
# This workflow is based on the `manylinux` job of
# https://github.com/gevent/gevent/blob/26.8.0/.github/workflows/ci.yml and the
# scripts/releases/make-manylinux script it runs.
name: Build gevent wheels (riscv64)

on:
workflow_dispatch:
inputs:
version:
description: 'gevent version to build (git tag, e.g. 26.8.0)'
required: true
default: '26.8.0'
pull_request:
paths:
- '.github/workflows/build-gevent.yml'

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

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

env:
GEVENT_VERSION: ${{ inputs.version || '26.8.0' }}
MANYLINUX_RISCV64_IMAGE: quay.io/pypa/manylinux_2_39_riscv64

jobs:
build_wheels:
name: Build gevent ${{ inputs.version || '26.8.0' }} ${{ matrix.python }}-manylinux_riscv64
runs-on: ubuntu-24.04-riscv
strategy:
fail-fast: false
matrix:
python:
# make-manylinux skips free-threaded builds: "The GIL is required".
- "cp312"
- "cp313"
- "cp314"

steps:
- name: Checkout gevent ${{ env.GEVENT_VERSION }}
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
repository: gevent/gevent
ref: ${{ env.GEVENT_VERSION }}
persist-credentials: false

- name: Checkout python-wheels
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
path: python-wheels
persist-credentials: false

# The wheel statically compiles libev, libuv and c-ares but ships only gevent's
# own LICENSE.
- name: Patch gevent source
run: |
git apply python-wheels/patches/gevent/${{ env.GEVENT_VERSION }}/00*.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_BEFORE_ALL_LINUX: yum -y install libffi-devel
# As in make-manylinux: NO_CYTHON_COMPILE keeps Cython, which has no riscv64
# binary wheel, from compiling its own accelerators here; TRAVIS is how it tells
# setup.py it is on CI, which makes the c-ares extension required, not optional.
CIBW_ENVIRONMENT: >-
NO_CYTHON_COMPILE=true
CI=1
TRAVIS=true
PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/
CIBW_TEST_EXTRAS: test
# The monkey-patched stdlib tests live in src/greentest and are found by climbing
# to setup.py, so both have to be staged or the runner just warns and skips them
# (17 of 86 test commands). src/gevent stays out so the wheel is what is imported.
CIBW_TEST_SOURCES: setup.py src/greentest examples
# GEVENT_MANYLINUX is test-only: during the build it makes setup.py assume
# c-ares was already configured by a separate step, which we don't have.
CIBW_TEST_ENVIRONMENT: >-
GEVENT_MANYLINUX=1
GEVENT_MANYLINUX_NAME=manylinux_2_39_riscv64
GEVENT_LOOP=libev-cext
GEVENTTEST_USE_RESOURCES=-network
PYTHONHASHSEED=8675309
CIBW_TEST_COMMAND: >-
python -c "import gevent; print(gevent, gevent.__version__)" &&
python -c "import gevent.core; print('default loop', gevent.core.loop)" &&
GEVENT_LOOP=libuv python -c "import gevent.core; print('libuv loop', gevent.core.loop)" &&
GEVENT_LOOP=libev-cffi python -c "import gevent.core; print('libev-cffi loop', gevent.core.loop)" &&
python -c "import gevent.ares; print('ares', gevent.ares)" &&
python -c "import importlib.metadata as m; f=[str(p) for p in m.files('gevent')]; missing=[n for n in ('licenses/LICENSE','licenses/NOTICE','licenses/deps/c-ares/LICENSE.md','licenses/deps/libev/LICENSE','licenses/deps/libuv/LICENSE','licenses/deps/libuv/LICENSE-extra') if not any(s.endswith(n) for s in f)]; assert not missing, missing" &&
python -m gevent.tests --second-chance

- name: Check the compiled extensions made it into the wheel
run: |
python3 - wheelhouse/*.whl <<'EOF'
import sys, zipfile
# gevent.resolver.cares is declared optional unless setup.py detects it is
# running on CI from a checkout, so a failed build silently drops it.
expected = (
'gevent/libev/corecext', 'gevent/libev/_corecffi',
'gevent/libuv/_corecffi', 'gevent/resolver/cares',
'gevent/_gevent_cgreenlet', 'gevent/_gevent_cqueue',
)
for whl in sys.argv[1:]:
sos = [n for n in zipfile.ZipFile(whl).namelist() if n.endswith('.so')]
missing = [e for e in expected if not any(n.startswith(e) for n in sos)]
assert not missing, (whl, missing, sos)
print(whl, len(sos), 'extension modules ok')
EOF

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

publish:
name: Publish gevent ${{ inputs.version || '26.8.0' }} to GitLab
needs: [build_wheels]
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write

steps:
- name: Publish wheels and open docs PR
uses: riseproject-dev/python-wheels/actions/publish-wheels@main
with:
artifact-pattern: gevent-${{ env.GEVENT_VERSION }}-*-manylinux_riscv64
gitlab-username: ${{ vars.GITLAB_DEPLOY_USER }}
gitlab-token: ${{ secrets.GITLAB_DEPLOY_TOKEN }}
gitlab-project-id: ${{ vars.GITLAB_PROJECT_ID }}
gh-token: ${{ secrets.GITHUB_TOKEN }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
From c85027ca757d661635d7c02f1b60e73eb9b19187 Mon Sep 17 00:00:00 2001
From: Ludovic Henry <git@ludovic.dev>
Date: Wed, 26 Aug 2026 13:24:02 +0200
Subject: [PATCH] package the licences of the embedded libev, libuv and c-ares

Upstream-Status: To upstream [not yet submitted; the same gap exists in every gevent wheel on PyPI, so this needs a maintainer discussion rather than a drive-by PR]

The wheels statically compile the bundled deps/libev, deps/libuv and
deps/c-ares sources into gevent.libev.corecext, gevent.libev._corecffi,
gevent.libuv._corecffi and gevent.resolver.cares. libev is BSD 2-clause
(or GPL 2+), libuv and c-ares are MIT; all three require the copyright
notice to travel with binary redistributions, but setup.py names only
'LICENSE' in license_files, so the wheel ships gevent's own licence alone.

The vendored c-ares tree carries no licence file at all -- the notice
appears only in the per-file headers -- so restore LICENSE.md from the
vendored release (c-ares 1.34.5).

NOTICE is added for the same reason: it carries the PSF licence covering
the stdlib test files copied under gevent/tests and the guv copyright of
gevent/libuv/_corecffi_*.c, both of which do ship in the wheel.

Signed-off-by: Ludovic Henry <git@ludovic.dev>
---
deps/c-ares/LICENSE.md | 24 ++++++++++++++++++++++++
setup.py | 7 +++++++
2 files changed, 31 insertions(+)
create mode 100644 deps/c-ares/LICENSE.md

diff --git a/deps/c-ares/LICENSE.md b/deps/c-ares/LICENSE.md
new file mode 100644
index 0000000..910ddde
--- /dev/null
+++ b/deps/c-ares/LICENSE.md
@@ -0,0 +1,24 @@
+MIT License
+
+Copyright (c) 1998 Massachusetts Institute of Technology
+Copyright (c) 2007 - 2023 Daniel Stenberg with many contributors, see AUTHORS
+file.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice (including the next
+paragraph) shall be included in all copies or substantial portions of the
+Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/setup.py b/setup.py
index 878a360..22ef420 100755
--- a/setup.py
+++ b/setup.py
@@ -349,6 +349,13 @@ def run_setup(ext_modules):
license='MIT', # pep 639, use SPDX license identifiers
license_files=[
'LICENSE',
+ 'NOTICE',
+ # Embedded and statically linked into the extension modules; their
+ # BSD/MIT terms require the copyright notice to ship with the binary.
+ 'deps/c-ares/LICENSE.md',
+ 'deps/libev/LICENSE',
+ 'deps/libuv/LICENSE',
+ 'deps/libuv/LICENSE-extra',
],
project_urls={
'Bug Tracker': 'https://github.com/gevent/gevent/issues',
Loading