Uzzu::Blog

Software Design, and my life.

New Gradle plugin DSLを使用するとビルドエラーになる場合のTIPS

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の依存解決方法を見てみましょう。

https://github.com/JLLeitschuh/ktlint-gradle/blob/44d7254a33aecb42590ec864078a331a91bb7a34/plugin/build.gradle.kts#L38

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 する
  • 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から参照できなくなったので、現状詰みです。

comments powered by Disqus