通常のKMMプロジェクトでは、sharedモジュールのコードをiOS側でも使用できるようにFrameworkとして生成している。
ここでは、sharedモジュールをFrameworkではなくXCFrameworkとして生成する方法をまとめる。
環境
- KMM:v0.3.3
- Kotlin:v1.7.0
- iOS framework distribution:Regular framework
- NewProjectでKotlin Multiplatform Appを選択した状態とする
デフォルトで生成されるFrameworkについて
NewProjectでKotlin Multiplatform Appを選択してビルドした場合、初期状態ではsharedモジュールをFrameworkとして生成するようになっている。
Frameworkは RootProject/shared/build/bin/に環境ごとに生成される。
- Arm64用のFramework
- Simulator Arm64用のFramework
- X64用のFramework
Frameworkの場合だとArm64の実機用、Arm64のシミュレータ用など異なったフレームワークを使用することになるが、XCFrameworkを使用することで、統一して1つのフレームワークを使用することが可能になる。
XCFrameworkとして生成する方法
-
build.gradle.ktsで以下を追加する
// 追加1 import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework ... kotlin { // 追加2 val xcf = XCFramework() listOf( iosX64(), iosArm64(), iosSimulatorArm64() ).forEach { it.binaries.framework { baseName = "shared" // 追加3 xcf.add(this) } } }
-
gradlewコマンドでビルドする
$ ./gradlew build ... BUILD SUCCESSFUL in 1s
するとXCFrameworkを生成する以下のタスクが登録される。
assembleXCFramework
assembleSharedDebugXCFramework
assembleSharedReleaseXCFramework
実際にタスクが登録されているかは以下のコマンドで確認できる。(DebugとReleaseのコマンドに関しては表示されない)
$ ./gradlew tasks ... assembleXCFramework - Assemble all types of registered 'shared' XCFramework
assembleXCFrameworkはDebug用とRelease用の両方を生成するため、状況に合わせてDebugのXCFrameworkのみを生成するassembleSharedDebugXCFrameworkを使用するなどすると良さそう。
-
生成コマンドを叩く
$ ./gradlew assembleXCFramework
これでXCFrameworkが生成された
生成されたXCFrameworkについて
XCFrameworkは RootProject/shared/build/XCFrameworks/に生成される。
前述した通り、XCFrameworkの場合Frameworkの時のようにArm64用・X64用のような環境ごとに生成はされず、1つのXCFrameworkにまとめられている。
Xcode側でXCFrameworkを参照する
-
Run Scriptの変更
Build SettingのKMM用のRun Scriptに先ほど生成したassembleXCFramework
コマンドを設定することで、Xcodeでビルド時にXCFrameworkを生成させる# デフォルトが以下 cd "$SRCROOT/.." ./gradlew :shared:embedAndSignAppleFrameworkForXcode # 変更後 cd "$SRCROOT/.." ./gradlew :shared:assembleSharedDebugXCFramework
-
Framework Search Pathsの変更
Build SettingのFramework Search Pathsを、XCFrameworkのpathへと変更する# デフォルトが以下 $(SRCROOT)/../shared/build/xcode-frameworks/$(CONFIGURATION)/$(SDK_NAME) # 変更後 $(SRCROOT)/../shared/build/XCFrameworks
-
Other Linker Flagsの変更
Buid SettingのOther Linker Flagsに設定されているの以下が不要になるので削除する# 削除する $(inherited) -framework shared
-
Frameworks, Libraries, and Embedded Contentへの追加
shared.xcframeworkモジュールを追加する。
+ボタン → Add Other Filesから、生成された.xcframeworkを選択する
↓
これでXCFrameworkを参照できるようになった。
.swiftファイルでimport sharedするとエラーが出ないことを確認できる。
import shared
XCFrameworkの名前を指定している場合
build.gradle.ktsで XCFrameworkの名前を指定した場合、コマンドは以下のように変更となる
assemble<”XCFrameworkの名前”>XCFramework
assemble<”XCFrameworkの名前”>DebugXCFramework
assemble<”XCFrameworkの名前”>ReleaseXCFramework
<”XCFrameworkの名前”>の箇所は、build.gradle.ktsで XCFramework(””)を生成したときに指定した名前を入れる。
以下の例だと”Hoge”が入っているので
val xcf = XCFramework("Hoge")
assembleHogeXCFramework
となる。
XCFrameworkの名前が変わっているので、importするときもsharedではなく、import Hogeになる
import Hoge
終わりに
最近KMMを触る機会が多いのですが、iOSエンジニアがKMMを触るのはGradleだったりAndroid周りの知識だったりが必要なので学習コストが高いなと感じました。
KMM触る時は是非身近なAndroidエンジニアを巻き込むことをお勧めします。