Skip to content

pyroaring: add build-pyroaring.yml for riscv64 wheels - #450

Merged
luhenry merged 3 commits into
mainfrom
pyroaring
Aug 26, 2026
Merged

pyroaring: add build-pyroaring.yml for riscv64 wheels#450
luhenry merged 3 commits into
mainfrom
pyroaring

Conversation

@luhenry

@luhenry luhenry commented Aug 26, 2026

Copy link
Copy Markdown
Member

pyroaring publishes per-interpreter manylinux/musllinux wheels for x86_64, aarch64 and armv7l plus macOS and Windows, but nothing for riscv64. It is a Cython extension over the CRoaring amalgamation that is bundled in the source tree (pyroaring/roaring.c, CRoaring v4.6.1), so there is no external native dependency and a plain build-from-checkout cibuildwheel job covers it.

The workflow mirrors the build_wheels job of upstream's buildwheels.yml, narrowed to manylinux_riscv64 and to cp312/cp313/cp314/cp314t. Upstream keeps no [tool.cibuildwheel] table at 1.1.0, so CIBW_TEST_REQUIRES, CIBW_TEST_COMMAND and CIBW_BUILD_FRONTEND: build are taken verbatim from its workflow env:; the only riscv64 addition is CIBW_MANYLINUX_RISCV64_IMAGE. The matrix is per-interpreter because PyPI shows separate cpXY-cpXY wheels (no -abi3- tag) and upstream ships a cp314-cp314t manylinux wheel, so free threading is supported.

Licensing

setup.py compiles the bundled pyroaring/roaring.c into a libcroaring static library that the extension links, so every wheel redistributes CRoaring in binary form. CRoaring is dual-licensed Apache-2.0/MIT and both require the copyright notice to travel with binary redistributions, but that notice lives only inside roaring.c, which ships in the sdist and not in the wheel — the published wheels carry pyroaring's own MIT LICENSE alone. patches/pyroaring/1.1.0/0001-package-the-CRoaring-licence-in-the-built-wheel.patch restores CRoaring's LICENSE verbatim from the v4.6.1 release recorded in pyroaring/croaring_version.pxi, as LICENSE.CRoaring at the project root: setuptools' default license_files glob is LICEN[CS]E* there, so no packaging change is needed and pyroaring's own LICENSE cannot be dropped by replacing the default glob with a hand-written list. Tagged To upstream — the same gap exists in every pyroaring wheel on PyPI, so it needs a maintainer discussion rather than a drive-by PR.

The test command asserts importlib.metadata.files('pyroaring') lists exactly LICENSE and LICENSE.CRoaring under dist-info/licenses/, so the patch cannot silently stop applying. Checked locally that the assertion fails against an unpatched wheel and passes against a patched one.

The one divergence: hypothesis on the free-threaded job

hypothesis became a Rust extension package in 6.156, and the only riscv64 wheels it publishes are cp310-abi3-manylinux_2_31_riscv64 and cp315-abi3.abi3t-manylinux_2_31_riscv64. The first covers cp312/cp313/cp314 fine, but neither loads on free-threaded 3.14, so the cp314t test step fell back to the sdist, whose backend computes the target triple riscv64-unknown-linux-gnu — a name rustup does not have — and died before pyroaring's own tests ran. 6.155.7 is the last release published as py3-none-any, so the cp314t matrix entry alone pins hypothesis<6.156; the GIL-ful interpreters keep resolving whatever pip picks, as upstream's workflow does.

build-hypothesis.yml landed on main in #451 and builds cp314t, so this pin should go away once those wheels are actually on pypi.riseproject.dev (the index still 302s for hypothesis today) — at that point CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/ restores upstream's unpinned line on every entry.

Results

All four matrix jobs green, publish job dry-ran the four wheels ("Dry run (not on main branch — no upload will happen)"). Each job runs upstream's exact test command: 123 pytest tests from test.py plus 226 doctests from cydoctest.py, and a unzip-equivalent check that the pyroaring...so really is in the wheel.

Local validation before pushing

  • Built the 1.1.0 checkout on macOS/arm64 with today's Cython 3.3.0 (upstream floats setup_requires=['cython>=3.0.2'] and released 1.1.0 against 3.2.x): builds clean, and all 123 tests plus cydoctest.py pass, so no version pin is warranted here.
  • Confirmed the wheel's top-level pyroaring...so wins over the checkout's pyroaring/ directory when pytest inserts the project root on sys.path — that directory has no __init__.py, so it is only a namespace portion and the installed extension is what gets imported.
  • actionlint clean apart from the usual label "ubuntu-24.04-riscv" is unknown.

pyroaring publishes per-interpreter manylinux/musllinux wheels for x86_64,
aarch64 and armv7l but none for riscv64. It is a Cython extension over the
CRoaring amalgamation bundled in the source tree, so a plain
build-from-checkout cibuildwheel job covers it; the workflow mirrors the
build_wheels job of upstream's buildwheels.yml, narrowed to
manylinux_riscv64 and to cp312/cp313/cp314/cp314t.

Upstream keeps no [tool.cibuildwheel] table, so the test requirements,
test command and `build` frontend are taken verbatim from its workflow env.

Also carry a patch adding CRoaring's own licence to the wheel: roaring.c is
compiled into the extension, and its Apache-2.0/MIT notice ships only in the
sdist. The test command asserts both licences are installed so the patch
cannot silently stop applying.
hypothesis became a Rust extension package in 6.156, and the only riscv64
wheels it publishes are cp310-abi3 and cp315-abi3.abi3t. Neither loads on
free-threaded 3.14, so the cp314t test step falls back to the sdist, whose
backend computes the target triple riscv64-unknown-linux-gnu -- a name
rustup does not have -- and fails before pyroaring's own tests run.

6.155.7 is the last release published as py3-none-any. Pin it on the
cp314t matrix entry alone so the GIL-ful interpreters keep resolving
whatever hypothesis pip picks, as upstream's workflow does.
@luhenry

luhenry commented Aug 26, 2026

Copy link
Copy Markdown
Member Author

Redo everything from scratch now that hypothesis is available at https://pypi.riseproject.dev/simple/hypothesis

@luhenry

luhenry commented Aug 26, 2026

Copy link
Copy Markdown
Member Author

Done in b7eb2a1. The include: matrix existed only to give cp314t a hypothesis<6.156 pin, so it collapses back to the standard python: ["cp312", "cp313", "cp314", "cp314t"] and CIBW_TEST_REQUIRES is plain hypothesis pytest.

Dropping the pin on its own would not have worked: this workflow had no PIP_EXTRA_INDEX_URL, so the test phase had no route to the registry and pip would have gone back to PyPI, found no cp314t riscv64 wheel and rebuilt the sdist — the same Rust/target-triple failure the pin was avoiding. So the change also adds CIBW_ENVIRONMENT: PIP_EXTRA_INDEX_URL=https://pypi.riseproject.dev/simple/, plus PIP_ONLY_BINARY=hypothesis scoped to the test phase (gotcha 12) so that if our wheel is ever missing the job fails loudly on "no matching distribution" instead of wandering into a source build.

Confirmed on the registry before pushing: hypothesis-6.165.10 is there for cp312/cp313/cp314 and cp314-cp314t, all manylinux_2_34_riscv64.manylinux_2_39_riscv64.

@luhenry
luhenry merged commit 3cb2db4 into main Aug 26, 2026
8 checks passed
@luhenry
luhenry deleted the pyroaring branch August 26, 2026 19:19
@luhenry luhenry linked an issue Aug 26, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pyroaring riscv64 support

1 participant