LoginSignup
13
9

More than 5 years have passed since last update.

build.gradle.ktsへの書き換えとハマリポイント part 2

Last updated at Posted at 2017-11-15

前回、途中で力尽きてしまったので続きです。

Step 2 続き

Step 2のハマリポイントは記載しきったつもりだったのですが、1つ忘れていたのでそこからです。
コード全体は前回のStep 2を参照してください。

ハマリポイント 3: Pluginのconfigurationが参照できない

このsampleではRibbonizer pluginを使用しています。
Groovy版ではこのように設定を書くことが出来ました。

app/build.gradle
ribbonizer {
    builder { variant, iconFile ->
        if (variant.buildType.name == "debug") {
            return yellowRibbonFilter(variant, iconFile)
        } else {
            return grayRibbonFilter(variant, iconFile)
        }
    }
}

ぱっと見、そのままKotlin化できそうな雰囲気を感じますが実際にはbuilderが参照できずコンパイルエラーになります。
ribbonizerは参照できているのでコードジャンプして見てみます。

accessors.kt
/**
 * Configures the [ribbonizer][com.github.gfx.ribbonizer.plugin.RibbonizerExtension] project extension.
 *
 * `ribbonizer` is not accessible in a type safe way because:
 * - `com.github.gfx.ribbonizer.plugin.RibbonizerExtension` is not public
 */
fun Project.`ribbonizer`(configure: Any.() -> Unit): Unit =
    extensions.configure("ribbonizer", configure)

どうやら、plugins構文で指定されたプラグインへのアクセスはこのaccessors.ktというファイルが生成されることで実現しているようです。
この拡張関数のコメントによると、configurationのインターフェースであるExtensionクラスがpublicではないときにtype safeなアクセスができないようです。
実際、RibbonizerExtensionクラスはpublicではありませんでした。

このような場合どうするかというと、withGroovyBuilderブロックを使って文字列指定でパラメータやメソッドに値を設定していくことになります。

build.gradle.kts
ribbonizer {
    withGroovyBuilder {
        "builder"(FilterBuilder { variant, iconFile ->
            return@FilterBuilder when (variant.buildType.name) {
                "debug" -> YellowRibbonBuilder().apply(variant, iconFile)
                else -> GrayRibbonBuilder().apply(variant, iconFile)
            }
        })
    }
}

このように書くことでbuilderメソッドに引数を渡すことができます。
また、groovyでyellowRibbonFilter(variant, iconFile)のようにしていた箇所も直接アクセス出来ないためyellowRibbonFilterの内部実装をコピペしています。

Step 3 - plugin versionの共通化

pluginのバージョン指定をする際、変数やgradle.propertiesの値を使うことができない謎の制限があるため、Kotlin関連プラグインのような同じバージョンのものを複数指定するパターンで記述をまとめることができず更新時などに辛い感じになってしまいます。

app/build.gradle.kts
plugins {
    ...

    kotlin("android") version "1.2.0-rc-39"
    kotlin("android.extensions") version "1.2.0-rc-39"

    ...
}

これを一箇所まとめたい場合はまたpluginManagementで行うことになります。
今回はkotlinのバージョンはgradle.propertiesに記載することにします

gradle.properties
kotlinVersion=1.2.0-rc-39

idを正規表現でKotlin関連プラグインが引っかかるように定義してuseVersionでバージョンを指定

settings.gradle
resolutionStrategy {
    eachPlugin {
        switch (requested.id.id) {
            ...

            case ~/org\.jetbrains\.kotlin\..*/:
                useVersion("${kotlinVersion}")
                break
        }
    }
}

build.gradle側では、versionの指定を無くします

app/build.gradle.kts
plugins {
    ...

    kotlin("android")
    kotlin("android.extensions")

    ...
}

拡張プロパティの取得はextraというdelegated propertyで行えたのですが、プロジェクトのプロパティは同様にprojectというdelegated propertyで行えます。
(projectで取得できる型はAnyになるので適宜Stringなどにcastして使ってください)

app/build.gradle.kts
val kotlinVersion by project

参考資料

gradleのkotlin-dslリポジトリにはサンプルが多く用意されているのでまずはここを見てみるのがいいと思います
gradle/kotlin-dsl: Kotlin language support for Gradle build scripts

おわりに

今回、build.gradleをkotlinに書き換えてみましたが正直なところ本格的に使うのは厳しいかなという感じです。
この記事では書きませんでしたが、一度スクリプトがコンパイルエラーになると補完がまともに効かなくなりコンパイルが通るようになるまで結局補完を使えないみたいな状況になりがちで想像していた快適さには程遠いものでした。
とはいえ、今後そのあたりも改善されていくと思うので期待しながら状況ウォッチしていきたいと思います。

今回の最終的なコードはここにあります
chibatching/KtsSample
途中のstep毎にコミットしているので必要に応じてそちらも参照していただけると〜

13
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
9