Kotlin DSL ビルド スクリプト ファイルについて

Android Studio 4.0 から、kts（Kotlin DSL ビルド スクリプト ファイル）がサポートされる様になりました。
ktsを導入するメリットは、記述が統一できることと、kotlinで実装が可能になります。

では、実際に導入していきたいと思います。

### buildSrc を作成

プロジェクトルート（appと同じ階層）に`buildSrc`フォルダーを作成します。
作成したら、そのフォルダーに`build.gradle.kts`ファイルを作成して、下記の内容を記載します。
記載したら、Gradleを同期させます。
同期すると`buildSrc`配下にGradle関連のフォルダーが作成されます。

* build.gradle.kts

```kotlin
plugins {
    `kotlin-dsl`
}

repositories {
    jcenter()
}
```

### Dependenciesを作成

`buildSrc`に下記のフォルダーを作成します。
`/buildSrc/src/main/java/`
作成したら、`Dependencies.kt`を作成します。（ファイル名は、任意です）

* Dependencies.kt

```kotlin
object Dependencies {
    object Versions {
        const val gradle = "4.0.0"
        const val kotlin = "1.4.0"
        const val appcompat = "1.3.0-alpha02"
        const val core = "1.5.0-alpha02"
        const val material = "1.3.0-alpha02"
        const val junit = "1.1.2"
        const val runner = "1.3.0"
        const val espresso = "3.3.0"
    }

    object Android {
        const val compileSdk = 29
        const val targetSdk = 29
        const val minSdk = 26
        const val buildTools = "30.0.2"
        const val versionCode = 1
        const val versionName = "1.0.0"
    }

    object Plugin {
        const val gradle = "com.android.tools.build:gradle:${Versions.gradle}"
    }

    object AndroidX {
        const val core = "androidx.core:core-ktx:${Versions.core}"
        const val appcompat = "androidx.appcompat:appcompat:${Versions.appcompat}"
        const val material = "com.google.android.material:material:${Versions.material}"

        object Test {
            const val junit = "androidx.test.ext:junit:${Versions.junit}"
            const val espresso = "androidx.test.espresso:espresso-core:${Versions.espresso}"
        }
    }

    object Test {
        const val jUnit = "junit:junit:4.12"
    }
}
```

### ktsに変換

ここから既存のgradleファイルをkts化していきます。

* settings.gradle

``` gradle
include ':app'
rootProject.name = "My Application"
```

* settings.gradle.kts

``` kotlin
include(":app")
rootProject.name = "My Application"
```

---

* build.gradle（プロジェクト）

```gradle
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    ext.kotlin_version = "1.4.10"
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath "com.android.tools.build:gradle:4.0.0"
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}
```

* build.gradle.kts（プロジェクト）

```kotlin
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath(Dependencies.Plugin.gradle)
        classpath(kotlin("gradle-plugin", version = Dependencies.Versions.kotlin))

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

tasks.register<Delete>("clean").configure {
    delete(rootProject.buildDir)
}
```

---

* build.gradle（アプリ）

```gradle
plugins {
    id 'com.android.application'
    id 'kotlin-android'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.example.myapplication"
        minSdkVersion 23
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
    implementation 'androidx.core:core-ktx:1.3.1'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
```

* build.gradle.kts（アプリ）

```kotlin
import org.jetbrains.kotlin.config.KotlinCompilerVersion

plugins {
    id("com.android.application")
    kotlin("android")
}

android {
    compileSdkVersion(Dependencies.Android.compileSdk)
    buildToolsVersion = Dependencies.Android.buildTools

    defaultConfig {
        applicationId = "com.example.myapplication"
        minSdkVersion(Dependencies.Android.minSdk)
        targetSdkVersion(Dependencies.Android.targetSdk)
        versionCode = Dependencies.Android.versionCode
        versionName = Dependencies.Android.versionName

        testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        getByName("release") {
            isMinifyEnabled = false
            proguardFiles(
                    getDefaultProguardFile("proguard-android-optimize.txt"),
                    "proguard-rules.pro"
            )
        }
    }
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_1_8
        targetCompatibility = JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = "1.8"
    }
}

dependencies {
    implementation(kotlin("stdlib", KotlinCompilerVersion.VERSION))
    implementation(Dependencies.AndroidX.core)
    implementation(Dependencies.AndroidX.appcompat)
    implementation(Dependencies.AndroidX.material)
    testImplementation(Dependencies.Test.jUnit)
    androidTestImplementation(Dependencies.AndroidX.Test.junit)
    androidTestImplementation(Dependencies.AndroidX.Test.espresso)
}
```

---
これで、対応は完了になります。

メリットにも記載しましたが、gradleの場合、シングルコーテーションやダブルコーテーションが混在してますが、ktsではダブルコーテーションしか記述出来ないので、統一性が担保されます。
他にもkotlinで記載しているので、宣言箇所へのジャンプや補完など、通常のソースコードとして扱うことが出来るので、便利になります。