ライブラリやモジュールを作る時、依存関係を伝搬させるかどうかという話が出てきます。
この考え方をちょっと勘違いしていました。
通常、依存関係のあるライブラリは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でも同一のライブラリを使いたい場合は、依存関係を書く必要があります。
dependencies {
implementation("com.example.library:library:1.0.0")
}
dependencies {
implementation(project(":module"))
// libraryの依存関係を書いていないので、appの中ではlibraryを使用することは不可能
}
moduleの実行にはlibraryが必要なので、あくまでappのコンパイル時に参照できないだけで、実行時には使われるように組み込まれます。
appで同様に依存関係を書いた場合は、appのコンパイル時にも使うことができます。バージョンについては、コンパイル時に使用するバージョンは、両者のうち新しい方のバージョンが採用されます。
moduleで指定しているバージョンの方が新しい場合、moduleで指定したバージョンでappがコンパイルされ、組み込まれます。
dependencies {
implementation("com.example.library:library:2.0.0")
}
dependencies {
implementation(project(":module"))
implementation("com.example.library:library:1.0.0")
// moduleで指定しているバージョンの方が新しいので、2.0.0が使われる
}
moduleで指定しているバージョンの方が古い場合、appで指定したバージョンでappがコンパイルされ、組み込まれます。
dependencies {
implementation("com.example.library:library:1.0.0")
}
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側で指定する必要がなくなります。
dependencies {
api("com.example.library:library:1.0.0")
}
dependencies {
implementation(project(":module"))
// libraryの依存関係を書いていなくても、appのなかでlibraryを使用可能
}
両者で指定している場合の挙動はimplementationの場合と同一です。
どういうときに依存関係を伝搬させるべきか
依存関係を伝搬させると、利用側では依存関係を書く必要がなくなります。違いはそれだけですね。
よって、そのライブラリ/モジュールを利用する上で、別のライブラリが必要な場合に依存関係を伝搬させるべきですね。
具体的に言うと、moduleがHoge
というクラスを提供しており、そのHogeクラスを利用する上で必要なクラスFuga
がlibraryから提供されているものの場合ですね。
class Hoge(fuga: Fuga)
この場合、moduleはlibraryの依存関係を伝搬させた方がよいでしょう。