CLI tool
kivy/kivy-ios avatar
kivy/kivy-ios

kivy-ios: the recipe based toolchain that compiles Python and Kivy for iOS

Toolchain for compiling Python / Kivy / other libraries for iOS

856 stars253 forksPythonMIT

At a glance

What is it?
kivy-ios is a macOS only toolchain that cross compiles Python, SDL2 and other native dependencies into an iOS bundle and then generates an Xcode project for your app directory. Nothing ships prebuilt, so the first run compiles everything twice, once for the device and once for the simulator.
Who is it for?
kivy-ios fits a Python developer who wants to ship a Kivy application on iOS and is prepared to work on a Mac with Xcode, to compile every native dependency twice before the first build, and to keep a Python runtime inside the app bundle. It does not fit a team that wants a CI pipeline without macOS, an app store submission without native code, or a build under time pressure, since the first compile is a long operation and there are no binary distributions to shortcut it.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

No binaries means a first build you plan for

kivy-ios is a toolchain to compile the necessary libraries for iOS to run Kivy applications, and to manage the creation of Xcode projects. Two statements in its own documentation set the expectations. The first is that no binary distributions of the toolchain are provided. The second is that you do need to compile it at least once before creating your Xcode project.

The supported targets are iPhone on iOS in arm64, and the iPhone Simulator on x86_64 and arm64. Since Xcode only runs on macOS, the toolchain is only useful on that platform, which makes this a Mac-only story from the first step.

Installation follows the ordinary Python packaging path. The documentation strongly advises using a virtual environment first:

code
python3 -m venv venv
. venv/bin/activate

And the package itself installs with pip like any other Python package:

code
pip3 install kivy-ios

There are also system dependencies to install: Xcode 13 or above with an iOS SDK and command line tools, installed through `xcode-select --install`, and a set of Homebrew packages:

code
brew install autoconf automake libtool pkg-config
brew link libtool

The project is managed by the Kivy Team, is MIT licensed, and can be used together with Buildozer. The packaging guide for iOS lives at kivy.org, and the package is published on PyPI as kivy-ios.

Recipes are how dependencies get onto the device

Any Python extension or C and C++ library has to be compiled for the target, and the toolchain's answer is what it calls a recipe. The documentation is explicit that the recipe contains the dependencies, the compilation and the packaging instructions, and gives Python, libffi, SDL2, SDL_image and freetype as examples.

The available recipes and their versions can be listed directly:

code
    $ toolchain recipes
    audiostream  master
    click        7.1.2
    cymunk       master
    ffmpeg       n4.3.1
    ffpyplayer   v3.2
    flask        1.1.2
    freetype     2.5.5
    hostlibffi   3.2.1
    hostopenssl  1.1.1g
    hostpython3  3.7.1
    ios          master
    itsdangerous 1.1.0

That list is the single most useful thing to read before committing to this toolchain, because it is where the version risk lives. The pins are old: python3 at 3.7.1, kivy at 1.10.1, numpy at 1.16.4, pillow at 6.1.0, pyyaml at 3.11. Several recipes are at master, which means they track the upstream default branch rather than a fixed release. If your application depends on a newer version of one of these libraries, you are not going to get it from the stock recipe list.

There is also a note that some recipes are not yet ported to the new toolchain, with lxml named as the example. That is a per-recipe compatibility statement, and it is the kind of thing that decides whether a given dependency set is workable at all.

The recipe format itself is shared with the Python-for-Android project, and the documentation directs you to that project's recipe documentation for the details, which means the documentation is shared even though the two toolchains target different platforms.

Building takes two passes because there are two platforms

Compilation starts with the toolchain build command naming the recipes you need:

code
$ toolchain build python3 kivy

And you can name several at once to let the dependency graph resolve itself:

code
$ toolchain build python3 openssl kivy

The dependency structure is what makes the kivy recipe convenient. The kivy recipe depends on the sdl recipes and the python recipes, and those depend in turn on others, with sdl2_ttf depending on freetype for example. The documentation describes it as the kivy recipe compiling everything necessary for a minimal working version of Kivy, which is the practical shortcut: you name the top-level recipe and the graph is walked for you.

Packages that need no compilation go through pip instead:

code
$ toolchain pip install plyer

And a build can be discarded with the clean command:

code
$ toolchain clean openssl

The one thing to internalise is the time cost. The documentation puts it plainly: do not just grab a coffee, do dinner, because compiling all the libraries for the first time, twice over, takes time. The twice matters. The targets are iOS and the iPhone Simulator, so a full first-time compile happens for both, and the recipe list includes substantial native projects such as OpenSSL, SDL2 and its image, mixer and ttf modules, freetype, libpng, libjpeg and, if you want it, ffmpeg.

For a complete list of what the tool can do, the bare invocation is the reference:

code
$ toolchain

Generating the Xcode project and the sync trap

The toolchain.py script creates the initial Xcode project from an application directory:

code
$ toolchain create <title> <app_directory>
$ toolchain create Touchtracer ~/code/kivy/examples/demo/touchtracer

The application directory must contain a main.py, and a directory named <title>-ios is created with the Xcode project inside it. You then open it:

code
$ open touchtracer-ios/touchtracer.xcodeproj

After that you press Play in Xcode and the app runs.

There is a workflow rule buried in the documentation that will save you an afternoon if you learn it now. Every time you press Play, your application directory is synced to the <title>-ios/YourApp directory, and the documentation says not to make changes in the -ios directory directly. In other words, the generated project directory is a build artefact, not your source of truth. Edit the app directory, and let the sync carry the changes across.

