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
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
55
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
740
Building App Extensions equivalents on Android (maybe?)
atsushieno
1
930
Taking trends in music app development into the future mobile ecosystem
atsushieno
0
880
DTM entry level hands-on
atsushieno
0
770
[COSCUP2024] Catching up Trends in Audio App Development
atsushieno
0
930
Other Decks in Technology
See All in Technology
AI Adaptable なテストを整える工夫 / Ways to Make Your Tests AI-Adaptable
bitkey
PRO
2
200
大規模災害時でも高い信頼性を維持するアプリケーション基盤の実現/nikkei-tech-talk46
nikkei_engineer_recruiting
0
130
Sony_KMP_Journey_KotlinConf2026
sony
2
200
Oracle AI Database@Google Cloud:サービス概要のご紹介
oracle4engineer
PRO
6
1.5k
AIガバナンス実践 - 生成AIコネクタのデータ漏洩リスクと実務対策
knishioka
0
160
形式手法特論:公平性制約の位相的特徴づけ #kernelvm / Kernel VM Study Kansai 12th
ytaka23
1
670
Mastering Ruby Box
tagomoris
3
130
はじめてのDatadog
kairim0
0
260
「速く作る」から「正しく作る」へ ─ 生成AI時代の開発フロー改革の ロードマップと実行 ─
starfish719
0
1k
AIプラットフォームを運用し続けるための可観測性
tanimuyk
4
990
Claude Codeですべての日常業務を爆速化しよう!
minorun365
PRO
17
16k
JEP 522 Deep Dive - G1 GC同期コスト削減によるスループット向上を徹底検証&解説
tabatad
1
610
Featured
See All Featured
The Cost Of JavaScript in 2023
addyosmani
55
10k
Speed Design
sergeychernyshev
33
1.8k
Making the Leap to Tech Lead
cromwellryan
135
9.9k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.5k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
141
35k
YesSQL, Process and Tooling at Scale
rocio
174
15k
First, design no harm
axbom
PRO
2
1.2k
Jamie Indigo - Trashchat’s Guide to Black Boxes: Technical SEO Tactics for LLMs
techseoconnect
PRO
0
150
Navigating Algorithm Shifts & AI Overviews - #SMXNext
aleyda
1
1.3k
Fireside Chat
paigeccino
42
3.9k
Bootstrapping a Software Product
garrettdimon
PRO
307
120k
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.5k
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 - みんなでカジュアルにライブラリを作ってエコシステムを育てていきましょう❢