Lock in $30 Savings on PRO—Offer Ends Soon! ⏳
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.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
[COSCUP2024] Catching up Trends in Audio App Development
atsushieno
0
470
Kotlin Multiplatformで MIDI 1.0/2.0 ライブラリを作っている話
atsushieno
1
660
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.3k
MML to MIDI 2.0 to DAW
atsushieno
1
2k
Other Decks in Technology
See All in Technology
PostgreSQL Conference Japan 2024 A4 Comparison of column-oriented access methods
nori_shinoda
0
120
検証と資産化を形にするプロダクト組織へ/tapple_pmconf2024
corin8823
1
7.8k
AWS認定試験の長文問題を早く解くコツ
keke1234ke
0
150
GAS × Discord bot × Gemini で作ったさいきょーの情報収集ツール
ysknsid25
1
680
Kubernetesを知る
logica0419
17
4.7k
asumikamというカンファレンスオーガナイザの凄さを語る / The Brilliance of Asumikam
tomzoh
1
290
[DevFestTokyo]Accelerating Flutter App Development Using Generative AI
korodroid
1
270
2024/12/05 AITuber本著者によるAIキャラクター入門 - AITuberの基礎からソフトウェア設計、失敗談まで
sr2mg4
2
510
EthernetベースのGPUクラスタ導入による学びと展望
lycorptech_jp
PRO
0
550
How is Cilium Tested?
yutarohayakawa
5
260
開志専門職大学特別講義 2024 デモパート
1ftseabass
PRO
0
210
プロダクトマネージャーは 事業責任者の夢をみるのか pmconf2024
gimupop
1
7.2k
Featured
See All Featured
Code Reviewing Like a Champion
maltzj
520
39k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
2
240
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Optimizing for Happiness
mojombo
376
70k
Producing Creativity
orderedlist
PRO
341
39k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
28
8.3k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
132
33k
jQuery: Nuts, Bolts and Bling
dougneiner
61
7.5k
The Power of CSS Pseudo Elements
geoffreycrofte
73
5.4k
Practical Orchestrator
shlominoach
186
10k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
10
770
StorybookのUI Testing Handbookを読んだ
zakiyama
27
5.3k
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 - みんなでカジュアルにライブラリを作ってエコシステムを育てていきましょう❢