Skip to content

mini-racer: add build-mini-racer.yml for riscv64 wheels - #1875

Open
luhenry wants to merge 9 commits into
mainfrom
mini-racer
Open

luhenry wants to merge 9 commits into
mainfrom
mini-racer

Conversation

@luhenry

@luhenry luhenry commented Sep 13, 2026

Copy link
Copy Markdown
Member

Builds v8 (branch-heads/14.4) from source and embeds it as a minimal Python JS engine. Upstream publishes no riscv64 wheel.

Mirrors upstream's build.yml build-dll/build-wheel jobs, narrowed to Linux glibc riscv64.

Differs from upstream

  • Uses v8's riscv64-linux-gnu- gcc_toolchain instead of clang - Chromium's prebuilt clang ships for amd64/arm64/mac hosts only.
  • One build-wheel job tests the wheel against every interpreter the image ships, not uv run --python X - uv has no riscv64 pythons to fetch.

Matrix: single riscv64 build; the wheel is py3-none-<platform> (one v8 build serves every interpreter, per upstream's own architecture notes).

Testing

  • same as upstream (pytest tests), run once per bundled interpreter (cp312/cp313/cp314/cp314t) against the one wheel.

License: OK

Patches

  • 0001-builder-recognize-riscv64-as-a-native-v8_target_cpu.patch - To upstream. Without it, get_local_v8_target_cpu() raises on a native riscv64 host before the --target-cpu override is even consulted.
  • 0002-setup-give-riscv64-wheels-their-own-manylinux-platfo.patch - To upstream. Without it, the wheel's platform tag silently mislabels riscv64 as x86_64.
  • 0003-builder-use-the-riscv64-linux-gnu-gcc_toolchain-not-.patch - To upstream. Without it, gclient sync fetches an unusable x86_64 clang and the build never reaches v8's own riscv64 gcc_toolchain.

Built on cp312/cp313/cp314/cp314t; pending CI.

Builds v8 (branch-heads/14.4) from source for riscv64, the shape
upstream already uses for x64/arm64: a build-dll job runs v8_build.py
to produce libmini_racer.so, then build-wheel packages it into a
single py3-none-manylinux_riscv64 wheel (the .so is not linked against
libpython, so one wheel serves every interpreter). v8's own riscv64
codegen backend (src/codegen/riscv) is mature and actively developed;
the gap is entirely in tooling: PyMiniRacer's build script does not
recognize riscv64 as a host arch, its wheel tagging mislabels
non-aarch64 riscv builds as x86_64, and Chromium's prebuilt clang is
only published for amd64/arm64/mac hosts, so the build must use v8's
existing riscv64-linux-gnu- gcc_toolchain instead. All three are
patched in patches/mini-racer/0.14.1/.
luhenry added a commit that referenced this pull request Sep 13, 2026
CI hit gclient sync's 'gsutil' bootstrap lockfile.LockError:
[Errno 11] Resource temporarily unavailable, from concurrent sync
workers racing to fetch the shared gsutil binary. depot_tools already
serializes sync (--jobs=1) for 32-bit arm boards for the same reason;
do the same for riscv64.

https://github.com/riseproject-dev/python-wheels/actions/runs/34731759983/job/103655726279
CI's gclient sync got past the gsutil lockfile race and then failed
resolving two CIPD packages neither published for linux-riscv64:
infra/rbe/client (remote build execution) and build/siso (the siso
build tool). Both are optional accelerators the plain gn+ninja build
never needs; skip them via custom_deps.

https://github.com/riseproject-dev/python-wheels/actions/runs/34732817721/job/103658674867
CI proved the previous approach wrong: gclient still tried (and
failed) to resolve infra/rbe/client/linux-riscv64 and
build/siso/linux-riscv64 with the custom_deps override in place.
CipdDependency.run() never consults the Dependency.url a custom_deps
override changes, only should_process, which is derived straight from
the DEPS-declared condition -- so nulling out a custom_deps entry can
never skip a CIPD package. A global host_cpu var override doesn't work
either: gn and ninja share the exact same guard clause and do have
riscv64 packages, so spoofing host_cpu would stop them being fetched
too. Patch the two conditions in the checked-out v8/DEPS directly
instead, after letting the first sync attempt run to completion (it
always finishes cloning v8 before it gets to CIPD resolution).

https://github.com/riseproject-dev/python-wheels/actions/runs/34734236315/job/103662627780
CI proved the retry itself wrong: gclient still re-resolved and
re-checked-out the v8 solution as normal (branch-heads/14.4 is a
branch name, not a pinned hash, so the current_revision fast path
never applied), refusing to proceed over our uncommitted DEPS edit
("You have uncommitted changes"). Drop --revision from the retry so
the .gclient's "managed: False" takes effect (only happens when there
is no revision override), skipping v8's git step entirely rather than
touching the working tree.