The configuration surface is the standard Xcode one, with the caveat that Xcode requires icons and launch images to be specified per device or per iOS version. On first build, a main.m file is created in the Xcode project folder, and that file configures the environment variables and controls application startup, so it is where you customise the launch environment. Because Kivy uses SDL, the launch image disappears as soon as the SDL main starts, and to prevent that you need two files named Default.png and Default-Landscape.png placed in the Resources folder in Xcode rather than in your application folder.

Orientation is another detail with a specific answer. To restrict the app's orientation you do it through the export_orientation function in main.m, and the Xcode orientation settings should be set to support all, rather than the other way around.

Trimming the bundle without breaking it

The bundle carries a full Python interpreter and its standard library, so size reduction is a real concern and the documentation offers three levers.

The first is the zip file holding the Python modules, named with the pattern build/pythonX/lib/pythonXX.zip. You can edit that zip and remove files you will not use, with the documentation suggesting reducing encodings and removing xml and email as examples. This is a surgical edit rather than a configuration flag, so it is manual work that has to be redone whenever the bundle is rebuilt.

The second lever is the strip options in the settings panel under build, and the warning is emphatic: triple-check that they are all set to NO. Stripping does not work with Python dynamic modules and will remove needed symbols. That is a failure that produces a broken app at runtime rather than a build error, which is exactly why it is worth reading before you set it rather than after.

The third lever is architecture pruning. By default the iOS package compiles binaries for all processor architectures, namely x86_64 and arm64, following Apple's guidelines, and the documentation says you can reduce the size of the ipa significantly by removing x86_64, which is the simulator slice that does not need to ship to devices.

Taken together, the three levers are a manual trimming workflow rather than a switch, and each carries a specific failure mode. The zip edit silently drops modules, the strip setting breaks dynamic loading, and the architecture removal is safe for device builds but breaks the simulator path.

Where kivy-ios is the wrong tool

The first constraint is hard: this only works on macOS. Because Xcode only runs there, there is no path to building an iOS app from a Linux CI runner, and a project whose entire continuous integration runs on Linux containers cannot use this toolchain without adding a Mac runner. There are no binary distributions of the toolchain either, so the compile cost is not avoidable by a hosted service.

The second constraint is the recipe version set. With python3 at 3.7.1, kivy at 1.10.1 and numpy at 1.16.4 in the default list, an application built on a modern Python and a recent Kivy release is not a straightforward fit. The recipes are meant to be forked and edited, and some are already at master, so the work of maintaining your own recipe set is part of the cost of using it.

The third is the workflow shape. The tool generates an Xcode project and expects a human in Xcode to press Play, with the sync rule that the -ios directory is derived output. That is workable for an individual developer and awkward for a team that wants reproducible scripted builds, and it puts the iOS signing and provisioning configuration into Xcode rather than into a script.

The alternative is worth naming. If the goal is a Python application on iOS without a Kivy interface, there are other routes that avoid shipping a whole SDL stack, and if the goal is a Kivy interface on both platforms, maintaining a single codebase across mobile and desktop has different costs that this toolchain does not address. The honest comparison is with the effort of running the Python for Android toolchain, since they share the recipe model, and with writing a native or Flutter application, which trade the shared Python codebase for a simpler app store story.

Editorial conclusion

kivy-ios fits a Python developer who wants to ship a Kivy application on iOS and is prepared to work on a Mac with Xcode, to compile every native dependency twice before the first build, and to keep a Python runtime inside the app bundle. It does not fit a team that wants a CI pipeline without macOS, an app store submission without native code, or a build under time pressure, since the first compile is a long operation and there are no binary distributions to shortcut it. Before starting, check that the recipe versions the toolchain offers still match what your app needs, since the list includes older pins such as python3 3.7.1 and kivy 1.10.1, confirm your Xcode is 13 or above with the command line tools installed, and read the size reduction guidance before packaging, since stripping the binaries breaks Python dynamic modules.

Frequently asked questions

How do I install kivy-ios and what do I need first?

The toolchain is a pip package, so `pip3 install kivy-ios` inside a virtual environment is the install step. You also need Xcode 13 or above with the iOS SDK and command line tools installed through `xcode-select --install`, plus autoconf, automake, libtool and pkg-config from Homebrew. Since Xcode only runs on macOS, the toolchain is only useful there.

What are recipes and how do I see which libraries are available?

A recipe holds the dependencies, compilation and packaging instructions for one Python extension or C and C++ library, and `toolchain recipes` lists them with their versions. The format is shared with the Python-for-Android project, whose recipe documentation covers the details.

How long does the first build take?

The documentation is blunt about it: compiling all the libraries for the first time, twice over, takes time, and you should plan dinner rather than a coffee. The twice is because the toolchain targets both iOS and the iPhone Simulator, so a full first-time compile happens for each.

How do I create the Xcode project for my app?

Run `toolchain create <title> <app_directory>` with an application directory that contains a main.py. A directory named <title>-ios is created holding the Xcode project, and you open it with `open touchtracer-ios/touchtracer.xcodeproj`.

How do I reduce the size of the packaged app?

You can edit build/pythonX/lib/pythonXX.zip to remove unused modules, you should leave the strip options in the build settings panel set to NO because stripping breaks Python dynamic modules, and you can drop the x86_64 architecture slice since the default build includes both x86_64 and arm64 binaries.

Official sources

  1. kivy/kivy-ios on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/kivy-kivy-ios.svg)](https://hysenlabs.com/projects/kivy-kivy-ios)

Was this useful?