0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ライブラリ/モジュールのGradle/Mavenの依存関係伝搬について

Last updated at Posted at 2022-11-13

ライブラリやモジュールを作る時、依存関係を伝搬させるかどうかという話が出てきます。
この考え方をちょっと勘違いしていました。

通常、依存関係のあるライブラリはimplementationを使います。

implementation("com.example.library:library:1.0.0")

これがライブラリで、pomファイルを出力すると、scopeはruntimeとなります。

<dependency>
  <groupId>com.example.library</groupId>
  <artifactId>library</artifactId>
  <version>1.0.0</version>
  <scope>runtime</scope>
</dependency>

一方、依存関係をライブラリ/モジュールの利用側に伝搬させたい場合は、apiを利用します。

api("com.example.library:library:1.0.0")

これがライブラリで、pomファイルを出力すると、scopeはcompileとなります。

<dependency>
  <groupId>com.example.library</groupId>
  <artifactId>library</artifactId>
  <version>1.0.0</version>
  <scope>compile</scope>
</dependency>

依存関係の伝搬

ライブラリ/モジュール(以下module)でimplementation(scopeがruntime)で指定されている場合、ライブラリ/モジュールの利用側(以下app)には、依存関係が伝搬しないため、appでも同一のライブラリを使いたい場合は、依存関係を書く必要があります。

module/build.gradle.kts
dependencies {
    implementation("com.example.library:library:1.0.0")
}
app/build.gradle.kts
dependencies {
    implementation(project(":module"))
    // libraryの依存関係を書いていないので、appの中ではlibraryを使用することは不可能
}

moduleの実行にはlibraryが必要なので、あくまでappのコンパイル時に参照できないだけで、実行時には使われるように組み込まれます。
appで同様に依存関係を書いた場合は、appのコンパイル時にも使うことができます。バージョンについては、コンパイル時に使用するバージョンは、両者のうち新しい方のバージョンが採用されます。
moduleで指定しているバージョンの方が新しい場合、moduleで指定したバージョンでappがコンパイルされ、組み込まれます。

module/build.gradle.kts
dependencies {
    implementation("com.example.library:library:2.0.0")
}
app/build.gradle.kts
dependencies {
    implementation(project(":module"))
    implementation("com.example.library:library:1.0.0")
    // moduleで指定しているバージョンの方が新しいので、2.0.0が使われる
}

moduleで指定しているバージョンの方が古い場合、appで指定したバージョンでappがコンパイルされ、組み込まれます。

module/build.gradle.kts
dependencies {
    implementation("com.example.library:library:1.0.0")
}
app/build.gradle.kts
dependencies {
    implementation(project(":module"))
    implementation("com.example.library:library:2.0.0")
    // appで指定しているバージョンの方が新しいので、2.0.0が使われる
    // moduleが2.0.0を使って再コンパイルされるわけではない
}

ただし、moduleが、appを指定したバージョンを組み込んで再コンパイルされるわけではありませんので、バイナリ互換性のないバージョン差分があると、問題が起こる場合があります。(例:FusedLocationProviderClientがclassからinterfaceになった。ライブラリとのバージョン不一致に気をつけろ)これについては指定方法を変えてもかわりませn

moduleでapi(scopeがcompile)で指定されている場合、app側で依存関係を書かなくても自動的に依存関係に含まれるため、app側で指定する必要がなくなります。

module/build.gradle.kts
dependencies {
    api("com.example.library:library:1.0.0")
}
app/build.gradle.kts
dependencies {
    implementation(project(":module"))
    // libraryの依存関係を書いていなくても、appのなかでlibraryを使用可能
}

両者で指定している場合の挙動はimplementationの場合と同一です。

どういうときに依存関係を伝搬させるべきか

依存関係を伝搬させると、利用側では依存関係を書く必要がなくなります。違いはそれだけですね。
よって、そのライブラリ/モジュールを利用する上で、別のライブラリが必要な場合に依存関係を伝搬させるべきですね。

具体的に言うと、moduleがHogeというクラスを提供しており、そのHogeクラスを利用する上で必要なクラスFugaがlibraryから提供されているものの場合ですね。

module
class Hoge(fuga: Fuga)

この場合、moduleはlibraryの依存関係を伝搬させた方がよいでしょう。

0
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?