https://github.com/riseproject-dev/python-wheels/actions/runs/34735996717/job/103669201128
…alse on riscv64

CI got past the DEPS/CIPD fixes into an actual ninja build for the
first time, surfacing three independent problems: the bundled
debian_trixie_riscv64-sysroot is missing a multiarch header our
riscv64-linux-gnu- toolprefix trick expects, v8's custom libc++ needs
GCC 15+ (ours is older), and the prebuilt Rust toolchain segfaults on
riscv64 (published for amd64/arm64/mac hosts only, same as clang).

https://github.com/riseproject-dev/python-wheels/actions/runs/34738407307/job/103678169855
luhenry added a commit that referenced this pull request Sep 13, 2026
sqreen/PyMiniRacer's own README deprecates it in favor of the
bpcreech/PyMiniRacer fork, which continues under the PyPI name
mini-racer (already being ported in PR #1875). py-mini-racer's last
PyPI release stayed at 0.6.0 (2021-04-22).
enable_rust=false alone doesn't work: gn gen failed with
'assert(enable_rust)' in build/rust/gni_impl/rust_target.gni, reached
via v8_maybe_temporal -> third_party/rust/temporal_capi.
v8_enable_temporal_support's own default already excludes ppc64 and
s390x by name ('some architectures don't have Rust toolchains in
Chromium') -- riscv64 is simply missing from that list. Temporal is
runtime-flag-gated even when built in, so disabling it drops no
default-on behavior.

https://github.com/riseproject-dev/python-wheels/actions/runs/34742097041/job/103685126595
…stall patch(1)

CI got past gn gen and almost an hour into the actual ninja build,
then failed compiling with GCC (is_clang=false):

  ../../src/strings/unicode.h:218:13: error: explicit specialization
    in non-namespace scope 'class unibrow::Utf8'

unibrow::Utf8::WriteLeadingAscii's two explicit specializations are
declared a second time inside the class body; clang accepts this as
an extension, GCC correctly rejects it (explicit specializations of a
member template must be at namespace scope). The out-of-line
definitions in unicode.cc are already namespace-scope and
standard-conformant on their own, so the in-class declarations are
both redundant and non-portable. Wire up the previously-unused
apply_patch() to drop them for a riscv64 build, and install the
patch(1) utility it shells out to.

https://github.com/riseproject-dev/python-wheels/actions/runs/34744357842/job/103689419698
CI got past the unicode.h fix and ~46% (1011/2176) into the ninja
build before hitting another GCC-only warning-as-error in
bigint/mul-karatsuba.cc ('1 << (shift - 2)' is int, compared against a
uint32_t; clang doesn't flag it, GCC does under -Wsign-compare). Cast
it explicitly. Renamed the accumulating patch to reflect that this is
evidently a class of issue, and pass ninja -k 1000 on riscv64 so one
build surfaces as many of these as it can find, instead of one
discovery per multi-hour CI cycle.

https://github.com/riseproject-dev/python-wheels/actions/runs/34748309593/job/103700194955
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.

1 participant