経緯
Kotlin Multiplatform で iOS / Android 両方から使える小さなライブラリを作成しました。Google Analytics for Firebase でイベントを送るにあたり、iOS / Android でイベントが違うことを防ぐために、Kotlin というワンソースでイベントをクラスとして定義して、iOS / Android アプリから使うことを意図しています。
Google Analytics for Firebase の基礎知識やこのライブラリで解決したい課題については、こちらの DroidKaigi 2024 登壇資料をご参照ください。
今回紹介するライブラリや GitHub Actions のワークフローは、こちらのリポジトリです。
Gradle プロジェクトおよびライブラリを作成
Android Studio Koala に Kotlin Multiplatform プラグインをインストールしました。Kotlin Multiplatform プロジェクトは New Project → Kotlin Multiplatform Library から作ります。
ライブラリの名前を Shared Module Name に設定します。
iOS framework distribution は XCFramework にします。
そうするとモジュールの build.gradle
には XCFramework を作るための設定が記載されます。
kotlin {
// 略
val xcf = XCFramework()
listOf(
iosX64(),
iosArm64(),
iosSimulatorArm64()
).forEach {
it.binaries.framework {
baseName = "ga913kmp"
xcf.add(this)
isStatic = true
}
}
// 略
}
ライブラリのソースコードは ga913kmp/src/commonMain/kotlin
に作ります。
(jvmMain
jvmTest
はローカル PC で動作するバリデーションとその単体テストで、記事の主題とは無関係です)
Swift Package Manager の使い方
次は Xcode で GitHub から Swift Package Manager 向けに配布されているライブラリを使用する方法を紹介します。Xcode は 16.0 を使っています。
ライブラリを使いたいプロジェクトを開いた状態で上部メニューの File → Add Package Dependency を選択します。
右上のテキスト検索欄にライブラリの GitHub ページの URL - 例えば https://github.com/tfandkusu/ga913-kmp を入力するとライブラリの情報が表示されます。ライブラリバージョンも指定できます。次に Add Package ボタンを押します。
最後に Target を選んで Add Package ボタンを押すと、ライブラリを選ばれた Target で使えるようになります。
Swift Package Manager から使えるようにライブラリを配布する
前述の方法で使用できるように、GitHub Actions を使いライブラリを自動配布します。
配布のためのワークフローはこちらになります。
VERSION ファイルに 0.1.2
等のようにバージョンを書き込み、release
ブランチに PUSH すると、ソースコードがビルドされ、ライブラリが配布されます。
ワークフローの内容を解説します。
まず Gradle タスクで XCFramework を作成します。
./gradlew assembleXCFramework
今回のモジュール名は ga913kmp
なので ga913kmp/build/XCFrameworks/release/
ディレクトリに作成されます。シミュレータ用と実機用のバイナリが生成されたことを確認できます。
cd ga913kmp/build/XCFrameworks/release/ga913kmp.xcframework/
find . -type f
./ios-arm64_x86_64-simulator/ga913kmp.framework/ga913kmp
./ios-arm64_x86_64-simulator/ga913kmp.framework/Headers/ga913kmp.h
./ios-arm64_x86_64-simulator/ga913kmp.framework/Modules/module.modulemap
./ios-arm64_x86_64-simulator/ga913kmp.framework/Info.plist
./ios-arm64/ga913kmp.framework/ga913kmp
./ios-arm64/ga913kmp.framework/Headers/ga913kmp.h
./ios-arm64/ga913kmp.framework/Modules/module.modulemap
./ios-arm64/ga913kmp.framework/Info.plist
./Info.plist
次に生成された XCFramework を ZIP で固めます。
zip -r ga913kmp.xcframework.zip ga913kmp.xcframework
Swift Package Manager は Package.swift
を読みに行くので Package.swift
ファイルを作ります。最終的にはこちらのファイルが作られます。
// swift-tools-version:5.5
import PackageDescription
let package = Package(
name: "ga913kmp",
products: [
.library(
name: "ga913kmp",
targets: ["ga913kmp"]
),
],
dependencies: [],
targets: [
.binaryTarget(
name: "ga913kmp",
url: "https://github.com/tfandkusu/ga913-kmp/releases/download/0.1.0/ga913kmp.xcframework.zip",
checksum: "54b04d1cad6dce83e100a387e8d54962cdbae7d34e4edb5b3790be84492b81c9"
),
]
)
url
フィールドに ZIP で固めた XCFramework のダウンロードパスがあり、そのチェックサムが checksum
フィールドに設定されます。url
と checksum
はバージョンごとに異なるので、新バージョンの配布ごとに作成する必要があります。
url
は GitHub Release の Asset の URL です。
checksum
はこちらのコマンドで作ります。
swift package compute-checksum ga913kmp/build/XCFrameworks/release/ga913kmp.xcframework.zip
Package.swift
ファイルは ejs テンプレートから作るようにしました。
// swift-tools-version:5.5
import PackageDescription
let package = Package(
name: "ga913kmp",
products: [
.library(
name: "ga913kmp",
targets: ["ga913kmp"]
),
],
dependencies: [],
targets: [
.binaryTarget(
name: "ga913kmp",
url: "https://github.com/tfandkusu/ga913-kmp/releases/download/<%= version %>/ga913kmp.xcframework.zip",
checksum: "<%= checksum %>"
),
]
)
VERSION=$(cat VERSION)
CHECKSUM=$(swift package compute-checksum ga913kmp/build/XCFrameworks/release/ga913kmp.xcframework.zip)
npx ejs Package.swift.ejs -i '{"version": "'$VERSION'", "checksum": "'$CHECKSUM'"}' -o Package.swift
Package.swift
ファイルを追加するコミットを作ります。
[skip ci]
をコミットメッセージに含めると、それについては GitHub Actions が動きません。
git config user.name "github-actions"
git config user.email "github-actions@github.com"
git add Package.swift
git commit -m "[skip ci]Package.swift を更新"
git push origin HEAD
VERSION
ファイルの内容をタグ名として PUSH し、リリースを作ります。
echo version=`cat VERSION` >> $GITHUB_ENV
# ${{ env.version }} に VERSION ファイルの内容が設定されている
git tag -a ${{ env.version }} -m "${{ env.version }}"
git push origin ${{ env.version }}
gh release create ${{ env.version }} -t ${{ env.version }} ga913kmp/build/XCFrameworks/release/ga913kmp.xcframework.zip
これで完了です。GitHub にはリリースが作られ、Swift Package Manager から使うことができます。
参考資料