Upgrade to Pro — share decks privately, control downloads, hide ads and more …

KSPの導入・移行を前向きに検討しよう!

shxun6934
September 11, 2024

 KSPの導入・移行を前向きに検討しよう!

DroidKaigi 2024 のセッションスライド

9/12 14:20 ~
https://2024.droidkaigi.jp/timetable/694249/

shxun6934

September 11, 2024
Tweet

Other Decks in Programming

Transcript

  1. > KSP is a more efficient replacement for kapt. For

    libraries that support both, KSP should be used to improve build times. KSP は、kapt より効率的な代替ツール 両方サポートしている場合は、ビルド時間を改善するために KSP を使用すべ き https://googlesamples.github.io/android-custom-lint-rules/checks/KaptUsageInsteadOfKsp.md.html
  2. @shuxn6934 name: しゅんいち - shxun6934 affiliation: PORT INC. Occupation: Android

    アプリ エンジニア / Rails エンジニア service: 就活会議 Android
  3. Agenda • KSP ◦ kapt ◦ annotation processor (Java) •

    KSP・kaptの特徴と比較 • KSPの実装・導入・移行方法 ◦ 単純な導入 ◦ SymbolProcessorでの導入 ◦ 検証 ◦ 検討 • KSP2 • まとめ
  4. Agenda • KSP ◦ kapt ◦ annotation processor (Java) •

    KSP・kaptの特徴と比較 • KSPの実装・導入・移行方法 ◦ 単純な導入 ◦ SymbolProcessorでの導入 ◦ 検証 ◦ 検討 • KSP2 • まとめ
  5. What is KSP Kotlin Symbol Processing Kotlin の軽量なCompiler Plugin を開発するための

    API Kotlin の機能を活用して、簡略化された Compiler Plugin を提供 2021年にstable Kotlin 1.5.30 〜 Document: https://kotlinlang.org/docs/ksp-overview.html GitHub: https://github.com/google/ksp
  6. What is kapt Kotlin Annotation Processing Tool Kotlin でAnnotation processor

    を使用する ためのツール 2016年にstable Kotlin 1.0 〜 Document: https://kotlinlang.org/docs/kapt.html GitHub: kapt3: https://github.com/JetBrains/kotlin/tree/master/plugins/kapt3 kapt4: https://github.com/JetBrains/kotlin/tree/master/plugins/kapt4
  7. What is Annotation Processor Pluggable Annotation Processing API Compile 時にAnnotation

    付きのソースコードを解析し、追加のコードや リソースを生成する Compiler Plugin Java 6 〜 (2006) JSR269: https://jcp.org/en/jsr/detail?id=269
  8. Agenda • KSPとは ◦ kapt ◦ annotation processor (Java) •

    KSP・kaptの特徴と比較 • KSPの実装・導入・移行方法 ◦ 単純な導入 ◦ SymbolProcessorでの導入 ◦ 検証 ◦ 検討 • KSP2 • まとめ
  9. kapt’s features • Annotation からコードを生成 • Kotlin からJava のコードを生成 •

    Annotation Processor に対応しているLibrary に対して利用可能 • メンテナンスモード(2021 〜) • K2 Compiler へのサポート(Experimental)
  10. kapt’s features • Annotation からコードを生成 • Kotlin からJava のコードを生成 •

    Annotation Processor に対応しているLibrary に対して利用可能 • メンテナンスモード(2021 〜) • K2 Compiler へのサポート(Experimental)
  11. kapt’s task • kaptGenerateStubs ◦ Kotlin Compiler によるスタブ作成 ◦ androidTest・main・test

    ◦ BuildVariantsごと • kapt ◦ Annotation Processor によるコード生成 ◦ androidTest・main・test ◦ BuildVariantsごと
  12. kapt’s task • kaptGenerateStubs ◦ Kotlin Compiler によるスタブ作成 ◦ androidTest・main・test

    ◦ BuildVariantsごと • kapt ◦ Annotation Processor によるコード生成 ◦ androidTest・main・test ◦ BuildVariantsごと
  13. kaptGenerateStubs Annotation Processor がKotlin のコードを読み取るために、Java のスタ ブクラスを生成 • クラス・メソッド・プロパティ・インターフェースなどの定義 •

    型情報 生成されたJavaファイルには、@kotlin.Metadataが含まれている → KotlinとJavaの相互運用 を可能にしている
  14. k: エンコードするメタデータの種類(数値ごとに意味が決まっている) mv: メタデータのバージョン == Kotlinバージョン d1: カスタム形式のメタデータ d2: d1への追加情報

    xs: 文字列型での追加情報 pn: パッケージ名 xi: 数値型での追加情報(数値ごとに意味が決まっている) ※ Kotlin 2.0 ※ Kotlinのバージョンによって異なる @kotlin.Metadata https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-metadata/
  15. kapt’s task • kaptGenerateStubs ◦ Kotlin Compiler によるスタブ作成 ◦ androidTest・main・test

    ◦ BuildVariantsごと • kapt ◦ Annotation Processor によるコード生成 ◦ androidTest・main・test ◦ BuildVariantsごと
  16. kapt’s features • Annotation からコードを生成 • Kotlin からJava のコードを生成 •

    Annotation Processor に対応しているLibrary に対して利用可能 • メンテナンスモード( 2021 〜) • K2 Compiler へのサポート( Experimental)
  17. Maintenance Mode > We are keeping it up-to-date with recent

    Kotlin and Java releases but have no plans to implement new features. Kotlin・Java のリリースを追ってアップデートはしている ただし、kaptに対する新機能開発が計画されていない https://kotlinlang.org/docs/kapt.html https://github.com/JetBrains/kotlin-web-site/commit/755eec6d7e41dee9b39c1c427f0dd884cfb20b4a
  18. Support for K2 Compiler (kapt) Kotlin 1.9.20 〜(Experimental) K2 Compiler上でkaptを使用することができる

    → パフォーマンスが向上 https://blog.jetbrains.com/kotlin/2023/11/kotlin-1-9-20-released/ https://kotlinlang.org/docs/kapt.html#try-kotlin-k2-compiler
  19. KSP

  20. KSP’s features • Kotlin のソースコードをKotlin で解析し、コード生成できる • Multi Platform 対応

    (JVM・JS・Native) • コードの変更・置換はできない • K2 Compiler へのサポート(Beta) == KSP2
  21. KSP’s features • Kotlin のソースコードを Kotlin で解析し、コード生成できる • Multi Platform

    対応 (JVM・JS・Native) • コードの変更・置換はできない • K2 Compiler へのサポート(Beta) == KSP2
  22. KSP’s task • ksp ◦ Symbol Processor によるコード解析・コード生成 ▪ 生成先:Java

    or Kotlin ▪ Annotation に限らない ◦ androidTest・main・test ◦ BuildVariantsごと ※ Symbol Processor については後半で!
  23. KSP’s features • Kotlin のソースコードをKotlin で解析し、コード生成できる • Multi Platform 対応

    (JVM・JS・Native) • コードの変更・置換はできない • K2 Compiler へのサポート(Beta) == KSP2
  24. Code cannot be changed (KSP) > Unlike a full-fledged compiler

    plugin, processors cannot modify the code. A compiler plugin that changes language semantics can sometimes be very confusing. KSP avoids that by treating the source programs as read-only. 言語のセマンティクス(意味や動作を定義する概念)を変更してしまうと、予期し ない意味・動作になり混乱を招くため 、書き込みを行えないようにしている https://kotlinlang.org/docs/ksp-overview.html#overview
  25. Compare KSP with kapt • コード生成方法が異なる ◦ kapt: Kotlin →

    Java(stub) → Java(impl) ◦ KSP: Kotlin → Java or Kotlin(impl)
  26. Compare KSP with kapt • コード生成方法が異なる ◦ kapt: Kotlin →

    Java(stub) → Java(impl) ◦ KSP: Kotlin → Java or Kotlin(impl) ビルド時間差に起因
  27. Compare KSP with kapt • コード生成方法が異なる ◦ kapt: Kotlin →

    Java(stub) → Java ◦ KSP: Kotlin → Java or Kotlin • 将来性 ◦ kapt: K2 Compiler (Experimental) ◦ KSP: K2 Compiler (Beta) https://kotlinlang.org/docs/components-stability.html#stability-levels-explained
  28. Agenda • KSPとは ◦ kapt ◦ annotation processor (Java) •

    KSP・kaptの特徴と比較 • KSPの実装・導入・移行方法 ◦ 単純な導入 ◦ SymbolProcessorでの導入 ◦ 検証 ◦ 検討 • KSP2 • まとめ
  29. Introduce・Migrate • KSP のGradle Plugin を定義 • (kapt を使用している場合は、kapt のGradle

    Plugin を削除) • Library のAnnotation Processor をksp で依存定義 • (ksp のオプション設定追加) • (kapt のオプション設定を削除) https://developer.android.com/build/migrate-to-ksp
  30. Implementation • (Annotation classを用意) • SymbolProcessorProvider と SymbolProcessor を実装 •

    META-INF/services/com.google.devtools.ksp.processing.S ymbolProcessorProvider に、実装した SymbolProcessorProvider を宣言 ※ 公式からもサンプルコードが提供されているので、参考に! Example:https://github.com/google/ksp/tree/main/examples/playground
  31. Implementation (Sample) • ViewModelFactory Annotation を作成 • ViewModel を継承したクラスに ViewModelFactory

    Annotationを付 与すると、ViewModelProvider.Factory を継承したクラスを生成
  32. Get Kotlin Symbol • getAllFiles:全ラウンドの全てのファイルを取得する • getNewFiles:ラウンドごとの全てのファイルを取得する • getSymbolsWithAnnotation:特定のAnnotation が付与された

    Symbol を全て取得(ラウンドごと) etc … https://github.com/google/ksp/blob/main/api/src/main/kotlin/com/google/devtools/ksp/ processing/Resolver.kt
  33. Get Kotlin Symbol • getAllFiles:全ラウンドの全てのファイルを取得する • getNewFiles:ラウンドごとの全てのファイルを取得する • getSymbolsWithAnnotation:特定のAnnotation が付与された

    Symbol を全て取得(ラウンドごと) etc … https://github.com/google/ksp/blob/main/api/src/main/kotlin/com/google/devtools/ksp/ processing/Resolver.kt
  34. Multi Round processing SymbolProcessor#process は複数回に実行する 一つ一つの実行 == ラウンド SymbolProcessor#process の返り値に処理できなかったSymbol

    のリス トを設定 → 次ラウンドで処理される 全ラウンドで新しいファイルが生成されなくなると終了 https://kotlinlang.org/docs/ksp-multi-round.html
  35. Dependencies • aggregating = false, sources = listOf(A.kt) ◦ A.kt

    への変更がある時のみ 再生成 • aggregating = true, sources = listOf(A.kt) ◦ 他のファイルへの変更がある時に A.kt も対象になる https://github.com/google/ksp/blob/main/api/src/main/kotlin/com/google/devtools/ksp/processing/CodeGe nerator.kt#L179-L206
  36. Verify (Environment) • M3 Pro Macbook Pro ◦ Memory 36GB

    ◦ MacOS 14.4 • Gradle 8.5 • Kotlin 1.9.0 • KSP 1.9.0-1.0.13 • room 2.6.1
  37. Verify • db ◦ kapt ◦ KSP • app (==

    view_model_factory) ◦ kapt ◦ KSP それぞれの Gradle task を10回行った平均秒数を比較
  38. • db ◦ kapt:0.718 s ◦ KSP:0.592 s • app

    ◦ kapt:0.539 s ◦ KSP:0.215 s Result
  39. • db ◦ kapt:0.718 s ◦ KSP:0.592 s • app

    ◦ kapt:0.539 s ◦ KSP:0.215 s Result + 17.46 % + 60.14 %
  40. Verify (Environment) • M3 Pro Macbook Pro ◦ Memory 36GB

    ◦ MacOS 14.4 • Gradle 8.5 • Kotlin 1.9.24 • KSP 1.9.24-1.0.20 • room 2.6.1 • hilt 2.52
  41. Verify • room (KSP) + hilt (KSP) • room (KSP)

    + hilt (kapt) • room (kapt) + hilt (kapt) それぞれの Gradle task を10回行った平均秒数を比較
  42. Result • room (KSP) + hilt (KSP):1.077 s • room

    (KSP) + hilt (kapt):1.571 s • room (kapt) + hilt (kapt):1.312 s
  43. Result • room (KSP) + hilt (KSP):1.077 s • room

    (KSP) + hilt (kapt):1.571 s • room (kapt) + hilt (kapt):1.312 s - 19.73 %
  44. Result • room (KSP) + hilt (KSP):1.077 s • room

    (KSP) + hilt (kapt):1.571 s • room (kapt) + hilt (kapt):1.312 s + 17.89 %
  45. Verification result • 移行により、ビルド時間の改善 が見込める ◦ ※ Project により差が出る •

    実装を行うことで、Project にあったコード生成を自動で行える ◦ 例:計測用のタグ生成 • 併用だと、逆にビルド時間の悪化 になる ◦ 移行は一気に行う ▪ モジュール単位で移行・導入を検討する
  46. Agenda • KSPとは ◦ kapt ◦ annotation processor (Java) •

    KSP・kaptの特徴と比較 • KSPの実装・導入・移行方法 ◦ 単純な導入 ◦ SymbolProcessorでの導入 ◦ 検証 ◦ 検討 • KSP2 • まとめ
  47. KSP2 K2 Compiler 上で動くKSP KSP 1.0.21 〜(Beta) Kotlin 2.0.0 〜

    gradle.properties に ksp.useKSP2=true を追加 Github: https://github.com/google/ksp/blob/main/docs/ksp2.md
  48. KSP2 • Compiler Plugin → Compiler API • エントリポイントを他のプログラムから呼び出せるようになった •

    KSP APIの動作が一部変更 https://github.com/google/ksp/blob/main/docs/ksp2.md# ksp1-deprecation-schedule
  49. KSP2 • Compiler Plugin → Compiler API • エントリポイントを他のプログラムから呼び出せるようになった •

    KSP APIの動作が一部変更 https://github.com/google/ksp/blob/main/docs/ksp2.md# ksp1-deprecation-schedule
  50. SymbolProcessor in Program • Processor をロード • Logger を実装する or

    KspGradleLogger を使用する • KSPConfig を設定 • KotlinSymbolProcessing を実行 https://github.com/google/ksp/blob/main/docs/ksp2entrypoints.md
  51. 各Platform ごとのConfigクラスが用意されている • KSPJvmConfig:JVM • KSPNativeConfig:Native • KSPJsConfig:JS • KSPCommonConfig:Common(MultiPlatform)

    KSPConfig https://github.com/google/ksp/blob/2.0.0-1.0.22/common-deps/src/main/kotlin/com/google/devtools /ksp/KSPConfig.kt
  52. Agenda • KSPとは ◦ kapt ◦ annotation processor (Java) •

    KSP・kaptの特徴と比較 • KSPの実装・導入・移行方法 ◦ 単純な導入 ◦ SymbolProcessorでの導入 ◦ 検証 ◦ 検討 • KSP2 • まとめ
  53. Conclution • KSPは、Annotation が付与された Kotlin コードを別の Kotlin・Java コードに生成 ◦ kapt

    と比べて高速で、 Multi Platform に対応 • GradlePlugin・Library を追加することで、導入・移行可能 • SymbolProcessor・Provider を実装することで、実装可能 • K2 Compiler 上で動く新しい KSP == KSP2 • KSP2では、KSPのデバッグ・テストが簡単に
  54. References • https://github.com/google/ksp • https://kotlinlang.org/docs/ksp-overview.html • https://kotlinlang.org/docs/ksp-quickstart.html • https://kotlinlang.org/docs/ksp-why-ksp.html •

    https://kotlinlang.org/docs/ksp-examples.html • https://kotlinlang.org/docs/ksp-additional-details.html • https://kotlinlang.org/docs/ksp-reference.html • https://kotlinlang.org/docs/ksp-incremental.html • https://kotlinlang.org/docs/ksp-multi-round.html • https://blog.jetbrains.com/kotlin/2023/11/kotlin-1-9-20-released/ • https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-metadata/ • https://blog.jetbrains.com/kotlin/2015/06/better-annotation-processing-supporting-stubs-in-kapt/ • https://github.com/JetBrains/kotlin-web-site/pull/2591 • https://jcp.org/en/jsr/detail?id=269 • https://developer.android.com/build/migrate-to-ksp • https://inside.pixiv.blog/2023/05/23/110000 • https://tech.every.tv/entry/2024/06/20/095753 • https://star-zero.medium.com/annotation-processor%E3%81%A7kotlin-metadata-789b36c76a1a • https://qiita.com/kitakkun/items/f8702d5975809c2bea05 • https://kotlinlang.org/docs/k2-compiler-migration-guide.html • https://blog.jetbrains.com/kotlin/2015/05/kapt-annotation-processing-for-kotlin/ • https://kotlinlang.org/docs/k2-compiler-migration-guide.html • https://kotlinlang.org/docs/gradle-configure-project.html
  55. End