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
0
3.2k
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
[COSCUP2024] Catching up Trends in Audio App Development
atsushieno
0
300
Kotlin Multiplatformで MIDI 1.0/2.0 ライブラリを作っている話
atsushieno
1
620
building_audio_plugin_ecosystem_on_Android.pdf
atsushieno
0
1.1k
get updated to the latest realtime audio processings knowledge base (2023) (再履修: 2023年までの リアルタイムオーディオ処理)
atsushieno
1
1.1k
learning how DAWs work, with Zrythm
atsushieno
0
1.1k
What for, Where and How to Adopt MIDI 2.0
atsushieno
0
1.2k
audio plugin format study meetup 2022.7.6 (JP)
atsushieno
0
1.6k
CLAPオーディオプラグイン is 何?
atsushieno
1
1.2k
MML to MIDI 2.0 to DAW
atsushieno
1
2k
Other Decks in Technology
See All in Technology
今日から始める技術的負債の解消
leveragestech
3
440
AWS DDKを利用したDataOps事始め
beex
1
160
Delta Commit…の最近...
akuwano
2
110
Cosmos DB で持続可能な RAG を実現しよう!~ AOAI Dev Day ふりかえりを添えて / Sustainable RAG with Cosmos DB with recap AOAI Dev Day
miyake
0
170
地域DXにおけるGrafana活用事例
wacky
0
370
ゼロからはじめる生成AI〜AWS認定とハンズオンで学ぶ初心者の道〜
kenichinakamura
0
130
組織デバイスのための効率的なアプリケーション更新戦略
kenchan0130
0
450
外部カンファレンスで登壇しよう! 〜「強い」エンジニアへの一歩を踏み出す〜
logica0419
4
130
Japan AWS Jr. Championsがお届けする、アウトプットのすすめ
hamijay_cloud
0
190
運営11年目タイトルを守る最強の盾の有効性と活用法
mixi_engineers
PRO
2
120
管理画面とユーザー機能の調和を取り戻す!~クエリパフォーマンス改善の成功物語~ / Restore harmony between administrative and user functions!
minisera
1
190
Microsoft 365 でデータセキュリティを強化しよう
sophiakunii
2
450
Featured
See All Featured
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
250
21k
Building Your Own Lightsaber
phodgson
102
6k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
43
6.5k
Art, The Web, and Tiny UX
lynnandtonic
296
20k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
5
130
Put a Button on it: Removing Barriers to Going Fast.
kastner
58
3.5k
A Tale of Four Properties
chriscoyier
156
22k
Product Roadmaps are Hard
iamctodd
PRO
48
10k
Into the Great Unknown - MozCon
thekraken
31
1.4k
How to Ace a Technical Interview
jacobian
275
23k
How to Think Like a Performance Engineer
csswizardry
18
1k
Designing for Performance
lara
604
68k
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 - みんなでカジュアルにライブラリを作ってエコシステムを育てていきましょう❢