Skip to content

Prebuilt runtimes and wheels

kivyforge never builds Python or its C extensions from source. It assembles prebuilt pieces. This explains which dependencies your app can use on each target.

The core rule: no from-source builds

kivyforge has no recipe system and does not cross-compile Python C extensions. Instead, it:

  • downloads a prebuilt, relocatable Python runtime for the target, and
  • installs prebuilt, platform-tagged wheels,

then leaves any genuine compilation to the platform's own toolchain, for example Xcode's Swift Package Manager for Swift packages. This keeps builds fast and reproducible.

Where runtimes come from

Each target uses an official or well-maintained prebuilt CPython:

  • iOS: the official python.org Python.xcframework.
  • Android: the official python.org Android runtime, one per ABI (application binary interface).
  • macOS, Linux, and Windows: a relocatable python-build-standalone CPython, bundled into the app.

You choose the version in the overlay's python table. For example:

[tool.kivy.macos.python]
version = "3.13.14"

What this means for your dependencies

Each dependency must be available as a wheel for the target's platform tag:

  • Desktop targets use ordinary PyPI wheels: macosx_* (arm64 or universal2), manylinux_*, and win_amd64.
  • iOS uses wheels with ios_* platform tags.
  • Android uses wheels with android_* platform tags, one per ABI.

A pure-Python dependency works everywhere. A dependency with a C extension works only where a matching wheel exists. If no wheel exists for a target, kivyforge cannot build one from source, and kivyforge lock fails to resolve it.

Mobile wheels for Kivy

Kivy, pyjnius, and pyobjus are published as first-party prebuilt iOS and Android wheels on the kivy-mobile-wheels index until they land on PyPI. Add the index with extra_index_urls in the mobile overlay, as the mobile examples do:

[tool.kivy.android]
extra_index_urls = ["https://elliotgarbus.github.io/kivy-mobile-wheels/simple/"]

Integrity

Every artifact is pinned by SHA-256 in the lockfile and verified on download. A mismatch fails the build. Downloads are cached in a per-user cache shared by all your projects. To empty it, run kivyforge clean --cache. pip keeps a separate cache for what lock resolves, which that leaves alone; pip cache purge clears it.

What's next