Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
87bcefe
Use `pyodide config get emscripten_dir`
agriyakhetarpal Apr 6, 2026
17679b8
Update constraints
agriyakhetarpal Apr 6, 2026
2df97d1
Updates for `pyemscripten` platform tag
agriyakhetarpal Apr 6, 2026
4bd785d
Weird constraints stuff...
agriyakhetarpal Apr 6, 2026
499e965
Revert "Weird constraints stuff..."
agriyakhetarpal Apr 6, 2026
8064a46
Add some special constraints for pyodide
agriyakhetarpal Apr 6, 2026
ac56575
Wheel pyemscripten collision
agriyakhetarpal Apr 6, 2026
52fa455
Put delocate back in constraints (not needed tho)
agriyakhetarpal Apr 6, 2026
46a2627
Drop Pyodide 0.27.7 (cp312-pyodide_wasm32)
agriyakhetarpal Apr 10, 2026
088d6e5
Add Pyodide 314.0.0a1 (cp314-pyodide_wasm32)
agriyakhetarpal Apr 10, 2026
455e568
Delete no-longer-needed Pyodide 312 constraints
agriyakhetarpal Apr 10, 2026
9396cae
Update Pyodide 313 and 314 constraints
agriyakhetarpal Apr 10, 2026
f0289d8
Add back prerelease stuff and update tests
agriyakhetarpal Apr 10, 2026
9749c11
Fix `test_pyodide_on_windows`
agriyakhetarpal Apr 10, 2026
e3c8ca1
Update and fix tests some more
agriyakhetarpal Apr 10, 2026
f4e5229
Also enable pyodide-prerelease in GHA sample build
agriyakhetarpal Apr 10, 2026
3fe3394
Update tests yet again (`SINGLE_PYTHON_VERSION` changes)
agriyakhetarpal Apr 10, 2026
6092434
Add a Pyodide-specific maintenance guide
agriyakhetarpal Apr 10, 2026
87c1be7
Merge branch 'main' into pyodide-updates
agriyakhetarpal Apr 10, 2026
40ffec0
Add suggestions from Hood and Gyeongjae
agriyakhetarpal Apr 13, 2026
18ea0fc
Merge main
agriyakhetarpal May 7, 2026
e50d138
Add "Last updated: May 2026" to Pyodide document
agriyakhetarpal May 7, 2026
829392f
Add a Pyodide EOL filter
agriyakhetarpal May 7, 2026
0a4abb6
Fix typo
agriyakhetarpal May 7, 2026
1960c6e
Update maintenance docs about EoL Pyodide
agriyakhetarpal May 7, 2026
44bdfbc
Add Pyodide 312 constraints back
agriyakhetarpal May 7, 2026
f4255af
Update Pyodide 313 and 314 constraints
agriyakhetarpal May 7, 2026
8fc1e7c
Remove "experimental" note about Pyodide
agriyakhetarpal May 8, 2026
ff16b28
Remove another experimental Pyodide sentence
agriyakhetarpal May 8, 2026
d408f03
Add docs about the `pyodide-eol` enable option
agriyakhetarpal May 8, 2026
11490ff
Merge upstream/main into pyodide-updates
henryiii May 9, 2026
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
21 changes: 10 additions & 11 deletions cibuildwheel/platforms/pyodide.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,29 +94,28 @@ def ensure_node(major_version: str) -> Path:
return path


def install_emscripten(
env: dict[str, str], version: str, xbuildenv_cache_path: Path, pyodide_version: str
) -> Path:
def install_emscripten(env: dict[str, str], version: str, xbuildenv_cache_path: Path) -> Path:
"""Install Emscripten via pyodide-build, which also applies Pyodide-specific patches."""
emcc_path = (
xbuildenv_cache_path / pyodide_version / "emsdk" / "upstream" / "emscripten" / "emcc"
emscripten_dir = Path(
call("pyodide", "config", "get", "emscripten_dir", env=env, capture_stdout=True).strip()
)
with FileLock(CIBW_CACHE_PATH / "emscripten.lock"):
if emcc_path.exists():
return emcc_path
if emscripten_dir.exists():
return emscripten_dir
call(
"pyodide",
"xbuildenv",
"install-emscripten",
"--force",
Comment thread
henryiii marked this conversation as resolved.
"--version",
version,
"--path",
str(xbuildenv_cache_path),
env=env,
cwd=CIBW_CACHE_PATH,
)
assert emcc_path.exists()
return emcc_path
assert emscripten_dir.exists()
return emscripten_dir


def get_all_xbuildenv_version_info(env: dict[str, str]) -> list[PyodideXBuildEnvInfo]:
Expand Down Expand Up @@ -315,9 +314,9 @@ def setup_python(
log.step(
f"Installing Emscripten {emscripten_version} and applying Pyodide-specific patches ..."
)
emcc_path = install_emscripten(env, emscripten_version, xbuildenv_cache_path, pyodide_version)
emscripten_dir = install_emscripten(env, emscripten_version, xbuildenv_cache_path)

env["PATH"] = os.pathsep.join([str(emcc_path.parent), env["PATH"]])
env["PATH"] = os.pathsep.join([str(emscripten_dir), env["PATH"]])
Comment thread
henryiii marked this conversation as resolved.

return env

Expand Down
14 changes: 7 additions & 7 deletions cibuildwheel/resources/constraints-pyodide312.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
# nox -s update_constraints
annotated-types==0.7.0
# via pydantic
auditwheel-emscripten==0.2.3
auditwheel-emscripten==0.2.4
# via pyodide-build
build==1.2.2.post1
build==1.4.2
# via
# -r .nox/update_constraints/tmp/constraints-pyodide.in
# pyodide-build
certifi==2026.2.25
# via requests
charset-normalizer==3.4.6
charset-normalizer==3.4.7
# via requests
click==8.1.8
# via
Expand Down Expand Up @@ -50,9 +50,9 @@ pydantic==2.12.5
# pyodide-lock
pydantic-core==2.41.5
# via pydantic
pygments==2.19.2
pygments==2.20.0
# via rich
pyodide-build==0.33.0
pyodide-build==0.34.1
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
pyodide-cli==0.5.0
# via
Expand All @@ -62,9 +62,9 @@ pyodide-lock==0.1.2
# via pyodide-build
pyproject-hooks==1.2.0
# via build
python-discovery==1.2.0
python-discovery==1.2.1
# via virtualenv
requests==2.32.5
requests==2.33.1
# via pyodide-build
rich==14.3.3
# via
Expand Down
14 changes: 7 additions & 7 deletions cibuildwheel/resources/constraints-pyodide313.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
# nox -s update_constraints
annotated-types==0.7.0
# via pydantic
auditwheel-emscripten==0.2.3
auditwheel-emscripten==0.2.4
# via pyodide-build
build==1.2.2.post1
build==1.4.2
# via
# -r .nox/update_constraints/tmp/constraints-pyodide.in
# pyodide-build
certifi==2026.2.25
# via requests
charset-normalizer==3.4.6
charset-normalizer==3.4.7
# via requests
click==8.1.8
# via
Expand Down Expand Up @@ -50,9 +50,9 @@ pydantic==2.12.5
# pyodide-lock
pydantic-core==2.41.5
# via pydantic
pygments==2.19.2
pygments==2.20.0
# via rich
pyodide-build==0.33.0
pyodide-build==0.34.1
# via -r .nox/update_constraints/tmp/constraints-pyodide.in
pyodide-cli==0.5.0
# via
Expand All @@ -62,9 +62,9 @@ pyodide-lock==0.1.2
# via pyodide-build
pyproject-hooks==1.2.0
# via build
python-discovery==1.2.0
python-discovery==1.2.1
# via virtualenv
requests==2.32.5
requests==2.33.1
# via pyodide-build
rich==14.3.3
# via
Expand Down
6 changes: 3 additions & 3 deletions test/test_custom_repair_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
wheel = Path(sys.argv[1])
dest_dir = Path(sys.argv[2])
platform = wheel.stem.split("-")[-1]
if platform.startswith("pyodide"):
# for the sake of this test, munge the pyodide platforms into one, it's
if platform.startswith("pyemscripten"):
# for the sake of this test, munge the pyemscripten platforms into one, it's
# not valid, but it does activate the uniqueness check
platform = "pyodide"
platform = "pyemscripten"

name = f"spam-0.1.0-py2-none-{platform}.whl"
dest = dest_dir / name
Expand Down
19 changes: 14 additions & 5 deletions test/test_dependency_versions.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,11 +140,20 @@ def test_dependency_constraints(
project_dir = tmp_path / "project"
test_projects.new_c_project().generate(project_dir)

tool_versions = {
"pip": "23.1.2",
"build": "1.2.2",
"delocate": "0.10.3",
}
if utils.get_platform() == "pyodide":
# pyodide-build 0.34+ requires build~=1.4.0, so we must use a
# compatible version here. delocate is macOS-only and not used on pyodide.
tool_versions = {
"pip": "23.1.2",
"build": "1.4.2",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what happens if we use build 1.4 or 1.5 for all cases?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It now supports 1.4 and 1.5, but it's highly constrained due to worries about it using build's internals. Those are generally okay, I think. I think the reason for 1.2.2 was likely older Python support, but we are dropping 3.9 so hopefully that's better now.

"delocate": "0.10.3",
}
else:
tool_versions = {
"pip": "23.1.2",
"build": "1.2.2",
"delocate": "0.10.3",
}

if method == "file":
constraints_file = tmp_path / "constraints file.txt"
Expand Down
10 changes: 5 additions & 5 deletions test/test_pyodide.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ def test_pyodide_build(tmp_path: Path, use_pyproject_toml: bool) -> None:

# check that the expected wheels are produced
expected_wheels = [
"spam-0.1.0-cp312-cp312-pyodide_2024_0_wasm32.whl",
"spam-0.1.0-cp313-cp313-pyodide_2025_0_wasm32.whl",
"spam-0.1.0-cp312-cp312-pyemscripten_2024_0_wasm32.whl",
"spam-0.1.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl",
]

print("actual_wheels", actual_wheels)
Expand Down Expand Up @@ -144,8 +144,8 @@ def test_filter() -> None:
)
# check that the expected wheels are produced
expected_wheels = [
"spam-0.1.0-cp312-cp312-pyodide_2024_0_wasm32.whl",
"spam-0.1.0-cp313-cp313-pyodide_2025_0_wasm32.whl",
"spam-0.1.0-cp312-cp312-pyemscripten_2024_0_wasm32.whl",
"spam-0.1.0-cp313-cp313-pyemscripten_2025_0_wasm32.whl",
]
assert set(actual_wheels) == set(expected_wheels)

Expand All @@ -170,6 +170,6 @@ def test_pyodide_repair_wheel(tmp_path: Path) -> None:

# check that the expected wheels are produced
expected_wheels = [
"spam-0.1.0-cp312-cp312-pyodide_2024_0_wasm32.whl",
"spam-0.1.0-cp312-cp312-pyemscripten_2024_0_wasm32.whl",
]
assert set(actual_wheels) == set(expected_wheels)
6 changes: 3 additions & 3 deletions test/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,14 +414,14 @@ def _expected_wheels(

elif platform == "pyodide":
platform_tags = {
"cp312-cp312": ["pyodide_2024_0_wasm32"],
"cp313-cp313": ["pyodide_2025_0_wasm32"],
"cp312-cp312": ["pyemscripten_2024_0_wasm32"],
Comment thread
henryiii marked this conversation as resolved.
Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The existing tags should stay the same right? There is no version of Pyodide that accepts a wheel tagged pyemscripten_2024_0 so if we're going to make them we might as well just delete support for versions older than 314. But it'd be better not to change the existing behavior.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I believe this is a regression, then. @ryanking13, were we too early in changing to the pyemscripten platform tag in pyodide-build? Ideally the previous xbuildenvs (0.27.7, 0.29.3, etc.) should have set USE_LEGACY_PLATFORM, but then that's not possible to fix retroactively as we didn't know that at the time. So maybe we should yank pyodide-build==0.34.1, set USE_LEGACY_PLATFORM to 1 and create a new release with it (0.35.0 because semver), and then ensure that the upcoming 314.0 xbuildenv(s) will set USE_LEGACY_PLATFORM to 0 in Makefile.envs. I would like to support both 0.29.3 and 314.0 releases at the same time, to allow users extra time to switch ABIs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Well, I am not sure to be honest. If we keep the pyodide tag, then the package will not be uploadable to PyPI, if we change it to pyemscripten, old versions of micropip will deny the package. So both choices have downsides.

I am personally +1 for using the pyemscripten name for even older versions for consistency. Older Pyodide versions can still either 1) install newer micropip from PyPI, or 2) install it directly through pyodide.loadPackage. I think it is less confusing than outputting different platform names for differenet Python versions.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Hmm, given that users do have an option to update micropip, and now that the first alpha of 314.0 is out (thanks to you!), I will add it in this PR and drop Pyodide 0.27.7.

Will that resolve your concerns, @hoodmane? Or, do you think that cibuildwheel should work around it now, and rename 2024_0 and 2025_0 ABI wheels that contain pyemscripten in the platform tag string back to pyodide for them?. We do have some time until this PR is merged and released, and it brings pyodide-build 0.34.1, so it's better that we do things right in the first go.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

If a patch release of pyodide 3.13 with updated micropip was possible, then I'd go:

  • drop 3.12
  • switch 3.13 to pyemscripten_2025
  • keep 3.14 as "pre-release" until pyemscripten_2026 is declared stable.

If a patch release is hard to do... Well, that's uglier. Are these "normal" enough that wheel tag can re-tag?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

There is now a v0.29.4 patch release: https://github.com/pyodide/pyodide/releases/tag/0.29.4. Updating to it!

"cp313-cp313": ["pyemscripten_2025_0_wasm32"],
}.get(python_abi_tag, [])

if not platform_tags:
# for example if the python tag is `none` or `abi3`, all
# platform tags are built with that python tag
platform_tags = ["pyodide_2024_0_wasm32"]
platform_tags = ["pyemscripten_2024_0_wasm32"]

else:
msg = f"Unsupported platform {platform!r}"
Expand Down
Loading