Gradle Pluginを導入する際、buildscript dependenciesかnew gradle plugin dslに統一したいですよね。 前者は簡単なので、後者の方向けの記事です。
例えばですが、ktlint-gradle pluginを導入する際、root projectにて
plugins {
id("org.jlleitschuh.gradle.ktlint") version "9.2.0"
}
subprojects {
apply(plugin = "org.jlleitschuh.gradle.ktlint")
ktlint {
verbose.set(true)
android.set(true)
outputToConsole.set(true)
reporters {
reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.CHECKSTYLE)
}
ignoreFailures.set(true)
}
}
とし、subprojectにて
plugins {
kotlin("jvm") version "1.3.61"
}
とすると、ビルドに失敗します。
これは、Gradle Plugin自体が別のGradle Pluginに依存しており、かつ先にapplyされてしまった場合、
別のPluginへの依存の解決方法によっては NoClassDefFound
となってしまうためです。
では、ktlint-gradleの依存解決方法を見てみましょう。
compileOnly
となっていますね。つまり、ktlint-gradleはKotlin Gradle Pluginへの依存をコンパイル時のみ解決し、artifactの依存関係には含めないので、上記のgradle scriptの記述ではKotlin Gradle Pluginに含まれているクラスを解決できない、というわけです。
このような場合、root projectにおいて
plugins {
kotlin("jvm") version "1.3.61" apply false
id("org.jlleitschuh.gradle.ktlint") version "9.2.0"
}
subprojects {
apply(plugin = "org.jlleitschuh.gradle.ktlint")
ktlint {
verbose.set(true)
android.set(true)
outputToConsole.set(true)
reporters {
reporter(org.jlleitschuh.gradle.ktlint.reporter.ReporterType.CHECKSTYLE)
}
ignoreFailures.set(true)
}
}
とし、subprojectにて
plugins {
kotlin("jvm")
}
とすると、無事にビルドが通ります。
- Pluginをroot projectで解決する
- root projectには必要ないので
apply false
する
- root projectには必要ないので
- subprojectでは同Pluginのversionを指定しない
- rootprojectにて指定済の為。指定するとビルドエラーになる。
- pluginManagement DSLによる解決もありだが、個人的には好みではない。
このやり方が実質buildscript dependenciesの置き換えになるんでしょうか? 本記事の例はKotlin Gradle Pluginでしたが、Android Gradle PluginやGoogle Services Gradle Pluginを利用していると本記事の修正前の症状に陥りがちで、 やむを得ずbuildscript dependenciesを使用する事がありました。解決できるといいですね。
(追記) Android Gradle PluginとGoogle Services Pluginは相変わらずだめそうでした。 二重でバージョン指定すればエラーになるし、subprojectでバージョンを指定しなければpluginManagement scopeではmodule format errorになるし Gradle 6.0からbuildSrcのオブジェクトをsettings.gradleから参照できなくなったので、現状詰みです。