Add CEP: subdirs and virtual packages for iOS and Android - #183
Conversation
Defines the ios-*/iossimulator-*/android-* subdirs and the __ios and __android virtual packages, mapping the PyPI wheel-tag model (PEP 730, PEP 738) onto conda's subdir + virtual-package machinery. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
These subdirs describe a target platform; they do not assume an implementation cannot run natively on iOS or Android. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
| Although Android runs a Linux kernel, `android-*` subdirs MUST NOT be treated as Linux subdirs. | ||
| `linux-*` packages express their C-library requirement through the `__glibc` virtual package, and | ||
| Android links against Bionic, which cannot satisfy a glibc constraint. Treating Android as Linux | ||
| would allow the solver to install `linux-*` packages whose libc requirement is silently violated. | ||
| iOS and Android subdirs ARE Unix subdirs for the purpose of the `__unix` virtual package. |
There was a problem hiding this comment.
This feels wrong. This seems like a different stdlib. For eg:
c_stdlib:
- sysroot # maybe rename to sysroot_glibc?
- sysroot_bionic
jaimergp
left a comment
There was a problem hiding this comment.
A few editorial comments. My main observation is that the current draft includes redundant information already expressed in prior CEPs, so ends up explaining and justifying a few things that are not needed. Trimming those out will improve the readability and focus of the CEP.
Also, the Specification section should be as terse as possible. A couple passages there belong better in Rejected Ideas.
The ideas are otherwise sound and well reasoned, and it makes sense to cover this omission in our ecosystem. Thanks for bringing it up!
| (via [PEP 730] and [PEP 738]) and the wider native toolchain ecosystem now support iOS and Android as | ||
| first-class target platforms, and tools such as pixi and rattler-build are able to produce packages | ||
| for them. Without an agreed naming scheme, each implementation would be free to invent its | ||
| own subdir tokens (`ios_arm64` vs `ios-arm64`, `ios-sim-arm64` vs `iossimulator-arm64`) and its own |
There was a problem hiding this comment.
Some of these examples are illegal as per CEP-26:
Channel subdir names MUST either be the literal
noarchor a string following the syntax
{os}-{arch}, where{os}and{arch}MUST only consist of lowercase ASCII letters and numbers.
Non-noarchsubdirs MUST match this regex:^[a-z0-9]+-[a-z0-9]+$.
ios_arm64 and ios-sim-arm64, in particular.
| Two facts about these platforms shape the design: | ||
|
|
||
| 1. **The subdir describes a target platform.** These names identify the platform a package is *for*, | ||
| independently of the host that resolves or builds it. In practice packages are often produced by |
There was a problem hiding this comment.
| independently of the host that resolves or builds it. In practice packages are often produced by | |
| independently of the host that resolves or builds it. In practice packages for new platforms are often produced by |
| Two facts about these platforms shape the design: | ||
|
|
||
| 1. **The subdir describes a target platform.** These names identify the platform a package is *for*, | ||
| independently of the host that resolves or builds it. In practice packages are often produced by | ||
| cross-compiling from another host, but this CEP does not assume that — an implementation may just | ||
| as well run natively on the platform. | ||
|
|
||
| 2. **PyPI already encodes three axes in one wheel tag.** A wheel tag such as | ||
| `ios_13_0_arm64_iphoneos` packs together the CPU architecture (`arm64`), the ABI / platform variant | ||
| (device `iphoneos` vs simulator `iphonesimulator`), and the minimum OS version (`13.0`). conda | ||
| traditionally splits these axes across the *subdir* (architecture and ABI) and *virtual packages* | ||
| (OS-version compatibility). This CEP applies the same split rather than inventing a monolithic tag. |
There was a problem hiding this comment.
I think these two items are superfluous and already implied by the existing CEP corpus.
| on a device and vice versa, even for the same architecture. Rather than introduce a second dash | ||
| (which would break subdir-splitting tools), the variant is folded into the OS token: device builds use | ||
| `ios`, simulator builds use `iossimulator`. There is no `ios-64` (Apple ships no x86_64 iOS *device*). |
There was a problem hiding this comment.
CEP 26 prevents double dashes, no need to argue that here.
| #### Android is not Linux | ||
|
|
||
| Although Android runs a Linux kernel, `android-*` subdirs MUST NOT be treated as Linux subdirs. | ||
| `linux-*` packages express their C-library requirement through the `__glibc` virtual package, and | ||
| Android links against Bionic, which cannot satisfy a glibc constraint. Treating Android as Linux | ||
| would allow the solver to install `linux-*` packages whose libc requirement is silently violated. | ||
| iOS and Android subdirs ARE Unix subdirs for the purpose of the `__unix` virtual package. |
There was a problem hiding this comment.
This should also be moved to Rejected Ideas.
| Otherwise (for example when cross-compiling) it SHOULD be taken from an explicit override: | ||
|
|
||
| - `__ios` version: from the `CONDA_OVERRIDE_IOS` environment variable, otherwise a build-tool-supplied | ||
| default, otherwise `0` (matches any requirement). |
There was a problem hiding this comment.
This is not true. If __ios==0 it will prevent any constraint from being satisfied.
| ## Rationale and alternatives | ||
|
|
||
| - **A single dash per subdir.** An alternative was to encode the simulator variant as a third dash | ||
| (`ios-simulator-arm64`). This breaks the widespread assumption that a subdir is `<os>-<arch>` and |
There was a problem hiding this comment.
Again, not an assumption, this is the specification. No need to state it here.
| existing, well-understood `__osx`/`__glibc` mechanism. | ||
| - **Reusing `linux-*` for Android.** Rejected: Bionic is not glibc, and reuse would let the solver | ||
| violate libc requirements silently (see [Android is not Linux](#android-is-not-linux)). | ||
|
|
There was a problem hiding this comment.
I'm missing some bits mentioned in PEP 730's Rationale here, namely:
- Why two ABIs for iOS, and why not simply
osx - Why no iPadOS
- Why
iosandiossimulatorinstead of the classiciphoneosvendor string
There was a problem hiding this comment.
Addressed in 9e16e31. The rationale now explains that device and simulator are incompatible ABIs even on arm64 and that macOS is a distinct platform despite also using Darwin; that iPadOS has no separate development ABI; and that conda folds PEP 730’s separate OS/ABI fields into ios and iossimulator, avoiding an iPhone-only name while conforming to CEP 26.
Co-authored-by: jaimergp <jaimergp@users.noreply.github.com>
Co-authored-by: jaimergp <jaimergp@users.noreply.github.com>
|
Maybe subdirs should be extended to three terms instead. |
|
I think |
|
I'm suggesting something like |
| | `android-aarch64` | `aarch64` | `arm64-v8a` | | ||
| | `android-armv7a` | `armv7a` | `armeabi-v7a` | |
There was a problem hiding this comment.
Is there any benefit to diverging from the Android ABI naming here? At least in principle, there could be other 64-bit ARM ABIs in future; is there some benefit to using aarch64 instead of arm64-v8a and armv7a instead of armeabi-v7a?
There was a problem hiding this comment.
This follows the architecture naming of the existing conda platforms (hence x86 is simply "32" and "64"), which is probably more useful than following the Android names. In hindsight, I should probably have done the same when establishing the Android wheel tag format, and made it match the Linux architecture names, which would have saved me a bit of work in auditwheel.
There could theoretically be other ABI variants of ARM64 in the future, but I think Google will probably handle them the same way as they did with NEON instructions on ARM32: declare that they're required on all devices newer than a certain Android version. In that case, there would be no need for a separate subdir; packages that are affected can simply require a minimum Android version.
[ARM32 discussion moved below]
freakboy3742
left a comment
There was a problem hiding this comment.
I'm the author of PEP 730 and CPython iOS/Android platform delegate; I'll admit to not being fully across the implications of this specification, but the details described don't appear too surprising based on what knowledge I do have.
Tagging @mhsmith (PEP 738 author) for visibility.
| - **Using `armv7l` for Android.** Android's `armeabi-v7a` uses the softfp calling convention and | ||
| Bionic, unlike the ABI represented by `linux-armv7l`. The `armv7a` token keeps these incompatible | ||
| targets distinct. |
There was a problem hiding this comment.
Even if it does use the softfp calling convention, it is still armv7l (ARM version 7, little-endian), and the kernel reports it as such. The incompatible targets can be expressed by having different OS names: android-armv7l vs linux-armv7l.
In any case, the Android 32-bit platforms aren't officially supported by Python, so I'd suggest leaving them out for now.
As discussed above, the |
Defines the ios-/iossimulator-/android-* subdirs and the __ios and __android virtual packages, mapping the PyPI wheel-tag model (PEP 730, PEP 738) onto conda's subdir + virtual-package machinery.
Checklist for submitter
cep-0000.mdnamedcep-XXXX.mdin the root level.CEP XX: Amend XYZ.## Changelogsection right above the final "Copyright" section with an item that uses syntaxYYYY-MM-DD: Brief explanation of changes.Checklist for CEP approvals
${greatest-number-in-main} + 1.cep-XXXX.mdfile has been renamed accordingly.# CEP XXXX -header has been edited accordingly.pre-commitchecks are passing.