buildSrcディレクトリ で gradleタスクを作成する際にKotlinを使用するにはkotlin gradle pluginの適用が必要

# サマリー
`buildSrc`ディレクトリを用いてgradleタスクを作成する際にKotlinを使用するには、kotlin gradle pluginの適用が必要でした。
具体的には、`buildSrc`直下に以下のような`build.gradle`を追加する必要があります。

```buildSrc/build.gradle
// デフォルトで適用される分
// http://gradle.monochromeroad.com/docs/userguide/organizing_build_logic.html
apply plugin: 'groovy'
dependencies {
    implementation gradleApi()
    implementation localGroovy()
}


// 以下カスタム
apply plugin: 'kotlin' // これがないと、buildSrc/arc/main以下にKotlinファイルを置いても実行できなくなる(Ctrl+Bでのジャンプでは認識されるけど)
buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        def kotlin_version = '1.6.10' // 多分、アプリ全体とバージョンを合わせないとだめ
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" // apply plugin: 'kotlin' に必要

    }
}

repositories {
    mavenCentral()
}
```

# 詳細
## 背景
```
projectRoot
|
|-buildSrc
|    |-src
|       |-main
|           |-java
|               |-GreetingTaskKotlin.kt
|               |-GreetingTaskJava.java
|
|-app
|  |-src
|  |  |-main
|  |       |
|  |    (以下略)
|  |
|  |-build.gradle
|
|-build.gradle
```


というディレクトリ構成で、(projectRootの)`build.gradle` から使用するためのカスタムGradleタスクを作成しました。　　
そうしたところ、`GreetingTaskJava.java`の方に定義したタスクは`build.gradle` から使用できるけど`GreetingTaskKotlin.kt`に定義したものは使用できませんでした。

ネット上に情報が少なく、またAndroidStudio上でのCtrl+Bでの定義ジャンプは`GreetingTaskKotlin.kt`に対しても正常に動いていたのもあり、何が悪いのかわからず解決に時間がかかってしまったので備忘録でした。


## 環境
gradle : v7.0.2
android gradle plugin (GAP) : v7.0.4
kotlin : v1.6.10


