Contents
1️⃣ 環境構築 ― 必要なツールとインストール手順
| カテゴリ | 推奨バージョン(2024‑04 時点) | 備考 |
|---|---|---|
| Android Studio | Flamingo 2023.3.2 以上 | KMP 用テンプレートが標準装備 |
| Kotlin プラグイン | 1.9.22(Kotlin DSL) | kotlin("multiplatform") が利用可能 |
| JDK | OpenJDK 17(または 21) | Gradle のデフォルト JVM |
| Android SDK | API 34(Android 14)以上 | compileSdk = 34 を推奨 |
| Xcode | 15.0 以降 | iOS シミュレータ実行に必須 |
| Node.js | 20 LTS | JS/WasM ビルドに使用 |
| CocoaPods (macOS) | 1.12 以上 | iOS 用ネイティブ依存管理 |
1‑1 インストール手順(Windows / macOS 共通)
- Android Studio のダウンロード
-
公式サイトから「Flamingo」版を取得し、インストーラを実行。
-
Kotlin Multiplatform プラグインの導入
-
File > Settings > Plugins > Marketplace(macOS はPreferences)で Kotlin を検索し、Install→ 再起動。 -
JDK の設定
-
JDK 17(または 21)をインストール後、
Settings > Build, Execution, Deployment > Build Tools > Gradleにて Gradle JVM に指定。 -
macOS だけの追加作業
bash
xcode-select --install # コマンドラインツール有効化
sudo gem install cocoapods # CocoaPods インストール(必要に応じて) -
Node.js のインストール
- 公式サイトの LTS バイナリをダウンロード、または
brew install node@20(macOS)で導入。
Tip:全ツールが正しくパスに通っているかは、端末で
java -version,node -v,xcodebuild -versionなどを実行して確認してください。
2️⃣ Kotlin Multiplatform プロジェクトの作成
2‑1 プラグインと Wizard の有効化
- プラグイン:上記で導入した Kotlin プラグインが自動的に
kotlin-multiplatformを提供します。 - Wizard:Android Studio の「New Project」ダイアログに Kotlin Multiplatform App テンプレートが表示されます。
2‑2 Wizard で選択できる主な項目
| 項目 | 推奨設定例 |
|---|---|
| Project name | MyKmpApp |
| Package name | com.example.mykmpapp |
| Shared module type | Kotlin Multiplatform Library |
| Android UI | Compose |
| iOS UI | SwiftUI (UI を共有しない) |
| Web target | JS + Wasm |
| 有効化するプラットフォーム | android, iosX64/iosArm64/iosSimulatorArm64, js(IR), wasmJs |
Wizard が生成したプロジェクトは次のような構造になります(抜粋):
|
1 2 3 4 5 6 7 8 9 10 11 12 |
MyKmpApp/ ├─ shared/ │ └─ src/ │ ├─ commonMain/kotlin/ │ ├─ androidMain/kotlin/ │ ├─ iosMain/kotlin/ │ └─ jsMain/kotlin/ ├─ androidApp/ │ └─ src/main/… └─ iosApp/ └─ Sources/… |
2‑3 expect / actual の具体例(初心者向け)
|
1 2 3 4 5 6 7 8 9 |
// shared/src/commonMain/kotlin/com/example/util/Platform.kt package com.example.util /** * 現在実行中のプラットフォーム名を取得する関数。 * 各プラットフォームで実装 (actual) を提供します。 */ expect fun platformName(): String |
|
1 2 3 4 5 |
// shared/src/androidMain/kotlin/com/example/util/Platform.kt package com.example.util actual fun platformName(): String = "Android ${android.os.Build.VERSION.SDK_INT}" |
|
1 2 3 4 5 6 7 8 |
// shared/src/iosMain/kotlin/com/example/util/Platform.kt package com.example.util import platform.UIKit.UIDevice actual fun platformName(): String = UIDevice.currentDevice.systemName + " " + UIDevice.currentDevice.systemVersion |
commonMain から platformName() を呼び出すだけで、実行環境に応じた文字列が得られます。
3️⃣ Gradle 設定のベストプラクティス
3‑1 root build.gradle.kts
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
plugins { // Kotlin Multiplatform のコアプラグイン(最新安定版) kotlin("multiplatform") version "1.9.22" id("com.android.application") version "8.4.0" apply false } repositories { google() mavenCentral() } // 共通の Gradle プロパティは gradle.properties に記述 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
// shared/build.gradle.kts plugins { kotlin("multiplatform") } kotlin { // ── ターゲット定義 ─────────────────────── android() iosX64() iosArm64() iosSimulatorArm64() js(IR) { browser() nodejs() } wasmJs { browser() } // ── ソースセットと依存関係 ─────────────── sourceSets { val commonMain by getting { dependencies { implementation(kotlin("stdlib-common")) implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0") } } val androidMain by getting { dependencies { implementation("androidx.core:core-ktx:1.13.0") implementation("androidx.compose.ui:ui:1.6.0") } } val iosMain by creating { dependsOn(commonMain) dependencies { implementation("io.ktor:ktor-client-ios:2.3.8") } } val jsMain by getting { dependencies { implementation("org.jetbrains.kotlin-wrappers:kotlin-react:18.2.0-pre.734") } } // テスト用 val commonTest by getting { dependencies { implementation(kotlin("test-common")) implementation(kotlin("test-annotations-common")) } } } } |
3‑3 Android アプリモジュール
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// androidApp/build.gradle.kts plugins { id("com.android.application") kotlin("android") } android { compileSdk = 34 defaultConfig { applicationId = "com.example.mykmpapp" minSdk = 21 targetSdk = 34 versionCode = 1 versionName = "1.0" } } |
3‑4 iOS アプリモジュール(CocoaPods 統合)
|
1 2 3 4 5 6 7 8 |
# iosApp/Podfile platform :ios, '15.0' use_frameworks! target 'iosApp' do pod 'shared', :path => '../shared' end |
ポイント:
pod install --repo-updateを CI の最初に実行すれば、バージョン不整合を防げます。
3‑5 ビルド速度向上のための gradle.properties
|
1 2 3 4 5 |
org.gradle.parallel=true kotlin.incremental.native=true android.useAndroidX=true android.enableR8.fullMode=false # R8 の高速化(リリースビルドに限定) |
4️⃣ ビルド・実行・テストの手順と CI 設定
4‑1 ローカルでのビルドコマンド
| プラットフォーム | コマンド例 |
|---|---|
| Android | ./gradlew :androidApp:assembleDebug |
| iOS(シミュレータ) | xcodebuild -workspace iosApp/iosApp.xcworkspace -scheme iosApp -destination 'platform=iOS Simulator,name=iPhone 15,OS=latest' build |
| JS (ブラウザ) | ./gradlew :jsApp:browserDevelopmentRun |
| Wasm | ./gradlew :wasmApp:wasmJsBrowserRun |
4‑2 GitHub Actions(完全版)
以下のワークフローは macOS ランナー 上で Android と iOS のテストを自動化し、JS/WasM は Linux ランナーで実行します。iOS シミュレータのセットアップ手順も含めています。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# .github/workflows/kmp-ci.yml name: KMP CI on: push: branches: [ main ] pull_request: jobs: test-common: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v3 with: distribution: temurin java-version: 17 - name: Build & test common JVM code run: ./gradlew :shared:testDebugUnitTest test-android: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up JDK 17 uses: actions/setup-java@v3 with: distribution: temurin java-version: 17 - name: Install Android SDK uses: android-actions/setup-android@v2 - name: Build & test Android run: | ./gradlew :androidApp:assembleDebug ./gradlew :androidApp:testDebugUnitTest test-ios: runs-on: macos-latest env: SIMULATOR_NAME: iPhone 15 OS_VERSION: latest steps: - uses: actions/checkout@v4 # JDK と CocoaPods の準備 - name: Set up JDK 17 uses: actions/setup-java@v3 with: distribution: temurin java-version: 17 - name: Install CocoaPods run: sudo gem install cocoapods # iOS シミュレータの作成・起動 - name: Create & boot iOS simulator run: | xcrun simctl list devices available | grep "${{ env.SIMULATOR_NAME }}" || \ xcrun simctl create "${{ env.SIMULATOR_NAME }}" com.apple.CoreSimulator.SimDeviceType.iPhone-15 com.apple.CoreSimulator.SimRuntime.iOS-${{ env.OS_VERSION }} xcrun simctl boot "${{ env.SIMULATOR_NAME }}" || true sleep 30 # 起動待機 - name: Install Pods working-directory: iosApp run: pod install --repo-update - name: Build & test iOS on simulator run: | xcodebuild \ -workspace iosApp/iosApp.xcworkspace \ -scheme iosApp \ -destination "platform=iOS Simulator,name=${{ env.SIMULATOR_NAME }},OS=${{ env.OS_VERSION }}" \ clean build test test-js-wasm: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Node.js 20 uses: actions/setup-node@v4 with: node-version: '20' - name: Build & test JS run: ./gradlew :jsApp:test - name: Build & test Wasm run: ./gradlew :wasmApp:test |
ポイント解説
test-iosジョブでは simctl によるシミュレータ作成・起動を明示的に行うため、GitHub の macOS ランナーでの「Simulator not found」エラーを回避できます。- iOS テストは Xcode の
xcodebuild testを使用し、-destinationにシミュレータ情報を渡すだけで実行可能です。 - Android と共通コードは Linux ランナーでもビルドできるため、ジョブの並列実行が速くなります。
5️⃣ 実務で活かすベストプラクティスとトラブルシューティング
5‑1 共有コードの境界を意識する
| 領域 | 推奨実装例 |
|---|---|
| ロジック(ビジネスルール、データ処理) | commonMain に Kotlin の純粋関数として置く。 |
| UI | 各プラットフォーム固有の *Main で Compose / SwiftUI を実装し、インタフェースだけを expect/actual で共有する。(例:expect fun Modifier.applyPlatformStyle(): Modifier) |
| ネイティブ API 呼び出し | expect 関数で抽象化し、プラットフォームごとに actual を提供。 |
5‑2 依存関係は一元管理
- Version Catalog(libs.versions.toml)
toml
[libraries]
coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.0"
ktorClientIos = "io.ktor:ktor-client-ios:2.3.8"
[plugins]
kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version = "1.9.22" }
androidApplication = { id = "com.android.application", version = "8.4.0" }
implementation(libs.coroutines) の形で参照し、バージョンの食い違いを防止します。
- 各モジュールは
5‑3 ビルド速度の最適化
| 手法 | 設定例 |
|---|---|
| 並列ビルド | org.gradle.parallel=true(gradle.properties) |
| ネイティブインクリメンタル | kotlin.incremental.native=true |
| Android ビルド高速化 | android.enableR8.fullMode=false(デバッグ時のみ) |
| キャッシュの有効活用 | CI では actions/cache@v3 を使い、~/.gradle/caches と ~/.gradle/wrapper を保存。 |
5‑4 よくある問題と対処法
| 問題 | 原因 | 解決策 |
|---|---|---|
| Gradle Sync が失敗 | Kotlin プラグインのバージョンが build.gradle.kts と不一致 |
Android Studio の「Plugins」画面でプラグインを最新に統一し、./gradlew --stop && ./gradlew cleanBuildCache を実行 |
iOS ビルドで pod install が失敗 |
CocoaPods リポジトリが古い | pod repo update 後に再度 pod install。CI では --repo-update オプションを必ず付与 |
| Wasm ビルドがタイムアウト | Node のバージョンが非対応 | Node.js 20 LTS にアップデートし、Gradle デーモンを無効化 (--no-daemon) して実行 |
| GitHub Actions でシミュレータが起動できない | macOS ランナーのデフォルトイメージに対象デバイスが存在しない | xcrun simctl create コマンドで必要なシミュレータを事前作成(上記ワークフロー参照) |
6️⃣ まとめ(要点)
- 環境構築は Android Studio Flamingo 2023.3.2、Kotlin 1.9.22、JDK 17/21、Xcode 15、Node.js 20 がベース。
- Wizardで
shared,androidApp,iosApp,js/wasmの四層構造を即生成し、expect / actualによるプラットフォーム分離が容易になる。 - Gradle 設定は root で Kotlin Multiplatform プラグインを管理し、各モジュールは
kotlin {}ブロックでターゲット・sourceSet を宣言。Version Catalog により依存バージョンの一元化が可能。 - ビルド・テストは CLI タスクだけで完結し、GitHub Actions では macOS と Linux のマトリクスを組むことで Android/iOS/JS/WasM をすべて自動検証。iOS シミュレータの作成・起動手順も含めた完全版ワークフローを提供。
- 運用上のベストプラクティスは「共有ロジックと UI の分離」「依存管理の集中化」「ビルド速度最適化」の三本柱。典型的なトラブル(Gradle sync、CocoaPods、Wasm タイムアウト)への対処法も網羅。
- 以上を実践すれば Kotlin Multiplatform を用いた Android・iOS・Web アプリの開発・テスト・CI が安定し、同一コードベースから複数プラットフォームへ迅速にリリースできるようになります。
本稿は執筆時点(2024 年 4 月)の情報を基にしています。ツールのバージョンが更新された場合は、公式ドキュメントをご確認ください。