サマリー
buildSrc
ディレクトリを用いてgradleタスクを作成する際にKotlinを使用するには、kotlin gradle pluginの適用が必要でした。
具体的には、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章 カスタムタスクの作成 の「58.1. タスククラスのパッケージング」で紹介されているものの2個めの「buildSrcプロジェクト」のことです。
この方法でタスクを作成した場合、buildSrc
に対するbuild.gadle
は設定していなくてもシステムが自動的に以下のスクリプトを適用します。
(ユーザーガイド : http://gradle.monochromeroad.com/docs/userguide/organizing_build_logic.html より)
apply plugin: 'groovy'
dependencies {
compile gradleApi()
compile localGroovy()
}
ユーザーガイドは少し古いので、compile
を使用しています。ですがこちらはGAP v7.0.4ではサポートが終わっているので、GAP v7.0.4にあわせて書き直した場合以下です。
apply plugin: 'groovy'
dependencies {
implementation gradleApi()
implementation localGroovy()
}
※正確には元の動きを尊重するにはcompile
はapi
に置き換えるべきですが ここでは依存関係をほかのモジュールに推移的にエクスポートする必要はないので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
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.");
}
}
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
の場合、
// 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