Gradle 依存関係の解決

ビルドファイルでは直接的な依存関係を指定しますが、これらの依存関係のそれぞれに他の依存関係が必要になる場合があります。これらの推移的依存関係により、依存関係グラフ全体が急速に拡大し、多くの場合、バージョンが競合します。

minor(新機能)または patch(バグ修正)の部分が変更されても、ライブラリは引き続き互換性があり、アプリに影響を与える可能性は低くなります。

たとえば、アプリがライブラリ A とライブラリ B に依存し、ライブラリ A とライブラリ B がライブラリ C の異なるバージョンに依存しているとします。

アプリがライブラリ A とライブラリ B に依存しており、ライブラリ A とライブラリ B がライブラリ C の異なるバージョンに依存している場合。Gradle はライブラリ C の最新バージョンを選択します。
図 1. 伝播型のバージョン競合。Gradle は最新バージョンに解決します(デフォルト)。

この場合、Gradle はデフォルトでライブラリ C の最新バージョンを選択します。これにより、コンパイル時またはランタイムの問題が発生する可能性があります。この例では、ライブラリ C は 2.1.1 に解決されますが、ライブラリ A はライブラリ C 1.0.3 をリクエストしています。バージョン番号の大部分が変更されており、削除された関数や型などの互換性のない変更が示されています。これにより、ライブラリ A から行われた呼び出しがクラッシュする可能性があります。

アプリには、推移的な依存関係でもある直接的な依存関係を含めることができます。

アプリがライブラリ A とライブラリ C に依存している場合。ライブラリ A は、ライブラリ C の新しいバージョンに依存しています。Gradle はライブラリ C の最新バージョンを選択します。
図 2. 別の伝播型バージョンの競合。ここで、Gradle は伝播バージョンを解決し、アプリケーションはその新しいバージョンを認識します。

このような場合、新しい伝播依存関係が、アプリで直接リクエストしたバージョンをオーバーライドする可能性があります。

Gradle は、グラフ内のすべての依存関係のすべての候補バージョンを確認し、各依存関係の最新バージョンを決定します。基本的な Gradle タスク高度なツールを使用して、Gradle が解決した各依存関係のバージョンを確認できます。この解像度での変更を比較することは、アップグレードのリスクを理解して軽減するうえで重要です。

たとえば、Gradle dependencies タスクを使用して ./gradlew app:dependencies を実行すると、アプリ モジュールで使用されるすべての依存関係のツリーが表示されます。図 2 に示すように、ライブラリを使用するアプリに対してこれを実行すると、次のように表示されます。

1: releaseRuntimeClasspath - Runtime classpath of /release.
2: +--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0
3: |    +--- ... (omitted for brevity) ...
4: +--- com.sample:library.a:1.2.3
5: |    +--- com.sample:library.c:2.1.1
6: |    |    \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
7: |    \--- org.jetbrains.kotlin:kotlin-stdlib:2.0.0 (*)
8: +--- com.sample:library.c:1.4.1 -> 2.1.1 (*)

レポートのこの部分には、releaseRuntimeClasspath 構成で解決された依存関係の一部が表示されます。

依存関係レポートに -> が表示される場合は、リクエスタ(アプリまたは別のライブラリ)が、想定していないバージョンの依存関係を使用しています。ほとんどのライブラリは下位互換性のために記述されているため、多くの場合、問題は発生しません。ただし、一部のライブラリでは互換性のない変更が行われることがあります。このレポートは、アプリケーションの動作に関する新しい問題の原因を特定するのに役立ちます。

Gradle の依存関係レポートの使用方法について詳しくは、依存関係を表示してデバッグするをご覧ください。

リクエストされたバージョンは、バージョン カタログまたは部品表(BOM)で直接指定できます。

直接バージョン仕様の解決

指定した依存関係のバージョンが、バージョン解決の候補になります。

たとえば、app/build.gradle.kts の依存関係として androidx.compose.ui:ui ライブラリのバージョン 1.7.3 をリクエストするには、次のようにします。

