Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow the use of arbitrary Pyodide versions #2002

Draft
wants to merge 50 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2ae389d
Fix a typo: pyoodide ➡️ pyodide
agriyakhetarpal Sep 10, 2024
0e3b3f1
Add `pyodide_build_version` attribute
agriyakhetarpal Sep 10, 2024
394459f
Add version to xbuildenv log step
agriyakhetarpal Sep 10, 2024
dff7bf2
Add version to Emscripten log step
agriyakhetarpal Sep 10, 2024
16057bc
Use `pyodide-build`'s version for updating constraints
agriyakhetarpal Sep 10, 2024
f167c50
Bump Pyodide constraints by updating `pyodide-build`
agriyakhetarpal Sep 10, 2024
31a6be9
Add a schema for `pyodide-version`
agriyakhetarpal Sep 12, 2024
cbca40b
Merge branch 'main' into feat/distinct-pyodide-build
agriyakhetarpal Sep 12, 2024
9003067
Update Pyodide constraints
agriyakhetarpal Sep 12, 2024
d8a8d5e
Bump `pyodide-build` to new 0.29.0
agriyakhetarpal Sep 24, 2024
cf5dd3e
Test out another Pyodide identifier
agriyakhetarpal Sep 24, 2024
55459cb
Merge branch 'main' into feat/distinct-pyodide-build
agriyakhetarpal Sep 24, 2024
4fe86e0
Update outdated Pyodide constraints
agriyakhetarpal Sep 24, 2024
b6830ee
Add Pyodide version to temp directory name
agriyakhetarpal Sep 24, 2024
aaf32e5
Remove Pyodide 0.26.1 from build configurations
agriyakhetarpal Sep 24, 2024
bb6e0d6
Retrieve + validate + install specific xbuildenvs
agriyakhetarpal Sep 24, 2024
735d5bb
Test wheel builds with Pyodide 0.26.2
agriyakhetarpal Sep 24, 2024
b8ac6c0
Add correct Pyodide version to identifier temp dir
agriyakhetarpal Sep 24, 2024
7796311
Don't pre-call Pyodide xbuildenv search
agriyakhetarpal Sep 24, 2024
97e22c8
Fetch just the stable Pyodide versions
agriyakhetarpal Sep 24, 2024
d30eb6a
Refactor search + validation + install into one step
agriyakhetarpal Sep 24, 2024
ce2a3f0
Move all of it under a lock
agriyakhetarpal Sep 24, 2024
13fbf66
Reorder xbuildenv installation
agriyakhetarpal Sep 24, 2024
14ec071
Add env and cwd to xbuildenv search call
agriyakhetarpal Sep 24, 2024
aae64bb
Temporarily lower to 0.26.2 target
agriyakhetarpal Sep 24, 2024
6956121
Separate out search, validate, install; again
agriyakhetarpal Sep 24, 2024
e5d8443
Run xbuildenv search in `CIBW_CACHE_PATH`
agriyakhetarpal Sep 24, 2024
95c3681
Remove prior `PYODIDE_ROOT` env vars, copy envs
agriyakhetarpal Sep 24, 2024
09af46f
Validate doesn't need to depend on searching
agriyakhetarpal Sep 24, 2024
66999cb
Add file lock when searching xbuildenvs
agriyakhetarpal Sep 24, 2024
1af1e5d
Test the original version: 0.26.1
agriyakhetarpal Sep 24, 2024
ad3a203
Merge branch 'main' into feat/distinct-pyodide-build
agriyakhetarpal Oct 22, 2024
d344548
Update Pyodide constraints
agriyakhetarpal Oct 22, 2024
b3143b4
Merge remote-tracking branch 'upstream/main' into feat/distinct-pyodi…
agriyakhetarpal Nov 21, 2024
738ed1f
Update constraints for `pyodide-build` 0.29.0 again
agriyakhetarpal Nov 21, 2024
41e466a
Bump Pyodide from version 0.26.1 ➡️ version 0.26.4
agriyakhetarpal Nov 21, 2024
2a66ddd
Add note on compatibility for macOS + other archs
agriyakhetarpal Nov 21, 2024
dff72ca
Note Pyodide version for Pyodide identifier
agriyakhetarpal Nov 21, 2024
9a78845
Docs about `CIBW_PYODIDE_VERSION`
agriyakhetarpal Nov 21, 2024
e551021
Don't fetch just the stable versions
agriyakhetarpal Nov 21, 2024
1fe8a04
Discard a variable that's not used later
agriyakhetarpal Nov 21, 2024
8a8177c
Rename `search_xbuildenv` ➡️ `get_xbuildenv_versions`
agriyakhetarpal Nov 21, 2024
fffb705
`validate_xbuildenv` ➡️ `validate_xbuildenv_version`
agriyakhetarpal Nov 21, 2024
0df3c45
Replace ordered comment, add newline
agriyakhetarpal Nov 21, 2024
057e542
Replace sentence on macOS support
agriyakhetarpal Nov 21, 2024
29b5eff
Capitalise: "pyodide" ➡️ "Pyodide"
agriyakhetarpal Nov 21, 2024
321e0de
"work" ➡️ "may succeed"
agriyakhetarpal Nov 21, 2024
92babdb
Add another job to test a custom Pyodide version
agriyakhetarpal Nov 21, 2024
d73f71f
Handle "v"-prefixed + non-prefixed versions
agriyakhetarpal Nov 21, 2024
0f52a4b
Merge remote-tracking branch 'upstream/main' into feat/distinct-pyodi…
agriyakhetarpal Nov 22, 2024
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
20 changes: 19 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -171,9 +171,13 @@ jobs:
run: uv run pytest --run-emulation ${{ matrix.arch }} test/test_emulation.py

