Gradle Kotlin DSLで何かと役に立つGroovyBuilderの話です。
Gradle Kotlin DSLで汎用的なビルドスクリプトを書く際はbuildSrcに書く事が多いと思いますが、Gradle Kotlin DSLが自動生成するDSLは使用できず、且つ素の状態で非標準なpluginのAPIを完全に型安全に使用する事はできません。
その際、pluginの依存関係をbuildSrc上で一貫して解決する、或いはbuildSrcは素の状態でやっていく2つの選択肢が考えられます(中途半端な状態での管理はしんどいので)。buildSrcは何でもできてしまうので、一定ルールを設けながらやっていけばどちらでも良いですが、素の状態に近い方が学習コストは低いのでいまいまは後者を考えます。後者の場合に役に立つのがGroovyBuilderです。
https://docs.gradle.org/current/userguide/kotlin_dsl.html#the_kotlin_dsl_groovy_builder
サンプルコードは↑にあるので省略しますが、これを利用すると、Groovy DSLの挙動のままにビルドスクリプト上のコンポーネントにアクセスできます。Gradleのコンポーネントの大半は Named
及び NamedDomainObjectContainer
によるidentitiyの付与とコンテナ管理の強制よって秩序が保たれている為、reflectionの如く大半のコンポーネントにアクセスする事ができます。なんでもできてしまうので正直あんまり使いたくないと思いつつも、Gradle Kotlin DSLでサポートが追いついていないなどの問題で使う事があります。
使用例として、Kotlin MultiPlatform Project(以下MPP)のライブラリ配布におけるsourceJarの生成を考えます。MPPにおいてはプラットフォーム実装側のmodule(subproject etc…)のsourceJarにcommon moduleのソースと外部配信しないinternalなmoduleのソースを含める必要がありますが、各module毎にそのビルドスクリプトを書くのは冗長です。これを、buildSrcに持っていきつつ汎用化します。
Android ProjectかどうかについてはGroovyBuilderもAndroid Gradle Pluginも不要ですが、その先KotlinSourceSetsを取得したりするのにGroovyBuilderを使用しています。
こんな感じでsourceJar生成の記述を減らしています。
余談として、 Gradle5.1から TaskContainer#create
の一部のsignatureのメソッドを新APIに置換する必要があります、置換先APIは4.10.2では遅延評価されないバグがあるため create
を使い続けています。5.1では治ってて欲しい(未調査)
そんな感じで、GroovyBuilderにほどほどに頼りつつやっていきましょうというお話でした。