Android で VersionCatalogを使う

公式ドキュメントの [Central declaration of dependencies](https://docs.gradle.org/current/userguide/platforms.html#sub:central-declaration-of-dependencies)を　AndroidStudioEEのMaterialDesign3テンプレートプロジェクトに適応してみたことの備忘記事です。


## 基本

### versionとlibrary
```gradle
dependencyResolutionManagement {
~~
    versionCatalogs {
        create("libs") {
            version("coreKtx","1.7.0")
            library("androidx-core-ktx", "androidx.core", "core-ktx").versionRef("coreKtx")
        }
    }
}
```

versionはライブライのバージョンで記法は `version("エイリアス名", "バージョン番号")`
libraryはライブラリ、記法は `library("エイリアス名", "ライブラリ")`

上記で
`implementation 'androidx.core:core-ktx:1.7.0'`
が
`implementation(libs.androidx.core.ktx)`
こう書ける。エイリアス名とカンマで宣言したライブラリが取得できる。

ライブラリを書く際に[:]は認識してくれないので、コンマで宣言を分ける
`implementation 'androidx.core:core-ktx:1.7.0'`
↓
`library("androidx-core-ktx", "androidx.core", "core-ktx").versionRef("coreKtx")`

また、参照する際は、[-]を[.]に変更する

`library("androidx-core-ktx", "androidx.core", "core-ktx").versionRef("coreKtx")`
↓
`implementation(libs.androidx.core.ktx)`




### bundle
```gradle
versionCatalogs {
        create("libs") {
~~

            version("compose", "1.2.0")
            library("compose-ui", "androidx.compose.ui", "ui").versionRef("compose")
            library("compose-preview", "androidx.compose.ui", "ui-tooling-preview").versionRef("compose")
            bundle("compose", ["compose-ui", "compose-preview"])
        }
    }
```

versionなどの同じライブラリはbundleでまとめ上げることが可能
記法　`bundle("bundleエイリアス名" ["ライブラリエイリアス名1","ライブラリエイリアス名2" ... ])`

```gradle
implementation(libs.bundles.compose)
```
`libs.bundles.エイリアス` で参照する

### plugin

```gradle
versionCatalogs {
        create("libs") {
            version("coreKtx","1.7.0")
            library("androidx-core-ktx", "androidx.core", "core-ktx").versionRef("coreKtx")
            plugin("android-application", "com.android.application").version("7.4.1") // 追加
        }
    }
```

```gradle
// build.gradle（app)
plugins {
    alias(libs.plugins.android.application)
    id 'org.jetbrains.kotlin.android'
}
```
`libs.plugin.エイリアス` で参照できるようになる。

```gradle
// build.gradle (project)
plugins {
    //    id 'com.android.application' version '7.4.1' apply false
    alias(libs.plugins.android.application) apply false // 上をこう宣言できる
    id 'com.android.library' version '7.4.1' apply false
    id 'org.jetbrains.kotlin.android' version '1.7.0' apply false
}
```



プロジェクトレベルのbuild.gradleも変更可能

### test系

上と同じ
```gradle
// setting.gradle
create("testlibs") {
            version("junit","4.13.2")
            library("junit", "junit", "junit").versionRef("junit")
        }
```

```gradle
// build.gradle
testImplementation(testlibs.junit)
```



## libs.versions.toml ファイルを使う
libs.versions.toml ファイルを作成して、エイリアスの宣言をそのファイルにまとめることができる

上述のsetting.gradleの宣言を移したものが以下

root/gradle/libs.versions.toml
```toml
[versions]
coreKtx = "1.7.0"
compose = "1.2.0"

[libraries]
androidx-core-ktx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" }
compose-ui = { module = "ndroidx.compose.ui:ui", version.ref = "compose" }
compose-preview = { module = "androidx.compose.ui:ui-tooling-preview", version.ref = "compose" }

[bundles]
compose = ["compose-ui", "compose-preview"]

[plugins]
android-application = { id = "com.android.application", version = "7.4.1" }
```

TOMLファイルは、主に以下4つのセクションから構成される。この辺の意味は上述のsetting.gradleにまとめる時と同じ。

- versions : バージョンの宣言
- libraries : ライブラリの宣言
- bundles : バンドル
- plugins : プラグイン

ちなみに、tomlファイル名の先頭の単語が、ファイルへのエイリアスになっている。
`{エイリアス}.versions.toml`

そのエイリアスを使って、build.gradleから参照する
```gradle
// build.gradle
def versionCatalog = extensions.getByType(VersionCatalogsExtension).named("libs")
dependencies {
    // implementation(libs.androidx.core.ktx)
    versionCatalog.findLibrary("androidx-core-ktx").ifPresent {
        implementation(it)
    }
```
また、これはType Unsafeなやり方なので、普通は下のやり方で参照する様子。

エイリアスの衝突を避けるため、`libraries.versions.toml`にファイル名を変えたのち、以下
```gradle
// setting.gradle
versionCatalogs {
        create("libs") { // こいつと衝突する
            from(files("gradle/libraries.versions.toml"))
        }
    }
```

```gradle
// build.gradle
dependencies {
    implementation(libs.androidx.core.ktx)
~~
```

**基本**のところで書いていたtestLibsやpluginも全てtomlに移すと以下になる

```toml
# libs-test.versions.toml

[versions]
junit = "4.13.2"

[libraries]
junit = { module = "junit:junit", version.ref = "junit" }
```

```gradle
// setting.gradle

dependencyResolutionManagement {
    versionCatalogs {
        create("libs") {
            from(files("gradle/libraries.versions.toml"))
        }
        create("testLibs") { // 追加
            from(files("gradle/libs-test.versions.toml"))
        }
    }
}
```

```gradle
// build.gradle

plugins {
    alias(libs.plugins.android.application)
~~~

dependencies {
    implementation(libs.androidx.core.ktx)
    implementation(libs.bundles.compose)
    testImplementation(testLibs.junit)
~~~
```


## 終わり
https://github.com/kkhouse/Playground/tree/main/AndroidProject/GradlePro/VersionCatalogPlayground