test-pyodide:
name: Test cibuildwheel building Pyodide wheels
name: Test cibuildwheel building Pyodide wheels (${{ matrix.pyodide-version }} version)
needs: lint
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
pyodide-version: ["default", "custom"]
timeout-minutes: 180
steps:
- uses: actions/checkout@v4
Expand All @@ -191,12 +195,26 @@ jobs:
uv run -m test.test_projects test.test_0_basic.basic_project sample_proj

- name: Run a sample build (GitHub Action)
if: matrix.pyodide-version == 'default'
uses: ./
with:
package-dir: sample_proj
output-dir: wheelhouse
env:
CIBW_PLATFORM: pyodide

- name: Run a sample build (GitHub Action) for an overridden Pyodide version
if: matrix.pyodide-version == 'custom'
uses: ./
with:
package-dir: sample_proj
output-dir: wheelhouse
# In case this breaks at any point in time, switch to using the latest version
# available or any other version that is not the same as the default one set
# in cibuildwheel/resources/build-platforms.toml.
env:
CIBW_PLATFORM: pyodide
CIBW_PYODIDE_VERSION: "0.27.0a2"

- name: Run tests with 'CIBW_PLATFORM' set to 'pyodide'
run: |
Expand Down
69 changes: 66 additions & 3 deletions cibuildwheel/pyodide.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import annotations

import json
import os
import shutil
import sys
Expand Down Expand Up @@ -66,6 +67,47 @@ def install_emscripten(tmp: Path, version: str) -> Path:
return emcc_path


def get_xbuildenv_versions(env: dict[str, str]) -> list[str]:
"""Searches for the compatible xbuildenvs for the current pyodide-build version"""
with FileLock(CIBW_CACHE_PATH / "xbuildenv.lock"):
xbuildenvs = call(
"pyodide",
"xbuildenv",
"search",
"--json",
"--all",
env=env,
cwd=CIBW_CACHE_PATH,
capture_stdout=True,
).strip()
xbuildenvs_dict = json.loads(xbuildenvs)
compatible_xbuildenv_versions = [
_["version"] for _ in xbuildenvs_dict["environments"] if _["compatible"]
]

