Android, Gradle: Version Catalog を使って Gradle プラグインを利用する

Gradle Version Catalog を使って、Gradle Plugin を利用する方法を解説します。

> この記事は以前に投稿した記事([Android, Gradle: Version Catalog と PluginManagement を使って Gradle プラグインを利用する](https://qiita.com/irgaly/items/45f84311f0c17a785644)) を、PluginManagement を使わない方法で書き直したものです。バージョン指定が Version Catalog で完結することから、この記事で解説している方法をおすすめします。

# 前提

* Gradle 7.2 以上
    * Gradle 7.2 から Version Catalog の `[plugins]` セクションが利用可能です
* Gradle Kotlin DSL
    * Kotlin DSL で解説しています
* マルチモジュールプロジェクトであること
    * マルチモジュールプロジェクトで、すべてのモジュールで同一バージョンの Plugin を使用する方法を解説しています

# 実装

## settings.gradle.kts の設定

enableFeaturePreview で Version Catalog 機能を有効化します。Gradle 8.0 以降では Version Catalog がデフォルトで有効となっているため、この設定は不要です。

pluginManagement で Plugin の依存解決に必要なリポジトリを定義します。

`settings.gradle.kts`

```kotlin
enableFeaturePreview("VERSION_CATALOGS") // Gradle 8.0 以降では不要
pluginManagement {
    repositories {
        google()
        mavenCentral()
        gradlePluginPortal()
    }
}
...
```

## Version Catalog の定義

Version Catalog に `[plugins]` セクションを定義します。ここでは例として AndroidX Navigation SafeArgs Plugin を定義します。

ここで定義した　Plugin 情報には `libs.plugins.*` でアクセスできるようになります。

```toml
[versions]
androidx-navigation = "2.5.3"
...
[plugins]
androidx-navigation-safeargs = { id = "androidx.navigation.safeargs", version.ref = "androidx-navigation" }
```

## rootProject で Plugin を読み込む

マルチモジュールプロジェクトではすべてのモジュールで同じバージョンの Plugin を読み込むために、rootProject で Plugin を読み込ませる必要があります。

rootProject の plugins ブロックで `alias()` により Plugin を読み込ませます。このとき、Plugin のバージョンを指定するだけで、rootProject にその Plugin を適用しない場合は `apply false` により Plugin の読み込みだけを設定します。

`(project root)/build.gradle.kts`

```kotlin
plugins {
...
    // rootProject で Plugin を読み込ませることによりマルチモジュール全体の Plugin バージョンを固定する
    alias(libs.plugins.androidx.navigation.safeargs) apply false
} 
...
```
## Plugin を利用する

Plugin を使用したいモジュールで、Plugin を適用します。

`app/build.gradle.kts`

```kotlin
plugins {
...
    alias(libs.plugins.androidx.navigation.safeargs)
}
...
```

# 実装 (subprojects / allprojects での利用)

subprojects / allprojects ブロックにより、すべてのプロジェクトへ Plugin を適用することができます。

例として [ktlint-gradle Plugin](https://github.com/JLLeitschuh/ktlint-gradle) を allprojects ブロックですべてのプロジェクトに適用する方法を解説します。

## Version Catalog の定義

Version Catalog へ ktlint-gradle Plugin を定義します。

`gradle/libs.versions.toml`

```toml
...
[plugins]
ktlint-gradle = { id = "org.jlleitschuh.gradle.ktlint", version = "11.1.0" }
```

## rootProject で Plugin の読み込みと allprojects で Plugin の適用

rootProject の `build.gradle.kts` で Plugin のバージョンを固定するための Plugin 読み込みと、allprojects ですべてのモジュールへ Plugin を適用します。

`(project root)/build.gradle.kts`

```kotlin
import org.jlleitschuh.gradle.ktlint.KtlintExtension
plugins {
    // ktlint-gradle Plugin のバージョンを固定するための読み込み
    // ここでは apply false で Plugin の適用はさせない
    alias(libs.plugins.ktlint.gradle) apply false
}
allprojects {
...
    afterEvaluate {
        // 対象プロジェクトの afterEvaluate の中でのみ libs.plugins.* へのアクセスが成功します
        // libs.plugins.ktlint.gradle.get().pluginId は
        // Version Catalog で定義した "org.jlleitschuh.gradle.ktlint" を取得できます
        apply(plugin = libs.plugins.ktlint.gradle.get().pluginId)
        configure<KtlintExtension> {
...
        }
    }
}
```

これで、すべてのモジュールで ktlint-gradle Plugin が適用されます。

# 参考

https://docs.gradle.org/7.2/userguide/plugins.html