Skip to content

pymupdf: add build-pymupdf.yml for riscv64 wheels - #341

Merged
luhenry merged 2 commits into
mainfrom
pymupdf
Aug 25, 2026
Merged

luhenry merged 2 commits into
mainfrom
pymupdf

Conversation

@luhenry

@luhenry luhenry commented Aug 25, 2026

Copy link
Copy Markdown
Member

Adds a riscv64 wheel build for pymupdf 1.28.2.

Shape

build-from-checkout + pypa/cibuildwheel. PyMuPDF's PEP-517 backend (pipcl,
in-tree setup.py) downloads the matching MuPDF source tarball at build time,
builds all of MuPDF (incl. tesseract/leptonica), generates MuPDF's C++ bindings
by parsing its headers with libclang, wraps them with SWIG, and finally compiles
PyMuPDF's own _extra extension — so the wheel job is one long native build.

riscv64-specific overrides

  • PYMUPDF_SETUP_LIBCLANG=clang — setup.py's
    get_requires_for_build_wheel() asks for the libclang PyPI wheel, which
    ships no riscv64 build (and its sdist just repackages prebuilt binaries).
    Instead we install the pure-Python clang bindings and let clang.cindex
    dlopen the image's own libclang.so — hence dnf install -y clang-devel in
    CIBW_BEFORE_ALL_LINUX (clang-libs alone has only the versioned soname).
  • PYMUPDF_SETUP_SWIG=swig — reuse the manylinux image's swig 4.4.1 instead of
    compiling the swig sdist in-container.
  • XCFLAGS/XCXXFLAGS=-D__LITTLE_ENDIAN__ — mupdf's
    scripts/tesseract/endianness.h detects byte order purely from
    arch-specific predefines (__AARCH64EL__, _M_X64, …) and has no riscv64
    case, so it hard-errors with #error "I don't know what architecture this is!". Verified locally in the manylinux riscv64 image.

Matrix

Upstream publishes exactly two Linux wheel shapes: cp310-abi3 and
cp314-cp314t. cp312 is our floor, so the abi3 wheel is built there;
the free-threaded build sets PYMUPDF_SETUP_PY_LIMITED_API=0 because pipcl
asserts Py_LIMITED_API and Py_GIL_DISABLED cannot be combined.

Tests

Upstream's own harness (tests/run_compound.py … pytest tests) with its test
deps, restricted to -i r (the default implementation) — the default rR
reruns the whole suite a second time with PYMUPDF_USE_EXTRA=0.
test_flake8 / test_pylint / test_codespell are ignored: they lint the
source tree rather than exercise the wheel, and track whatever linter version
pip resolves today.

luhenry and others added 2 commits August 25, 2026 12:21
PyMuPDF builds MuPDF from source (downloaded at build time), generates
MuPDF's C++ bindings with libclang and wraps them with SWIG, so the riscv64
port needs three overrides:

* PYMUPDF_SETUP_LIBCLANG=clang - the default `libclang` PyPI wheel has no
  riscv64 build; use the pure-Python `clang` bindings against the image's
  own libclang.so (dnf clang-devel).
* PYMUPDF_SETUP_SWIG=swig - reuse the manylinux image's swig 4.4.1 rather
  than building the `swig` sdist in-container.
* XCFLAGS/XCXXFLAGS=-D__LITTLE_ENDIAN__ - mupdf's tesseract endianness.h
  detects endianness from arch-specific predefines and has no riscv64 case,
  so it hard-errors with "I don't know what architecture this is!".

Matrix mirrors upstream's two wheel shapes: one cp312-abi3 build and one
free-threaded cp314t build (pipcl refuses Py_LIMITED_API together with
Py_GIL_DISABLED).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@luhenry
luhenry merged commit 853acc6 into main Aug 25, 2026
6 checks passed
@luhenry
luhenry deleted the pymupdf branch August 25, 2026 12:35
@luhenry luhenry linked an issue Aug 25, 2026 that may be closed by this pull request
luhenry added a commit that referenced this pull request Sep 28, 2026
CI (run 36351368476) had 28 identical test failures on Python 3.13,
3.14 and 3.14t while 3.12 passed clean. All 28 assert that pystack can
classify a native frame from a *target* process's own unwind as the
CPython eval loop or GC collector; on riscv64 that classification never
succeeds once the target interpreter is 3.13+, matching gotcha 33/169's
"identical failures on newer interpreters, clean on older" shape one
level removed (it's the target being inspected, not the one running
pytest). pystack itself only ships a signal-frame unwind fix for
AArch64 (elfutils-aarch64-signal-frame.patch, bloomberg/pystack
#341/#348) with no riscv64 equivalent, so this is a documented
per-arch native-unwind gap, not a defect in the wheel under test.

Deselect only the affected tests, generated once per matrix entry from
matrix.python_version so 3.12 keeps running the full suite unchanged.
See gotcha 597 (skills/python-project-porting).
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.

pymupdf riscv64 support

1 participant