three wheels per platform, and a gate that counts them - #5
Merged
Merged
Conversation
The wheel matrix, which is twenty-one wheels and an sdist: the stable ABI from 3.11 up, free-threaded 3.14, and PEP 803's free-threaded stable ABI from 3.15 up, each on manylinux_2_28 and musllinux for x86_64 and aarch64, macOS universal2, and Windows x64 and arm64. Three per platform is CPython's arithmetic rather than ours: the free-threaded build had no stable ABI until 3.15, so 3.14t is a version-specific wheel for as long as 3.14 is supported. Which ABI a build gets is now a feature of this crate rather than a feature of the pyo3 dependency, because a wheel cannot be told which ABI it is after it is built and the three builds have to differ somewhere. `abi3` is the default, so the ordinary build and every `pip install .` is unchanged; the other two rows turn it off, one building against whichever interpreter it is given and the other against `abi3t-py315`, which compiles with no interpreter present at all. That last part is the point of a stable ABI and the only reason a 3.15 wheel can be built before 3.15 is installable. The gate is `tools/wheel_tags.py`, run twice. Each build is held to the cell it asked for, and then the grid is checked as a grid: every cell filled, nothing outside it, exactly one sdist. Both halves matter, and the first one especially: a build that cannot find the interpreter it wants does not fail, it falls back, and what comes out is a wheel that works on the machine that built it and claims nothing about any other version. That is invisible until somebody's install resolves to it. Verified against real maturin output rather than only against strings. A universal2 build here produced `macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2`, a tag set and not a tag, which the first draft refused; a platform is now the one whose pattern any member of the set matches, and a wheel for one architecture matches none of them. A `--no-default-features` build against the 3.14 on this machine produced `cp314-cp314`, and the check caught it as the cp314-cp314t row it was not. 18 tests for the rule, 194 in the client. The lint job now compiles both of the other two ABIs, so a change that breaks one is found on the pull request rather than on the tag.
The first run of this workflow taught it two things. Four Linux rows built a wheel for the image's own Python 3.12: the free-threaded and 3.15 rows never had the interpreter they asked for, because the container is not the runner and setup-python is not visible inside it. The rows now name their interpreter under /opt/python, list what the image carries before building, and fail on the spot when the one they asked for is not there. The musl rows take the pypa image rather than the cross image the action picks by default, which carries four GIL-enabled interpreters and no free-threaded one at all. The other thing is the tag. A PEP 803 wheel is cp315-abi3.abi3t, not cp315-abi3t: one wheel that is the stable ABI for the GIL-enabled build and for the free-threaded build at once, which is the whole point of the PEP and the reason three wheels a platform does not become four. An ABI tag is a set the same way a platform tag is, so the check compares it as one and holds a wheel that claims only abi3 to be a wheel the free-threaded interpreter will not load.
20 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The wheel matrix, which is twenty-one wheels and an sdist.
cp311-abi3cp314-cp314tcp315-abi3.abi3tEach on manylinux_2_28 and musllinux_1_2 for x86_64 and aarch64, macOS universal2, and Windows x64 and arm64, every row built on its own architecture because an emulated build takes twenty minutes to produce the same bytes. Three per platform is CPython's arithmetic and not ours: the free-threaded build had no stable ABI until 3.15 and PEP 803, so 3.14t is a version-specific wheel for as long as 3.14 is supported. From 3.15 one wheel serves both builds and says so in two ABI tags at once, which is what stops this at three rather than four.
Which ABI is now a feature
abi3was a feature of the pyo3 dependency, which meant every build got it and the other two rows had no way to say otherwise. It is a feature of this crate now:The default is unchanged, so an ordinary build and every
pip install .produce the same wheel they did. The 3.14t row builds--no-default-featuresagainst the free-threaded interpreter it is given, and the 3.15 row adds--features abi3t. The lint job compiles both with no interpreter present at all, which is the thing a stable ABI is for and the reason a change that breaks one is found on the pull request rather than at release time.The gate
tools/wheel_tags.py, run twice. Each build is held to the cell it asked for, and then the grid is checked as a grid: every cell filled, nothing outside it, exactly one sdist.Both halves matter and the first one especially. A build that cannot find the interpreter it wants does not always fail. Sometimes it falls back, and what comes out is a wheel that works on the machine that built it and claims nothing about any other version, which is invisible until somebody's install resolves to it.
What the first run of it taught
Written against real maturin output rather than against strings, which is the only reason any of this is right, because the first run got two things wrong and both of them were quiet.
Four Linux rows built a wheel for CPython 3.12. The container is not the runner:
setup-pythonputs an interpreter on the runner's path and the build happens inside an image that cannot see it, so maturin took the image's own/usr/bin/python3and the free-threaded rows producedcp312-cp312. The abi3 rows produced the right wheel by luck, which is the same bug with a better outcome. Every Linux row now names its interpreter under/opt/python, lists what the image carries before it builds, and stops on the spot if the one it asked for is not there. The musl rows take the pypa image rather than the cross image the action picks by default, which carries four GIL-enabled interpreters and no free-threaded one at all.The other thing is the tag itself. A PEP 803 wheel is
cp315-abi3.abi3tand notcp315-abi3t: an ABI tag is a set the same way a platform tag is, and this wheel is the stable ABI for the GIL-enabled build and for the free-threaded build at once. The check compares the set, so the order maturin writes the two members in is not something a release is held to, and a wheel that claims onlyabi3is caught as what it is, a wheel the free-threaded interpreter will not load.The universal2 tag was the same kind of surprise a commit earlier:
macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2, three true things in one name. A platform is the one whose pattern any member of the set matches, and a wheel for a single architecture matches none of them.22 tests for the rule, covering a complete release, a missing wheel, a missing ABI, a version-specific wheel nobody asked for, the two ABI tags in either order, the stable ABI without the free-threaded one, a platform not on the list, a single-architecture mac wheel, a duplicate cell, a missing sdist, and something that is not ours at all. 198 tests in the client.
Where it runs
The wheels workflow runs on a tag, on dispatch, and on any pull request that touches how a wheel is built, because the alternative is finding out on the tag. All twenty-two artifacts, and the grid they make, are green on this branch.