@@ -6,7 +6,7 @@ nav_order: 6
66
77# Development Guide
88
9- Structurally, the [ python-wheels] ( https://github.com/riseproject-dev/python-wheels ) repository has three goals:
9+ Structurally, the [ python-wheels] ( https://github.com/riseproject-dev/python-wheels ) repository has four goals:
1010
11111 . Provide a simple interface for users to install Python wheels from.
12122 . Create GitHub Actions workflows for building binary Python wheels that
@@ -15,6 +15,8 @@ Structurally, the [python-wheels](https://github.com/riseproject-dev/python-whee
15153 . Add supplemental workflows and tooling to track upstream releases, automate
1616 version upgrades, and simplify deprecation once upstream projects incorporate
1717 riscv64 builds, allowing developers to focus on broader package support.
18+ 4 . Serve as a reference to upstream maintainers, indicating that their projects
19+ can easily add support for riscv64.
1820
1921## Workflow Creation Process
2022
@@ -33,13 +35,12 @@ The general process:
33352 . Create a copy of the upstream build workflow in the ` python-wheels ` repo at
3436 ` .github/workflows/build-<package>.yml ` , where ` <package> ` matches the
3537 project name (e.g. ` build-numpy.yml ` for NumPy`).
36- 3 . Strip out any logic not related to the Linux glibc and musl (if present)
37- build processes.
38+ 3 . Remove any workflow logic not related to the Linux glibc and musl (if
39+ present) build processes, support for other architectures and operating
40+ systems (e.g. Windows, Mac OS). This includes the sdist build (unless it is
41+ consumed by a build or test step).
38424 . Repeat steps #2 and #3 for the corresponding test workflow, if it is separate
3943 from the upstream build file.
40- 5 . Strip out any build logic which is not relevant to riscv64 for Linux. This
41- includes all other architectures, along with builds for Windows, Mac OS, and
42- so on. Also remove the sdist and publish steps.
4344
4445From this point, some customizations are required to enable builds targeting
4546riscv64.
@@ -62,19 +63,23 @@ jobs:
6263
6364### Target Python Versions
6465
65- By default, riscv64 wheels should be built for a matrix covering the four latest
66- released Python versions. As of July 14th, 2026, this includes Pythons 3.11,
67- 3.12, 3.13, and 3.14 (along with 3.14t, the freethreaded equivalent). Some
68- wheels have previously been built for 3.13t, but since this was an experimental
69- version with limited support we avoid it now. This makes our target matrix:
66+ Previously RISE has used a Python version matrix covering the four latest
67+ releases (` major.minor ` , e.g. ` 3.14 ` ), plus any freethreaded variants available
68+ (e.g. ` 3.14t ` ). As of July 14th, 2026, this includes Pythons 3.11, 3.12, 3.13,
69+ and 3.14 (along with 3.14t, the freethreaded equivalent). However, the NumPy
70+ project (as of version 2.5.0) supports Python 3.12 as the minimum. Since this
71+ package is fundamental to many others which we are supporting, we will follow
72+ its precedent when defining our version matrix. Some wheels have previously been
73+ built for 3.13t, but since this was an experimental version with limited support
74+ we avoid it now.
7075
71- ` ['3.11', '3.12', '3.13', '3.14', '3.14t'] `
76+ With these factors, our default version matrix becomes:
7277
73- It is worth noting that NumPy releases follow a minimum supported version
74- pattern that implies a narrower matrix - for example, as of NumPy 2.5.0, only
75- Python 3.12 and newer are supported. However, we cannot ensure that all users
76- will choose 2.5.0 or greater for their projects, so until Python 3.15 is
77- released we should continue building for 3.11 .
78+ ` ['3.12', '3.13', '3.14', '3.14t'] `
79+
80+ Exceptions may be necessary for some packages, which should be carefully
81+ considered to balance achieving similarity to upstream with feasibility of
82+ maintenance .
7883
7984### uv
8085
@@ -121,7 +126,7 @@ fork. More importantly, it is critical for uncomplicated usage of tools like
121126cibuildwheel, which assumes that the root directory is the project to be built
122127when invoked.
123128
124- ### python-wheels Checkouts
129+ ### Using the python-wheels Repository in Workflows
125130
126131The ` python-wheels ` repository contains some custom Actions we require, and
127132patch files to apply for certain projects. The most critical example is the
@@ -165,7 +170,8 @@ Python registry.
165170## Testing a New Workflow
166171
167172Open a new draft PR with the workflow(s) included, and include a ` Trigger: ` line
168- with a version for each package version you want to build, like so:
173+ in the PR description with a version for each package version you want to build,
174+ like so:
169175
170176` Trigger: numpy:v2.5.0 `
171177` Trigger: numpy:v2.5.1 `
@@ -186,23 +192,31 @@ workflow and retry, while opening an issue to track the musl incompatibility.
186192
187193### Patching a Project
188194
189- If a workflow fails consistently when building or testing a module, consider
190- whether the failure meets one of the following three criteria:
195+ Some workflows may fail consistently when building or testing a module, despite
196+ following the guidelines above. When this occurs, consider whether the failure
197+ meets one of the following criteria:
191198
1921991 . The failure exercises a narrow part of the module's functionality, or relies
193200 on external resources (e.g. large downloads over the network)
1942012 . The failure is due to reliance on some other software unavailable on riscv64
1952023 . The failure is a consequence of an artificial test limitation, e.g. a maximum
196203 timeout
204+ 4 . The project's build scripts use host tooling which isn't available on the
205+ runners or in the riscv64 manylinux images (e.g. ` apt ` vs ` dnf ` )
197206
198- In these cases, it may be justified to add one or more patch files to remove
199- these cases from the workflow. In this scenario, follow these steps:
207+ Additionally, some packages may not fully incorporate all of the LICENSE files
208+ found in their repositories or as required by their dependencies. See the
209+ [ Licensing] ( #licensing ) section for more info on this topic. In these cases, it
210+ may be justified to add one or more patch files to remove these cases from the
211+ workflow. In this scenario, follow these steps:
200212
2012131 . Any such patches should be placed in a ` patches/<package_name>/<version_tag> `
202214 path inside ` python-wheels ` .
203- 2 . an extra step should be added to the build/test workflows before execution to
215+ 2 . Each patch should include an ` Upstream-Status ` tag. See the [ Upstream Status
216+ Tags] ( #upstream-status-tags ) section for details on valid types.
217+ 3 . An extra step should be added to the build/test workflows before execution to
204218 use ` git apply ` to make necessary modifications to the project source.
205- 3 . The change should be documented for the package, so that users are aware of
219+ 4 . The change should be documented for the package, so that users are aware of
206220 modifications made.
207221
208222** Note: Patching should be performed and reviewed on a case-by-case basis - as
@@ -297,3 +311,36 @@ Some packages may require GCC 14 or later to compile for riscv64. If your build
297311requires GCC 14, ensure that you are either using a cibuildwheel container
298312approach, or (if the project doesn't use cibuildwheel) have an appropriate
299313workaround in place, since the RISC-V runners currently ship GCC 13 by default.
314+
315+ ### Upstream Status Tags
316+
317+ We use a pattern established by the [ Yocto
318+ Project] ( https://docs.yoctoproject.org/dev/contributor-guide/recipe-style-guide.html#patch-upstream-status )
319+ for indicating the purpose and status of custom patches which we carry for
320+ various projects. Each tag should be specified in the patch file's commit
321+ message like so:
322+
323+ ```
324+ Upstream-Status: <type> [reason and/or link]
325+ ```
326+
327+ There are five valid ` Upstream-Status ` types for the ` python-wheels ` repository:
328+
329+ 1 . ` Issue ` : An issue has been opened on the upstream project to indicate a bug
330+ was found during build/test. The issue link should be included.
331+ 2 . ` Submitted ` : A change was submitted to fix an issue upstream, but we are
332+ carrying the patch ourselves until it's merged and released in a future
333+ version. Include a link to the upstream PR and/or merged commit.
334+ 3 . ` To upstream ` : The patch needs to be submitted upstream, but submission is
335+ blocked. Include an explanation of why it can't be submitted upstream yet.
336+ 4 . ` Inappropriate ` : The patch includes changes which are necessary for riscv64
337+ builds and/or our infrastructure, but are not relevant upstream. Include a
338+ short description of why.
339+ 5 . ` Backport ` : The patch includes a fix which is already merged in an upstream
340+ release version, but not in the version we're trying to build. Include a link
341+ and short description of the problem.
342+
343+ Including an ` Upstream-Status ` tag is a baseline requirement for custom patches,
344+ and it is automatically searched for by the ` ci_scripts/check_patch.py ` script
345+ when submitting a PR. However, any additional detail which can be provided in
346+ each patch's commit message is helpful for maintenance.
0 commit comments