Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Building Kotlin Multiplatform Libraries in 2024
Search
Atsushi Eno
June 21, 2024
Technology
4.6k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Building Kotlin Multiplatform Libraries in 2024
"2024年に公開するに相応しいKotlin Multiplatformライブラリを構築する" @ KotlinFest '24 (Jun. 22nd, Tokyo)
Atsushi Eno
June 21, 2024
More Decks by Atsushi Eno
See All by Atsushi Eno
Android and Audio Plugins: State of Union
atsushieno
1
78
Can we build a DAW with Compose Multiplatform? Maybe!
atsushieno
0
7
2026年に相応しい 最先端プラグインホストの設計<del>と実装</del>
atsushieno
0
150
Android Audio: Beyond Winning On It
atsushieno
0
6.4k
Can we build better music software ecosystems for more generative era?
atsushieno
0
790
Some Music Libraries for Kotlin (with some .NET -> Kotlin migration stories)
atsushieno
0
750
Building App Extensions equivalents on Android (maybe?)
atsushieno
1
930
Taking trends in music app development into the future mobile ecosystem
atsushieno
0
890
DTM entry level hands-on
atsushieno
0
770
Other Decks in Technology
See All in Technology
LayerXにおけるセキュリティ管理の現在地と次の一手
tosho
0
200
作って終わりにしない タイミーのセマンティックレイヤー育成の現在地
chanyou0311
4
2.4k
AIっぽい文章を採点して人間らしく直すアプリを作ってみた
yama3133
2
190
エンジニアリング戦略の作り方 / Crafting Engineering Strategy
iwashi86
21
6.9k
Oracle AI Database@Azure:サービス概要のご紹介
oracle4engineer
PRO
6
2k
20260619 私の日常業務での生成 AI 活用
masaruogura
1
210
日本 Fintech 未来予測レポート 2027〜2028年(手動編集版)
8maki
0
2.3k
失敗を経て、Harness Engineering で 大切にしたいことを考える / Learning from Failure: What Matters in Harness Engineering
bitkey
PRO
1
370
LayerX コーポレートエンジニアリング室におけるサプライチェーンセキュリティへの取り組み / Supply Chain Security at LayerX Corporate Engineering
yuyatakeyama
2
430
GitHub Copilot 最新アップデート – 「一歩先」の実践活用術
moulongzhang
3
820
ACE-Step-1.5で見る 音楽生成AIのしくみと“破綻だけ直す”Retake機能の開発【zennfes spring 2026 登壇資料】
personabb
1
480
FinOps × AIエージェントで実現する コストインシデントの自動調査
oasis1994liveforever
0
140
Featured
See All Featured
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
530
RailsConf 2023
tenderlove
30
1.5k
My Coaching Mixtape
mlcsv
0
150
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
360
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
370
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
160
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
54k
Optimizing for Happiness
mojombo
378
71k
Max Prin - Stacking Signals: How International SEO Comes Together (And Falls Apart)
techseoconnect
PRO
0
180
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
250
Designing for Timeless Needs
cassininazir
1
250
Transcript
Building Kotlin Multiplatform Libraries in 2024 2024年に公開するに相応しい Kotlin Multiplatformライブラリを構築する
What is this session about? KMP (Kotlin Multiplatform) ライブラリを開発する時に気に留めておくとよいことをいろ いろ話します
主なトピック: - KMPライブラリプロジェクトとモジュールの作り方 - 後方互換性 - Mavenパッケージの発行 - その他やっておくとよいこと
whoami? Kotlin libs created so far atsushieno/ktmidi also slides at
Kotlin愛好会#49, Foojay podcast #54 (6/24?) atsushieno/compose-audio-controls atsushieno/missing-dot (equivalents to .NET XML Reader/Writer, XLinq) sporadic contributions to antlr-kotlin, accompanist, nj2k (idea) etc...
ライブラリを作るってすごい? そんなことはないのでみんなカジュアルにやろう 再利用性のあるコードのモジュールを作って Mavenパッケージを発行するだけ(!) 最初から完璧を目指さなくてもいい 言語コミュニティの魅力はみんながライブラリでエコシステムを拡大できること
なぜMultiplatformでライブラリを作るの? • これまで対象外としていたプラットフォーム向けにアプリを出せる ◦ Google at I/O '24: • ライブラリのユーザー「これに依存したらターゲットが制限されるかも…」
◦ XMLを読み書きするライブラリが JVM/JSの実装しかなかった (2021) ◦ ComposeアプリをKMP化しようとしたらUIライブラリがAndroid専用だった (2024) ◦ Compose MPPアプリでwasm対応しようとしたらktor-ioが…(2024)
より良いライブラリを作るために • 可用性 (availability) を高める ◦ 幅広いターゲットをサポートする ◦ 最新バージョンの言語やツールチェインでも使えるようにする ◦
Mavenパッケージを発行する • 適切な粒度の公開APIがある ◦ 以前のバージョンとの 後方互換性を維持できる • APIドキュメントを公開/配布する even better: ネイティブ プラットフォーム言語でも使える =「実装言語としてのKotlin」
Library authors' guidelines (Kotlin公式) 最近アップデートされた (2024.6) https://kotlinlang.org/docs/api-guidelines-introduction.html 今日のトピックと内容がそこそこかぶる(!)
Create New Project
ライブラリプロジェクトのテンプレート https://kmp.jetbrains.com で作る Multiplatform Libraryテンプレートが便利 Maven設定も含まれていて便利
KMPのモジュール構成 KMP Project Wizardが作る構成がよくできている 従来 common, android, desktopなどが別々のモジュール 2024年 1つのモジュールで1つのKMPライブラリを構築できる
参照解決も project(":myLibrary") だけで可能 (Gradleプラグイン上での実現は単純ではない)
Multiplatformのターゲット 2024: 幅広いtarget • jvm (desktop), androidTarget • js (IR)
• native (desktop, ios*, android native(!) • wasmJs (alpha) ※最近のトレンド ターゲットを増やすとどうなる ? • common APIの制約に縛られる • ビルド時間が余計にかかる ターゲットを減らすとどうなる ? • 可用性が低くなり使ってもらえなくなる (!) どのターゲットをビルド対象にするかは開発者次第 (build.gradle.ktsで明示的に指定する) android nativeも一部のライブラリでは対応(kotlinx.datetimeなど)
Mavenパッケージとしてローカル発行する Kotlinライブラリは通常はMavenパッケージとして配布/参照する maven-publish Gradleプラグインを使う ./gradlew (build) publishToMavenLocal で mavenLocal リポジトリに発行
➡ 他のプロジェクトでも参照できるようになる (repositories { mavenLocal() } が必要) mavenLocalにあるパッケージの内容は以下のようなパスに格納される : $HOME/.m2/repository/dev/atsushieno/ktmidi-*/0.1.0/
Backward Compatibility
後方互換性(の問題)の種類 • APIの互換性 - 損なわれるとビルド時エラーになる • ABIの互換性 - 損なわれると実行時エラーになる •
挙動の互換性 - 損なわれると想定外の挙動になる 挙動の互換性はテストで担保する(しかない) ABIの互換性維持がとにかく重要 ABIを損なわないAPI互換性破壊は(相対的に)大した問題ではない
ABI互換性を維持するには? Q: 何を変更したらABI互換性が損なわれる? A: いろいろある… 例: 「data classを使うな」「関数の引数を増やすな」 Library authors'
guidelines(前出)が規範的情報源 ABI互換性チェックは ./gradlew check に組み込むと安心 Kotlin/binary-compatibility-validator (metalava-gradleなども使えるが、Kotlin生成コードで偽陽性を検出することもある)
Kotlin 2.0に移行する? [1/3] Q: K2でビルドしたライブラリはK2のプロジェクトでないと使えない? A: 理論上はnoだが、現実にはyesかもしれない 例: kotlinx.serialization: 1.7.0-RCはserialization
plugin 2.0.0-RC1以降を要求する (Gradleプラグインがエラーとして報告する) 回避?策 : serialization pluginだけkotlin 1.9.xを使う(ビルドは通るが安全性は不明 !)
Kotlin 2.0に移行する? [2/3] 例: K1でK2なライブラリを参照するとwasmJsビルドでコンパイラがクラッシュしうる (wasmJsターゲットは1.9.xではpreview機能だから想定の範囲内) ➡ 利用する側が1.9.xでビルドできないなら、K2の波に乗ってもらうしか無い(!)
Kotlin 2.0に移行する? [3/3] Q: ライブラリのサポート範囲を最大化するならKotlin 1.9.xに留まり続けるべき? A: Gradleプラグインが要求してこなければたぶん可能…? Compose compiler,
Serialization, KSP... コンパイラとstdlibとコンパイラプラグインのバージョンが統一されないといけないうちは たぶん解決できない問題
補遺: 依存ライブラリのバージョン選定 [1/3] Q: 依存関係解決時に同じライブラリの複数ver.を参照されたら、どう解決する? foo:libraryA:1.0.0 foo:libraryA:1.1.0 bar:libraryB:1.0.0 baz:libraryC:1.0.0 MyApplication
which one?😱
補遺: 依存ライブラリのバージョン選定 [2/3] A: 依存関係の距離が「近い」ほうが選ばれる🙃 Mavenの仕様なので仕方ない 問題が生じたら、ユーザーは望ましいバージョンのほうを「近づける」 (build.gradle(.kts) で明示的な dependencies
や resolutionStrategy を記述する)
補遺: 依存ライブラリのバージョン選定 [3/3] Q: 古いほうと新しいほう、参照するならどっちが望ましい? A: 一般的には新しいほうでよい(バグフィックス、パフォーマンス向上など) 大抵はsemantic versioningがきちんと機能していると期待できる(!?) •
場合によっては参照可能なバージョン範囲を指定しないといけないこともある Gradleには実際にはバージョン範囲を指定する方法が( mvnと同様に)存在する ただ、誰も使ってない (!?) • Renovateによる自動化もトレンドだが、 AGPなどIDEAの事情で上げられないものを考慮しない、 Composeの要求バージョンとの相性調整が必要など、運用にはまだ覚悟が必要そう
Publish
Mavenパッケージ発行までのワークフロー ./gradlew build publish でリモートリポジトリに発行できる CI経由でビルドの再現性・透明性・安全性を担保したほうが妥当 (CircleCI, Bitrise, GitHub Actions,
local Jenkins, ...) 2024年: mac/ios nativeターゲットはクロスコンパイルできないので macosビルドが必要… cf. youtrack KT-52666, KT-68323, KT-66944 2024年: Maven Centralへの発行が望ましい • jitpack: 自前ビルドするしpublishすら不要でこの上なく楽だけど、 mac/ios nativeが未サポート… • GitHub PackagesはDLにユーザー認証が必須なのが致命的 • jcenter (bintray)は発行受付停止
Sonatype Nexus [1/3] Maven Centralには承認されたサービス経由で 要件を満たすパッケージのみ発行できる • 開発者の電子署名があること • sourcesJar,
javadocJarがあること • 十分なパッケージメタデータがあること etc. etc. ➡ Sonatype Nexusが唯一的(?)な選択肢 日本語解説もいくつかある https://aakira.app/blog/2019/03/upload-kotlin-mpp-library/ (bintray時代) https://qiita.com/arashiyama/items/0c997126fb6ee0f9c8e7 Developer invalid package valid package Maven Central Package Publisher Agent
Sonatype Nexus [2/3] ⚠2024年2月以降の新規SonatypeユーザーはPortal Publisher APIの利用が必須 Sonatypeの正式なGradleサポートがまだ無い (!) https://central.sonatype.org/publish/publish-portal-gradle/ 非公式のコミュニティ
Gradleプラグインで対処するしかない( ↑で列挙あり) ⚠2024: ユーザー認証にSonatypeアカウント名を使わなくなった(移行期間中) 最新の仕組みではMavenユーザー名とパスワードを access tokenのように生成して使う
Sonatype Nexus [3/3] KMP Project WizardのMaven設定は2023年11月の古い設計なので利用できない (!) のでPublisher Portal API対応版のforkを作った
https://github.com/atsushieno/multiplatform-library-template-nexus-publisher 解説記事: https://zenn.dev/atsushieno/articles/d066e757c9640f
Going Further
APIリファレンスを発行する KDocを書いてDokkaでAPIリファレンスを発行する KMP Project WizardテンプレートではDokkaドキュメントが取り込まれないが、 DokkaJarを javadocJarとして認識させて提供したほうが良いしその方法もある https://github.com/gradle/gradle/issues/26091#issuecomment-1681343496 IDEAはDokkaJarのKDocを認識してコード補完等で表示してくれる GitHub
Actions:github-pages-deploy-actionも有用
Kotlinエコシステムの「外側」へ 各ターゲット「で」ネイティブ(?)ライブラリとして利用したい • .dll/.lib/.so/.a/.framework/.js/.wasm • npmにしてvscode拡張で参照したい やり方: build.gradle(.kts) の binaries.*
メソッドを呼ぶ • js, wasm: binaries.executable(), binaries.library() • native: binaries.executable(), binaries.staticLib(), binaries.sharedLib() ◦ mac, ios: binaries.framework { ... }
補遺: 複数のCIビルドの生成物を整合して発行する • 複数のCIホストからのビルドアーティファクトが必要になる場合がある ◦ mac/ios nativeターゲットはクロスコンパイルできない(macosホストを使えば解決) ◦ nativeターゲットをビルドするとき、cinteropで外部ライブラリもビルドしてリンクしていると、プラットフォームごとにビル ドしなければならなくなる
• ./gradlew publish では別々のNexusリポジトリがホスト分だけ生成される ➡ パッケージ発行時に競合が生じて失敗する • Sonatype NexusではWeb APIでリポジトリ作成と送信を別々に実行できるが、 2024年のGitHub Actionsではsecret (password) をもとに生成された変数の受け渡しができない 解決策 ➡ ホストごとに publishターゲットを細かく指定して重複しないように調整 … run: ./gradlew iosArm64Binaries packageDmg publishMacosArm64PublicationToOSSRHRepository PublishIosArm64PublicationToOSSRHRepository PublishIosSimulatorArm64PublicationToOSSRHRepository
NPMにKotlin/JSパッケージを発行 npm-publish Gradleプラグインを使う ./gradlew publish でnpmにも発行される ⚠Sonatype Nexusで失敗してもnpmで発行済のパッケージは取り消せない(逆も同じ)
作ったKMPライブラリを宣伝する KMPプロジェクトを作成したらここに載せて !と言われている(Kotlin公式ドキュメント) https://libs.kmp.icerock.dev/ Kotlin Foundation Grants (6/25まで) https://kotlinfoundation.org/grants/
Lastly - みんなでカジュアルにライブラリを作ってエコシステムを育てていきましょう❢