dependencies {
    implementation("androidx.compose.ui:ui:1.7.3")
}

バージョン 1.7.3 が候補バージョンになります。Gradle は、1.7.3 と、推移的依存関係によってリクエストされた同じライブラリの他のバージョンの最新バージョンに解決します。

バージョン カタログの解決

バージョン カタログでは、アプリケーション全体で使用される依存関係のバージョンを追跡する変数を定義します。バージョン カタログの変数を使用する場合、その変数で指定された依存関係がバージョン解決の候補に追加されます。バージョン カタログで未使用の変数は無視されます。

たとえば、gradle/libs.versions.toml ファイルで androidx.compose.ui:ui のバージョン 1.7.3 を依存関係として指定するには、次のようにします。

[versions]
ui = "1.7.3"

[libraries]
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui", version.ref = "ui" }

これにより、ライブラリを表す libs.androidx.compose.ui という変数が定義されます。この変数を使用して依存関係を指定しない限り、このバージョンは候補と見なされません

app/build.gradle.kts でライブラリとそのバージョンをリクエストするには:

dependencies {
    implementation(libs.androidx.compose.ui)
}

Gradle は、直接指定の場合と同じ方法で解決します。

部品構成表(BOM)の解決策

BOM に表示されるすべてのライブラリのバージョンが、バージョン解決の候補になります。ライブラリが依存関係として使用されるのは、直接または間接として指定されている場合のみです。BOM 内の他のライブラリは無視されます。

BOM のバージョンは、直接依存関係と、BOM に表示されるすべての間接依存関係に影響します。

たとえば、app/build.gradle.kts で BOM をプラットフォーム依存関係として指定します。

dependencies {
    implementation(platform("androidx.compose:compose-bom:2024.10.00"))
    implementation("androidx.compose.ui:ui")
}

依存関係として使用するライブラリにバージョンの指定は必要ありません。リクエストされたバージョンは BOM から取得されます。

バージョン カタログを使用して、BOM とライブラリの変数を作成することもできます。BOM 依存関係に表示されるライブラリのバージョン カタログのバージョン番号を省略します。

たとえば、バージョン カタログには BOM とそのバージョン番号が含まれていますが、BOM から参照するライブラリのバージョンは指定されていません。

[versions]
composeBom = "2024.10.00"

[libraries]
androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" }
androidx-compose-ui = { group = "androidx.compose.ui", name = "ui" }

app/build.gradle.kts は、バージョン カタログで定義された変数を使用して BOM とライブラリを参照します。

dependencies {
    implementation(platform(libs.androidx.compose.bom))
    implementation(libs.androidx.compose.ui)
}

BOM で指定されたライブラリのバージョンが、Gradle の解決の候補になります。さらに、BOM で指定された他のすべてのライブラリ バージョンは、依存関係として直接使用しているかどうかにかかわらず、候補バージョンになります。

たとえば、BOM でライブラリ A、B、C のバージョンを指定するとします。アプリで、ライブラリ A とライブラリ D を依存関係として直接使用したいとします。ライブラリ D はライブラリ B を依存関係として使用します。ライブラリ C を使用するものはない。

BOM には、ライブラリ A、B、C のバージョンが含まれています。お客様のアプリは、ライブラリ A と D を依存関係として使用しています。ライブラリ D はライブラリ B を依存関係として使用します。ライブラリ C は、このアプリで直接または間接的に使用されていません。
図 3. BOM シナリオ。

ライブラリ A、B、D はアプリの依存関係であり、ライブラリ C は無視されます。ライブラリ B を依存関係として直接指定していなくても、Gradle は BOM で指定された A と B のバージョンを候補として使用します。

ライブラリ D がライブラリ B のバージョン 2.0.1 より前のバージョンをリクエストした場合、Gradle は 2.0.1 に解決します。ライブラリ D がライブラリ B のより高いバージョンをリクエストした場合、Gradle はそのバージョンに解決します。