## そもそも`buildSrc`  を用いてGradleタスクを作成するとは
Gradleのユーザーガイドの[第58章 カスタムタスクの作成](http://gradle.monochromeroad.com/docs/userguide/custom_tasks.html) の「58.1. タスククラスのパッケージング」で紹介されているものの2個めの「buildSrcプロジェクト」のことです。

この方法でタスクを作成した場合、`buildSrc`に対する`build.gadle`は設定していなくてもシステムが自動的に以下のスクリプトを適用します。
(ユーザーガイド : http://gradle.monochromeroad.com/docs/userguide/organizing_build_logic.html より)

```gradle
apply plugin: 'groovy'
dependencies {
    compile gradleApi()
    compile localGroovy()
}
```

ユーザーガイドは少し古いので、`compile`を使用しています。ですがこちらはGAP v7.0.4ではサポートが終わっているので、GAP v7.0.4にあわせて書き直した場合以下です。

```gradle
apply plugin: 'groovy'
dependencies {
    implementation gradleApi()
    implementation localGroovy()
}
```

※正確には元の動きを尊重するには[`compile`は`api`に置き換えるべきですが](https://developer.android.com/studio/build/dependencies?hl=ja#dependency_configurations) ここでは依存関係をほかのモジュールに推移的にエクスポートする必要はないので`implementation` にしてしまっています。

さて、buildSrc以下に置くタスク定義ファイルにjavaを使用した場合はシステムが自動的に適用してくれる`build.gradle`を用いたビルドだけでプロジェクトルートの`build.gradle`やアプリケーションモジュールの`build.gradle`からタスクとして使用できるようになります。したがって`buildSrc`以下に独自に`build.gradle`を置く必要は特にありません。

ただ、Kotlinを使用したファイルで定義してタスクの場合はそれでは認識されません。
(なぜかAndroid Studio上での定義ジャンプや入力補完は効きますが...)

`apply plugin: 'kotlin'`の適用もしてやらないといけないようです。したがって、[#サマリー](#サマリー)に記載した`build.gradle`を`buildSrc`直下においてやります。


## おまけ そのほかのファイル



### タスクを定義している`GreetingTaskJava.java`と`GreetingTaskKotlin.kt`

```GreetingTaskJava.java
package com.kkkkan.buildscript;

import org.gradle.api.DefaultTask;
import org.gradle.api.tasks.TaskAction;


public class GreetingTaskJava extends DefaultTask {
  @TaskAction
  void greet(){
    System.out.println("Hello from Java.");
  }
}
```

```GreetingTaskKotlin.kt
package com.kkkkan.buildscript

import org.gradle.api.DefaultTask
import org.gradle.api.tasks.TaskAction

abstract class GreetingTaskKotlin : DefaultTask() {
    
    @TaskAction
    fun greet() {
        println("Hello from Kotlin.")
    }
}
```

### `GreetingTaskJava.java`と`GreetingTaskKotlin.kt` で定義したタスクを使用する側(プロジェクトのルートやアプリケーションモジュールの`build.gradle`)

プロジェクトのルートの`build.gradle`の場合、

```projectRooot/build.gradle

// Top-level build file where you can add configuration options common to all sub-projects/modules.

// -------元々あったもの ここから-------------
buildscript {
    ext.kotlin_version = '1.6.10' // composeライブラリv1.1.1はkotlin v1.6.10に依存しているのでこれ以上あげられない
    ext.compose_version = '1.1.1'
    repositories {
        google()
        mavenCentral()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:7.0.4'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        (以下略)

    }
}

allprojects {
    repositories {
        google()
        mavenCentral()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

// -------元々あったもの ここまで-------------







// ------追加ここから------------------
import com.kkkkan.buildscript.GreetingTaskJava
import com.kkkkan.buildscript.GreetingTaskKotlin

task greetJava(type:GreetingTaskJava)
task greetKotlin(type: GreetingTaskKotlin)
// ------追加ここまで------------------

```

と最後の4行を付け足して、
`gradlew greetJava`(Windows)/`./gradlew greetJava`(Mac) で`GreetingTaskJava#greet`
`gradlew greetKotlin`(Windows)/`./gradlew greetKotlin`(Mac) で`GreetingTaskKotlin#greet`
が実行できるようになります。

なお、しつこいですが`buildSrc/build.gradle`を作成しなくても`gradlew greetJava`(Windows)/`./gradlew greetJava`(Mac) は実行できます。
(`import com.kkkkan.buildscript.GreetingTaskKotlin`と`task greetKotlin(type: GreetingTaskKotlin)`)をコメントアウト)しておけば)


アプリケーションモジュールの時も`app/build.gradle`に最後の4行を同様に追加して、`gradlew greetKotlin`(Windows)もしくは`gradlew app:greetKotlin`(Windows)などで同様に実行できます。(`app/build.gradle`に設定した場合でも、`gradlew app:greetKotlin`ではなく`app`を省略して`gradlew greetKotlin`だけでも大丈夫なようです。知らなかった....)

# 感想
- Kotlinを使うならkotlinプラグインを入れないとだめなんて、言われてみれば当たり前なんだけど、なまじ定義ジャンプや入力補完が効くので気づくのに時間がかかってしまった。
- Gradl関係を検索するとKotlin DSLを使用したもの、が多くて、groovyのまま通しつづけるのはそろそろ年貢の納め時なのかな...という気分になりました。今回の本題とは全然関係ないけども。


# 参考にしたもの
- http://gradle.monochromeroad.com/docs/userguide/custom_tasks.html
- http://gradle.monochromeroad.com/docs/userguide/organizing_build_logic.html
- https://docs.gradle.org/6.8/userguide/organizing_gradle_projects.html#organizing_gradle_projects
- https://qiita.com/mangano-ito/items/7e13f1988f9da61746b8
- https://developer.android.com/studio/build/dependencies?hl=ja
- https://kotlinlang.org/docs/gradle.html#kotlin-and-java-sources