Building Kivy Wheels¶
ksproject's default bootstraps target Kivy 2.3.x and Kivy 3.0.0. Pre-built wheels are published on the KivySchool indexes — but you don't have to wait for them. Both source trees build with cibuildwheel, so you can produce the exact platform wheels you need yourself, then drop them into your app's wheelhouse.
Typical reasons to do this:
- You patched Kivy and want your fork on device
- You want to track Kivy master ahead of published wheels
- You need an arch or platform combination that isn't published yet
Prerequisites¶
Add cibuildwheel (3.2 or newer — the first release supporting both iOS and Android targets) to your app's dev dependencies. Like ksproject itself, it lives in your project — dev-group dependencies stay on your dev machine and are never installed into the app's on-device site-packages:
The build commands below run from inside the Kivy clone, so they invoke cibuildwheel through your app's environment with uv run --project ../myapp — adjust that path to wherever your app actually lives.
What you can build depends on your host machine:
| Target | Host requirement |
|---|---|
| iOS | macOS with Xcode |
| Android | Linux or macOS, with an Android NDK |
| macOS | macOS with Xcode command line tools |
| Linux | Linux (or any host with Docker) |
| Windows | Windows |
Build only the Python version you ship
ksproject bundles CPython 3.13. Restrict cibuildwheel to it and skip the rest:
Kivy 2.3.x (kivy2x)¶
kivy-school/kivy2x is the maintained Kivy 2.3.x tree with cibuildwheel configuration baked in — no extra environment setup beyond the Android NDK.
--archs all builds device (arm64_iphoneos) and simulator (arm64_iphonesimulator, x86_64_iphonesimulator) wheels.
ksproject already manages an NDK — ask it for the path. Run the export from your app's root with uv run, then switch to the kivy2x clone:
# in your ksproject app root
export ANDROID_NDK_HOME=$(uv run ksproject android get-path ndk)
cd ../kivy2x # wherever you cloned it
uv run --project ../myapp cibuildwheel --platform android --archs all --output-dir ./wheelhouse
--archs all builds arm64_v8a and x86_64 wheels.
(--platform can be omitted on a macOS host — it defaults to the host platform.)
(--platform can be omitted on a Linux host.)
The wheels land in ./wheelhouse inside the clone — copy them into your app afterwards (see Using the wheels).
Kivy 3.0.0 (master)¶
Kivy 3.0.0 builds from the official kivy/kivy master branch. Unlike kivy2x, its native dependencies (SDL3 and friends) must be compiled first — the repo ships tools/build_*_dependencies.sh scripts for this, which you hook into cibuildwheel via CIBW_BEFORE_ALL_*.
export KIVY_DEPS_ROOT=$(pwd)/ios-kivy-dependencies
export CIBW_BEFORE_ALL_IOS=./tools/build_ios_dependencies.sh
uv run --project ../myapp cibuildwheel --platform ios --archs all --output-dir ./wheelhouse
uv run ./tools/add-ios-frameworks.py ./wheelhouse
The final step embeds the dependency xcframeworks into the wheels — don't skip it, the wheels won't link on device without it.
Work in progress
Android wheels for Kivy 3.0.0 are not buildable out-of-the-box yet. The remaining pieces:
- A
build_android_dependencies.shbefore-all script (doesn't exist upstream yet) - Packaging of the ThorVG dependency for Android
- A post-build step to bundle SDL3 / ThorVG shared libraries into the wheel's
.libs/so they end up merged intosite-packages/.libs
Once those land, the build will look like:
# in your ksproject app root
export ANDROID_NDK_HOME=$(uv run ksproject android get-path ndk)
cd ../kivy # wherever you cloned it
export CIBW_BEFORE_ALL_ANDROID="./tools/build_android_dependencies.sh"
uv run --project ../myapp cibuildwheel --platform android --archs all --output-dir ./wheelhouse
Until then, use kivy2x for Android.
Using the Wheels in Your App¶
Copy the built wheels into your ksproject app's wheelhouse:
Then make sure your dependency constraint matches what you built:
Build as usual — uv resolves the wheelhouse via find-links and installs your wheels into the cross-compiled site-packages:
Verify which wheel was picked
The uv pip install output during the build lists the resolved distributions. A wheel installed from the wheelhouse shows a file:// path instead of an index URL.