Python3.10 + kivy-iosでiOSアプリをビルドする【Xcode16, 実機のみ対応】

目次

Briefcase を使ったときに興味が沸いたので、こちらでもやってみることにしました。

開発環境

バージョンの整合性を取るために、適宜古いバージョンを選定して使用していきます。

また、実機で動かすことが目的です。
シミュレーターは使いませんので、依存関係のビルド等も実機のみを対象にしていきます。

環境構築

Python 3.10系

当方、pyenvを使用しています。
仮想環境の立ち上げは後でやります。

python -V

>> Python 3.10.16

kivy-ios

git clone https://github.com/kivy/kivy-ios

# 以降はここがプロジェクトルートになる
cd kivy-ios

# python3.10系をターゲットとするリビジョンへcheckout
git checkout 6df5db389b7303c4cc9fd1c805ea1442fafa7eb4
python -m venv venv
source venv/bin/activate
pip install -U pip

依存ライブラリをインストールします。

pip install -e .
pip install packaging
このときの pip freeze
arrow==1.3.0
binaryornot==0.4.4
certifi==2025.4.26
chardet==5.2.0
charset-normalizer==3.4.2
click==8.2.1
cookiecutter==2.6.0
Cython==0.29.36
docopt==0.6.2
idna==3.10
Jinja2==3.1.6
kivy-ios==2023.8.24
markdown-it-py==3.0.0
MarkupSafe==3.0.2
mdurl==0.1.2
openstep_parser==2.0.1
packaging==25.0
pbxproj==4.2.1
pillow==11.2.1
Pygments==2.19.1
python-dateutil==2.9.0.post0
python-slugify==8.0.4
PyYAML==6.0.2
requests==2.32.4
rich==14.0.0
sh==2.2.2
six==1.17.0
text-unidecode==1.3
types-python-dateutil==2.9.0.20250516
typing_extensions==4.14.0
urllib3==2.4.0

kivy-iosのバージョンを確認します。

pip freeze | grep kivy-ios

# kivy-ios==2023.8.24

最新版kivy-ios

あとで必要になるので、最新版も落としておきます。
適当なディレクトリ newest_kivy-ios を作成して、その中にクローンしておきます。

mkdir newest_kivy-ios
cd newest_kivy-ios
git clone https://github.com/kivy/kivy-ios

最新版kivy-iosのリビジョンは以下の通りです。

cd kivy-ios
git rev-parse HEAD

# 70c89c2906ca3b79c5f070ef1f252942ac41a308
この時点でディレクトリ構造は以下のようになっています。
/path/to/kivy-ios
 ├── build
 ├── dist
 ├── get-pip.py
 ├── kivy_ios
 │   ├── __init__.py
 │   ├── recipes
 │   └── ... 省略
 ├── newest_kivy-ios
 │   └── kivy-ios
 ├── toolchain.py
 ├── venv
 └── ...省略

古いバージョンのkivy-iosの中に、最新版のkivy-iosがあります。

ここまできたらターミナルを新しくして仮想環境を立ち上げます。

依存関係のビルド(上から順に)

toolchain で依存関係(「レシピ」と言います)をビルドします。
ビルド成果物は build に配置され、依存関係のビルドの際に使用されます。
iOSアプリに組み込まれるのは dist 配下のものになります。

hostpython3

toolchain clean hostpython3
toolchain build hostpython3 --platform iphoneos-arm64

実機のみを対象とするので --platform iphoneos-arm64 を指定しています。

このあと、ビルドした hostpython3 のpipを使って色々インストールしていく中で警告が出るので、先に色々しておく。

# ビルドしたhostpython3があるパスへ移動
cd dist/hostpython3/bin

# pipをアップグレード
./python3.10 -m pip install --upgrade pip
./pip -V

./pip install cookiecutter
./pip install pbxproj
./pip install sh
このときの pip freeze
arrow==1.3.0
binaryornot==0.4.4
certifi==2025.4.26
chardet==5.2.0
charset-normalizer==3.4.2
click==8.2.1
cookiecutter==2.6.0
docopt==0.6.2
idna==3.10
Jinja2==3.1.6
markdown-it-py==3.0.0
MarkupSafe==3.0.2
mdurl==0.1.2
openstep_parser==2.0.1
pbxproj==4.2.1
Pygments==2.19.1
python-dateutil==2.9.0.post0
python-slugify==8.0.4
PyYAML==6.0.2
requests==2.32.4
rich==14.0.0
sh==2.2.2
six==1.17.0
text-unidecode==1.3
types-python-dateutil==2.9.0.20250516
typing_extensions==4.14.0
urllib3==2.4.0