return compatible_xbuildenv_versions


# The xbuildenv version is brought in sync with the pyodide-build version in build-platforms.toml,
# which will always be compatible. Hence, this condition really checks only for the case where the
# version is supplied manually through a CIBW_PYODIDE_VERSION environment variable and raises an
# error as appropriate.
def validate_xbuildenv_version(
cibw_pyodide_version: str, pyodide_build_version: str, compatible_versions: list[str]
) -> None:
"""Validate the Pyodide version if set manually for the current pyodide-build version
against a list of compatible versions."""

if cibw_pyodide_version not in compatible_versions:
msg = (
f"The xbuildenv version {cibw_pyodide_version} is not compatible with the pyodide-build"
f" version {pyodide_build_version}. The compatible versions available to download are:\n"
f"{compatible_versions}. Please use the 'pyodide xbuildenv search' command to"
f" find the compatible versions for 'pyodide-build' {pyodide_build_version}."
)
raise errors.FatalError(msg)


def install_xbuildenv(env: dict[str, str], pyodide_build_version: str, pyodide_version: str) -> str:
"""Install a particular Pyodide xbuildenv version and set a path to the Pyodide root."""
# Since pyodide-build was unvendored from Pyodide v0.27.0, the versions of pyodide-build are
Expand All @@ -76,6 +118,7 @@ def install_xbuildenv(env: dict[str, str], pyodide_build_version: str, pyodide_v
CIBW_CACHE_PATH
/ f".pyodide-xbuildenv-{pyodide_build_version}/{pyodide_version}/xbuildenv/pyodide-root"
)

