gradle Kotlin,Java Spring

【Gradle備忘】implementation,runtimeOnly...などの違い

Gradle使ってて「implementation」とか「runtimeOnly」とかあるけど、これ何が違うんだ??となったのでメモ。

依存のさせ方意味
implementation依存関係を定義する。一番一般的なもの。
apiimplementationとベースは一緒だが、依存が伝播する
runtimeOnlyコンパイルする時には要らないけど、実行時には必要なやつ。
compileOnly実行する時には要らないけど、コンパイル時には必要なやつ。

runtimeOnlyを使う例

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    runtimeOnly 'org.postgresql:postgresql:42.3.8'
}
  • JPAでコード書いたら「コンパイルしないといけないし、実行時にも必要」なのでimplementation
  • DBのドライバは実行時にあればいいので、runtimeOnly

compileOnlyを使う例

  • Lombokの役割は「我々が書くソースファイルにおけるボイラープレートコード(GetterとかSetterとか)の排除」
  • ソースファイルから実行ファイル作る(=compile)ときに自動でGetter Setter作ってもらうだけ。実行時には意味なし。
  • なのでcompileOnly
dependencies {
    compileOnly 'org.projectlombok:lombok:1.18.30'
    annotationProcessor 'org.projectlombok:lombok:1.18.30'
}

apiの挙動

// Aモジュールのbuild.grale
// JPAを利用
dependencies {
    api 'org.springframework.boot:spring-boot-starter-data-jpa'
}

// Bモジュールのbuild.grale
// Aに依存している
dependencies {
    implementation project(':A')
}

この時、BモジュールでもJPAが使えて、関連クラスがimportできたりする。(依存関係が伝播していく)

(Bモジュールの保守チームからしたら、暗黙的に定義されたAの依存関係も意識しないといけないから、めんどくさそう...)

とは言っても、どう使い分ける?

以下、山根の意見です。

  • 基本は全部implemetationで良さそう。
  • よっぽどの理由がない限り、apiは基本使わない方向が良さそう。(必要になるケースがあまり思いつかない。。)
  • runtimeOnly/compileOnly/implementationにするか迷うぐらいなら、基本はimplementationを選択する、で良さそう。ビルドが軽くなるメリットより、判断コストが大きくなるデメリットの方が大きい気がする。正しい依存のさせ方については、「アプリが大きくなって、ビルド時間を短くしたくなってきたら」考えることのような気がする。

元ネタ

https://docs.gradle.org/current/userguide/java_library_plugin.html#java_library_plugin
https://docs.gradle.org/current/userguide/dependency_configurations.html

-gradle, Kotlin,Java, Spring