環境変数の設定

hostpython3 のビルドができたら環境変数を設定してビルドしていきます。

export IOS_SDK=$(xcrun --sdk iphoneos --show-sdk-path)
export ARCHS=arm64
export ARCH_FLAGS="-arch arm64"
export PLATFORM=OS64
export SYSROOT="${IOS_SDK}"
export OPT_FLAGS="-O3 -g3"
export CC=$(xcrun -sdk iphoneos -find clang)
export CXX=$(xcrun -sdk iphoneos -find clang++)
export IPHONEOS_DEPLOYMENT_TARGET=18.0

邪魔になる可能性があるので、以下の環境変数を消しておきます。

unset CPPFLAGS
unset LDFLAGS
unset CFLAGS
unset CXXFLAGS

libffi

最新版kivy-iosからlibffiのレシピをまるっとコピーしてきてビルドします。

cp -f newest_kivy-ios/kivy-ios/kivy_ios/recipes/libffi/* kivy_ios/recipes/libffi
toolchain clean libffi
toolchain build libffi --platform iphoneos-arm64

sdl2など

toolchain clean sdl2 sdl2_image sdl2_mixer
toolchain build sdl2 sdl2_image sdl2_mixer --platform iphoneos-arm64

libpng

toolchain clean libpng
toolchain build libpng --platform iphoneos-arm64

🧨 失敗する場合の対策

最新版kivy-iosから libpng のレシピをまるっとコピーしてきて、もう一度ビルドしてみます。最新版はv1.6.48 がターゲットになってます。

cp -f newest_kivy-ios/kivy-ios/kivy_ios/recipes/libpng/* kivy_ios/recipes/libpng/

sdl2_ttf

最新版kivy-iosからレシピをコピーします。

cp -f newest_kivy-ios/kivy-ios/kivy_ios/recipes/sdl2_ttf/* kivy_ios/recipes/sdl2_ttf

次に、コピーしてきた sdl2_ttf の iOS の Minimum Deployments を 18.0 になるようにしたいので、レシピを修正します。
レシピクラスの build_platform で実行しているコマンドの引数に "IPHONEOS_DEPLOYMENT_TARGET=18.0" を追加します。

その後、ビルドします。

toolchain clean sdl2_ttf
toolchain build sdl2_ttf --platform iphoneos-arm64

python3

toolchain clean python3
toolchain build python3 --platform iphoneos-arm64

ios

toolchain clean ios
toolchain build ios --platform iphoneos-arm64

numpy

toolchain clean numpy
toolchain build numpy --platform iphoneos-arm64

pillowをビルドしてないので以下のようなエラーが出るがスルーする。

[DEBUG   ] ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
[DEBUG   ] kivy-ios 2023.8.24 requires Pillow, which is not installed.
[DEBUG   ] Successfully installed Cython-0.29.36

こんな結果で完了する。

[DEBUG   ] INFO: 
[DEBUG   ] ########### EXT COMPILER OPTIMIZATION ###########
[DEBUG   ] INFO: Platform      : 
[DEBUG   ]   Architecture: aarch64
[DEBUG   ]   Compiler    : unix-like
[DEBUG   ] 
[DEBUG   ] CPU baseline  : 
[DEBUG   ]   Requested   : 'min'
[DEBUG   ]   Enabled     : NEON NEON_FP16 NEON_VFPV4 ASIMD
[DEBUG   ]   Flags       : none
[DEBUG   ]   Extra checks: none
[DEBUG   ] 
[DEBUG   ] CPU dispatch  : 
[DEBUG   ]   Requested   : 'max -xop -fma4'
[DEBUG   ]   Enabled     : ASIMDHP ASIMDDP ASIMDFHM
[DEBUG   ]   Generated   : 
[DEBUG   ]               : 
[DEBUG   ]   ASIMDHP     : NEON NEON_FP16 NEON_VFPV4 ASIMD
[DEBUG   ]   Flags       : -march=armv8.2-a+fp16
[DEBUG   ]   Extra checks: none
[DEBUG   ]   Detect      : ASIMD ASIMDHP
[DEBUG   ]               : numpy/core/src/umath/_umath_tests.dispatch.c

[DEBUG   ] INFO: 
[DEBUG   ] ########### CLIB COMPILER OPTIMIZATION ###########
[DEBUG   ] INFO: Platform      : 
[DEBUG   ]   Architecture: aarch64
[DEBUG   ]   Compiler    : unix-like
[DEBUG   ] 
[DEBUG   ] CPU baseline  : 
[DEBUG   ]   Requested   : 'min'
[DEBUG   ]   Enabled     : NEON NEON_FP16 NEON_VFPV4 ASIMD
[DEBUG   ]   Flags       : none
[DEBUG   ]   Extra checks: none
[DEBUG   ] 
[DEBUG   ] CPU dispatch  : 
[DEBUG   ]   Requested   : 'max -xop -fma4'
[DEBUG   ]   Enabled     : ASIMDHP ASIMDDP ASIMDFHM
[DEBUG   ]   Generated   : none

NEON というのが重要みたいです。

pyobjus

toolchain clean pyobjus
toolchain build pyobjus --platform iphoneos-arm64

kivy

こちらも最新版kivy-iosからレシピをコピーしてきてビルドします。

cp -f newest_kivy-ios/kivy-ios/kivy_ios/recipes/kivy/* kivy_ios/recipes/kivy

v2.3.1 がターゲットになってました。

toolchain clean kivy
toolchain build kivy --platform iphoneos-arm64

アプリのソースを作成

まず、アプリのソースルートとなるフォルダを作成します。

mkdir src

当方、サンプルとしてsrcに以下ようなソースファイルを配置しました。
用意済みであれば不要です。

main.py
# -*- coding:utf-8 -*-
import os

from kivy import Config
from kivy.core.window import Window
from kivy.resources import resource_add_path


# ===== アプリ全体の設定 =====

# スクロール時にフォーカス中のTextInputを上にスクロールさせる
Window.softinput_mode = 'below_target'

# 最小移動量とタッチ時間を増やして、軽く触れたときに誤ってスクロールさせないようにする
Config.set('widgets', 'scroll_timeout', 400)  # 既定値は250
Config.set('widgets', 'scroll_distance', 100)  # 既定値は20

# リソースフォルダを指定
resource_add_path("kv")

# tesseractの言語データのパスを指定
os.environ['TESSDATA_PREFIX'] = "assets"

# ===== ====== =====


# 設定完了してから読み込む
from app import Application


if __name__ == '__main__':
    Application().run()
app.py
# -*- coding:utf-8 -*-

from kivy.app import App
from kivy.uix.boxlayout import BoxLayout


class TestScreen(BoxLayout):
    pass


class Application(App):

    def build(self):
        print("Python: 初期化")

        # kvファイルに定義したUIを読み込む
        # Builder.load_file("test.kv") # こっちでもOK
        self.load_kv("test.kv")

        return TestScreen()
kv/test.kv

<TestScreen>:
    BoxLayout:

        # テキトーな背景色をセットする
        canvas.before:
            Color:
                rgba: 1, 1, 1, 0.1
            Rectangle:
                size: self.size
                pos: self.pos

        Button:
            text: "Tap!"
            on_press: print("クリック!")
            size_hint: 0.5, 0.1
            pos_hint: {"center_x": 0.5, "center_y": 0.5}
            background_color: "orange"

Xcodeでビルド

Xcodeプロジェクトを作成します。

toolchain create {アプリ名} src

{アプリ名}-ios というフォルダができます。
その中にある {アプリ名}.xcodeproj をXcodeで開いてiOSビルドに必要な設定をしていきます。

作業項目はだいたい以下のような感じになると思います。

タブ名セクション選択・操作内容
GeneralSupported Destinations「iPhone」だけにする
Mininum Deplayments18.0(iOS 18)
Deployment Info「Landscape」と「Hide during …」を外す
Frameworks, Libraries, and Embedded ContentFrameworks フォルダ内の赤文字になっているもの(リンク切れ)を全部追加しなおしてリンク切れを解消。
リンク切れの方をフォルダから削除。
Signing & CapabilitiesTeam, Bundle Identifier自分のAppleIDで署名して、チームを選択。
Build PhasesLink Binary With LibrariesFrameworks フォルダ内のファイルで、ないものがあればここに追加する
Build Options > User Script SandboxingNo(rsyncやSandboxのエラーが出る場合、必要に応じて)

Signing & Capabilitiesに関する作業はこちらで詳しくやっていますので参考になれば。

Python × Briefcase で iOS アプリをビルドするまでの道のり

上記の表すべて対応できたら、自分のiOSデバイスを選択してビルドします。

Xcodeのコンソール上に色々エラーやら警告が出てますが、とりあえず起動できました。
「Tap!」をタップすると、Xcodeのコンソール上にログが出ます。

ここまでお読みいただき、ありがとうございました。