with FileLock(CIBW_CACHE_PATH / "xbuildenv.lock"):
if pyodide_root.exists():
return str(pyodide_root)
Expand All @@ -84,6 +127,8 @@ def install_xbuildenv(env: dict[str, str], pyodide_build_version: str, pyodide_v
# PYODIDE_ROOT so copy it first.
env = dict(env)
env.pop("PYODIDE_ROOT", None)

# Install the xbuildenv
call(
"pyodide",
"xbuildenv",
Expand Down Expand Up @@ -176,9 +221,24 @@ def setup_python(

env["PATH"] = os.pathsep.join([str(emcc_path.parent), env["PATH"]])

log.step(f"Installing Pyodide xbuildenv version: {python_configuration.pyodide_version} ...")
# Allow overriding the xbuildenv version with an environment variable. This allows
# testing new Pyodide xbuildenv versions before they are officially released, or for
# using a different Pyodide version other than the one that is listed to be compatible
# with the pyodide-build version in the build-platforms.toml file.
cibw_pyodide_version = os.environ.get(
"CIBW_PYODIDE_VERSION", python_configuration.pyodide_version
)
Comment on lines +228 to +230
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The other options can be passed either as a cli flag e.g., --pyodide-version or as the corresponding environment variable in this case CIBW_PYODIDE_VERSION. They can also come from the cibuildwheel section in pyproject.toml. We should handle this in the same way as all the other options. Then we can just use python_configuration.pyodide_version and it should already have the right value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most options are not available as flags (and I wouldn't add this one), only stuff you often need on the command line, like --platform. Just env var and config.

# If there's a "v" prefix, remove it: both would be equally valid
cibw_pyodide_version = cibw_pyodide_version.lstrip("v")
log.step(f"Installing Pyodide xbuildenv version: {cibw_pyodide_version} ...")
# Search for compatible xbuildenv versions
compatible_versions = get_xbuildenv_versions(env)
# and then validate the xbuildenv version
validate_xbuildenv_version(
cibw_pyodide_version, python_configuration.pyodide_build_version, compatible_versions
)
env["PYODIDE_ROOT"] = install_xbuildenv(
env, python_configuration.pyodide_build_version, python_configuration.pyodide_version
env, python_configuration.pyodide_build_version, cibw_pyodide_version
)

return env
Expand Down Expand Up @@ -227,7 +287,10 @@ def build(options: Options, tmp_path: Path) -> None:

log.build_start(config.identifier)

identifier_tmp_dir = tmp_path / config.identifier
# Include both the identifier and the Pyodide version in the temp directory name
cibw_pyodide_version = os.environ.get("CIBW_PYODIDE_VERSION", config.pyodide_version)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again we should get the correct value into config.pyodide_version to begin with.

identifier_tmp_dir = tmp_path / f"{config.identifier}_{cibw_pyodide_version}"

built_wheel_dir = identifier_tmp_dir / "built_wheel"
repaired_wheel_dir = identifier_tmp_dir / "repaired_wheel"
identifier_tmp_dir.mkdir()
Expand Down
5 changes: 5 additions & 0 deletions cibuildwheel/resources/cibuildwheel.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,11 @@
},
"test-requires": {
"$ref": "#/properties/test-requires"
},
"pyodide-version": {
Copy link
Contributor

@henryiii henryiii Nov 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file gets generated, I don't see the bin/generate_schema.py being updated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Just tried nox -s generate_schema and the changes went away. I'll check how to update the schema properly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't cibuildwheel/options.py also need updating? I don't see a .get("pyodide-versions") being read there.

"description": "Specify the Pyodide xbuildenv version to use for building",
"type": "string",
"title": "CIBW_PYODIDE_VERSION"
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ Default: `auto`

- For `linux`, you need [Docker or Podman](#container-engine) running, on Linux, macOS, or Windows.
- For `macos` and `windows`, you need to be running on the respective system, with a working compiler toolchain installed - Xcode Command Line tools for macOS, and MSVC for Windows.
- For `pyodide` you need to be on an x86-64 linux runner and `python3.12` must be available in `PATH`.
- For `pyodide` `python3.12` must be available in `PATH` and you need to be on one of the following runners: x86-64 Linux, arm64 Linux. Intel and Silicon macOS hosts may succeed, though there are known bugs. See [the section on Pyodide](setup.md#pyodide-(WebAssembly)-builds-(experimental)) for more information.

This option can also be set using the [command-line option](#command-line) `--platform`. This option is not available in the `pyproject.toml` config.

Expand Down Expand Up @@ -321,7 +321,7 @@ If you set the value lower, cibuildwheel will cap it to the lowest supported val
Windows arm64 platform support is experimental.

For an experimental WebAssembly build with `--platform pyodide`,
`cp312-pyodide_wasm32` is the only platform identifier.
`cp312-pyodide_wasm32` is the only platform identifier, corresponding to [Pyodide version `0.26.4`](https://github.com/pyodide/pyodide/releases/tag/0.26.4).

See the [cibuildwheel 1 documentation](https://cibuildwheel.pypa.io/en/1.x/) for past end-of-life versions of Python, and PyPy2.7.

Expand Down
9 changes: 8 additions & 1 deletion docs/setup.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,14 @@ Pre-requisite: you need to have a matching host version of Python (unlike all
other cibuildwheel platforms). Linux host highly recommended; macOS hosts may
work (e.g. invoking `pytest` directly in [`CIBW_TEST_COMMAND`](options.md#test-command) is [currently failing](https://github.com/pyodide/pyodide/issues/4802)) and Windows hosts will not work.

You must target pyodide with `--platform pyodide` (or use `--only` on the identifier).
You must target Pyodide with `--platform pyodide` (or use `--only` on the identifier).

!!!tip

It is also possible to target a specific Pyodide version by setting the `CIBW_PYODIDE_VERSION` environment variable to the desired version. Users are responsible for setting an appropriate Pyodide version according to the `pyodide-build` version. A list is available in Pyodide's [cross-build environments metadata file](https://github.com/pyodide/pyodide/blob/main/pyodide-cross-build-environments.json) or can be
referenced using the `pyodide xbuildenv search` command.

This option is **not available** in the `pyproject.toml` config.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a good reason that it isn't available in the pyproject.toml config?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like it should be.


## Configure a CI service

Expand Down
Loading