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
1
4.5k
Building Kotlin Multiplatform Libraries in 2024
"2024年に公開するに相応しいKotlin Multiplatformライブラリを構築する" @ KotlinFest '24 (Jun. 22nd, Tokyo)
Atsushi Eno
June 21, 2024
Tweet
Share
More Decks by Atsushi Eno
See All by Atsushi Eno
Android Audio: Beyond Winning On It
atsushieno
0
6.3k
Can we build better music software ecosystems for more generative era?
atsushieno
0
750
Some Music Libraries for Kotlin (with some .NET -> Kotlin migration stories)
atsushieno
0
710
Building App Extensions equivalents on Android (maybe?)
atsushieno
1
870
Taking trends in music app development into the future mobile ecosystem
atsushieno
0
830
DTM entry level hands-on
atsushieno
0
730
[COSCUP2024] Catching up Trends in Audio App Development
atsushieno
0
910
Kotlin Multiplatformで MIDI 1.0/2.0 ライブラリを作っている話
atsushieno
1
900
building_audio_plugin_ecosystem_on_Android.pdf
atsushieno
0
1.2k
Other Decks in Technology
See All in Technology
ソフトバンク流!プラットフォームエンジニアリング実現へのアプローチ
sbtechnight
1
200
VPCエンドポイント意外とお金かかるなぁ。せや、共有したろ!
tommy0124
1
710
JAWS DAYS 2026 AWS知識・技術力を使って隠された旗をゲットせよ!〜出張版「ごーとんカップ」〜 解説編
kaminashi
0
110
脳内メモリ、思ったより揮発性だった
koutorino
0
390
Go 1.26 Genericsにおける再帰的型制約 / Recursive Type Constraints in Go 1.26 Generics
ryokotmng
0
140
実践 Datadog MCP Server
nulabinc
PRO
2
240
中央集権型を脱却した話 分散型をやめて、連邦型にたどり着くまで
sansantech
PRO
1
110
AWSの資格って役に立つの?
tk3fftk
2
370
TypeScript 7.0の現在地と備え方
uhyo
7
1.9k
最強のAIエージェントを諦めたら品質が上がった話 / how quality improved after giving up on the strongest AI agent
kt2mikan
0
200
OCI技術資料 : コンピュート・サービス 概要
ocise
4
54k
品質を経営にどう語るか #jassttokyo / Communicating the Strategic Value of Quality to Executive Leadership
kyonmm
PRO
2
660
Featured
See All Featured
Testing 201, or: Great Expectations
jmmastey
46
8.1k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.2k
Tips & Tricks on How to Get Your First Job In Tech
honzajavorek
0
460
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
52
5.9k
The Organizational Zoo: Understanding Human Behavior Agility Through Metaphoric Constructive Conversations (based on the works of Arthur Shelley, Ph.D)
kimpetersen
PRO
0
270
SEO for Brand Visibility & Recognition
aleyda
0
4.4k
The Language of Interfaces
destraynor
162
26k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
254
22k
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
150
Scaling GitHub
holman
464
140k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
2
250
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
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 - みんなでカジュアルにライブラリを作ってエコシステムを育てていきましょう❢