Skip to content

Add CEP: subdirs and virtual packages for iOS and Android - #183

Open
wolfv wants to merge 5 commits into
conda:mainfrom
wolfv:feat/ios-android-subdirs
Open

Add CEP: subdirs and virtual packages for iOS and Android#183
wolfv wants to merge 5 commits into
conda:mainfrom
wolfv:feat/ios-android-subdirs

Conversation

@wolfv

@wolfv wolfv commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

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

  • I am submitting a new CEP: Put your title here.
    • I am using the CEP template by creating a copy cep-0000.md named cep-XXXX.md in the root level.
  • I am submitting modifications to CEP XX.
    • The PR title reflects the CEP I'm modifying: CEP XX: Amend XYZ.
    • I updated the "Updated" date.
    • I added the link of this PR to the Discussions row.
    • I added or extended the ## Changelog section right above the final "Copyright" section with an item that uses syntax YYYY-MM-DD: Brief explanation of changes.
  • Something else: (add your description here).

Checklist for CEP approvals

  • The vote period has ended and the vote has passed the necessary quorum and approval thresholds.
  • A new CEP number has been minted. Usually, this is ${greatest-number-in-main} + 1.
  • The cep-XXXX.md file has been renamed accordingly.
  • The # CEP XXXX - header has been edited accordingly.
  • The CEP status in the table has been changed to approved.
  • The last modification date in the table has been updated accordingly.
  • The table in the README has been updated with the new CEP entry.
  • The pre-commit checks are passing.

wolfv and others added 2 commits July 24, 2026 15:05
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>
Comment thread cep-XXXX.md Outdated
Comment on lines +92 to +96
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.

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.

This feels wrong. This seems like a different stdlib. For eg:

c_stdlib:
  - sysroot               # maybe rename to sysroot_glibc?
  - sysroot_bionic

@jaimergp jaimergp left a comment

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.

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!

Comment thread cep-XXXX.md Outdated
(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

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.

Some of these examples are illegal as per CEP-26:

Channel subdir names MUST either be the literal noarch or a string following the syntax
{os}-{arch}, where {os} and {arch} MUST only consist of lowercase ASCII letters and numbers.
Non-noarch subdirs MUST match this regex: ^[a-z0-9]+-[a-z0-9]+$.

ios_arm64 and ios-sim-arm64, in particular.

Comment thread cep-XXXX.md Outdated
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

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.

Suggested change
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

Comment thread cep-XXXX.md Outdated
Comment on lines +42 to +53
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.

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.

I think these two items are superfluous and already implied by the existing CEP corpus.

Comment thread cep-XXXX.md Outdated
Comment thread cep-XXXX.md Outdated
Comment on lines +72 to +74
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*).

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.

CEP 26 prevents double dashes, no need to argue that here.

Comment thread cep-XXXX.md Outdated
Comment on lines +90 to +96
#### 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.

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.

This should also be moved to Rejected Ideas.

Comment thread cep-XXXX.md Outdated
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).

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.

This is not true. If __ios==0 it will prevent any constraint from being satisfied.

Comment thread cep-XXXX.md Outdated
## 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

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.

Again, not an assumption, this is the specification. No need to state it here.

Comment thread cep-XXXX.md
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)).

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.

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 ios and iossimulator instead of the classic iphoneos vendor string

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

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.

Comment thread cep-XXXX.md Outdated
wolfv and others added 3 commits July 27, 2026 12:27
Co-authored-by: jaimergp <jaimergp@users.noreply.github.com>
Co-authored-by: jaimergp <jaimergp@users.noreply.github.com>
@isuruf

isuruf commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

linux-64 is actually x86_64-linux-gnu and we need a subdir for x86_64-linux-android. Using a android-64 seems wrong here since lots of build scripts uses pattern matching like case linux-* or linux as a preprocessing selector.

Maybe subdirs should be extended to three terms instead.

@wolfv

wolfv commented Jul 27, 2026

Copy link
Copy Markdown
Contributor Author

I think linux_android would look ugly but it would possibly work OK with the current tools. Personally I don't mind android-xxx...

@isuruf

isuruf commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

I'm suggesting something like x86_64-linux-android as the subdir and let linux-64 be an alias for x86_64-linux-gnu

Comment thread cep-XXXX.md
Comment on lines +54 to +55
| `android-aarch64` | `aarch64` | `arm64-v8a` |
| `android-armv7a` | `armv7a` | `armeabi-v7a` |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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?

@mhsmith mhsmith Jul 28, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 freakboy3742 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Comment thread cep-XXXX.md
Comment on lines +109 to +111
- **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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

@mhsmith

mhsmith commented Jul 28, 2026

Copy link
Copy Markdown

I'm suggesting something like x86_64-linux-android as the subdir and let linux-64 be an alias for x86_64-linux-gnu

As discussed above, the {os}-{arch} format is already established by CEP 26, and I don't think this is a good enough reason to reopen that. Any build scripts with code like case linux-* will need to be updated to accommodate Android, in the same way as Python code that checks for sys.platform == "linux".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants