kotlin + spring boot + gradle + IntelliJ のbuild.gradle.ktsメモ

kotlin初学者が頑張って書く自分用メモ。
個人で学習用に作成した`build.gradle.kts`をもとに書いていく。
間違えていたら指摘いただけるとありがたいです。
随時更新する。

# build.gradle.kts
### **`plugins`** 
Graldeがプロジェクトをビルドする際、ビルドスクリプト（build.gradle）実行時に必要となるプラグインを記述するブロック。あくまでもビルドスクリプトが使用する依存関係のため、ここで指定したものはプロジェクトのコーディングで使用できない。
**Gradleが公開しているプラグインを指定する。**

https://plugins.gradle.org/

```kotlin
plugins {
    // Gradle Application Plugin: JVMアプリケーションのローカル実行やビルドを補助するためのプラグイン
    application
    // IDEA Plugin: IntelliJ IDEAが使用すファイルを生成し、プロジェクトをIDEAで開けるようにする。
    // またいくつかのタスクも追加する。
    idea
    // kotlinメソッドはKotlin Teamが提供するプラグインの指定。
    // プラグイン名の"org.jetbrains.kotlin."を省略して書く。
    kotlin("jvm") version "1.8.21"
    // version でプラグインのバージョンを指定する。
    kotlin("plugin.spring") version "1.8.21"
    kotlin("plugin.jpa") version "1.8.21"
    kotlin("plugin.serialization") version "1.8.21"
    // idメソッドはKotlin Team以外が提供するプラグインの指定。
    // フルパスで書く必要がある。
    id("org.springframework.boot") version "3.1.0"
    id("io.spring.dependency-management") version "1.0.12.RELEASE"
    id("com.palantir.git-version") version "3.0.0"
    id("org.flywaydb.flyway") version "9.4.0"
}
```

### **`buildscript`**
Gradleビルドスクリプト(build.gradle.ktsのこと)自身の依存関係を指定するもの。
あくまでもビルドスクリプトが使用する依存関係のため、ここで指定したものはプロジェクトのコーディングで使用できない。
ここには後述する`repositories`ブロックと`dependencies`ブロックが置かれる。
**Gradle以外のリポジトリが公開しているプラグインを指定する。**

```kotlin
buildscript{
    //　ビルド時に使うリポジトリはこっから取ってこいということ。
    repositories {
        mavenCentral()
    }
    //　使いたいリポジトリ
    dependencies {
        classpath("mysql:mysql-connector-java:8.0.32")
    }
}
```

* #### `repositories`
プロジェクトの依存関係解決のためにライブラリを取ってくる外部のリポジトリを指定する。
複数個指定することができる。
上にあるリポジトリから優先順位が高く、上のリポジトリにライブラリがなければ下のリポジトリから検索してくる。
```kotlin 
repositories {
    // 基本こいつで良さそう。
    // 必要なライブラリが公開されているリポジトリを追加する。
    mavenCentral()
}
```

* #### `dependencies`
ビルド時必要なライブラリを記述。
```kotlin
dependencies {
    classpath("mysql:mysql-connector-java:8.0.32")
}
```
なお、`repositories`と`dependencies`はビルド時だけでなくプロジェクト自体の依存関係でも使用する（後述）。

### **`allprojects`**
ルートプロジェクト、サブプロジェクトに共通した設定を記述。
マルチプロジェクトで、全てのプロジェクトに統一した設定が必要な際に使用。

```kotlin
allprojects {
    // groupとversionはプロジェクトを識別するためのもの。
    // group: マルチプロジェクトの共通したパッケージ
    group = "jp.co.hogehoge"
    // プロジェクト自体のバージョン。gitVersion()でgitと連携させると手作業にならずに済む。
    version = gitVersion()

    repositories {
        mavenCentral()
    }

    // プロジェクト全体で使用できるタスク
    tasks {
        // withType<>: 特定のタスクにアクセスする。
        // configureEach {}: 指定されたプロジェクトの特定のタスクに変更を加える。
        withType<KotlinCompile>().configureEach {
            // "-Xjsr305=strict"とすることで、null安全を機能させることができる。
            kotlinOptions.freeCompilerArgs = listOf("-Xjsr305=strict")
            kotlinOptions.jvmTarget = Versions.jdk
        }

        withType<Test>().configureEach {
            // テストにはJUnitを使うよって記述。
            useJUnitPlatform()
        }

        // 以下buildタスクに関する設定。
        // buildタスクは初期ではBootJar,Jarの両方が生成される。

        // BootJar: sprigBootで使用されるGradleタスクの一つ。実行jarと呼ばれるファイルを生成する。
        // 実行jar(bootjar)はSpring Boot特有の設定や構造を持ったJAR(Java Archive)ファイル。
        // springbootを使用したMVCアプリケーションではこちらを使用する。
        withType<BootJar>().configureEach {
            archiveFileName.set("hoge-sample.jar")
            if (this.project == rootProject || !this.project.name.contains("fuga")) {
                enabled = false
            }
        }

        // Jar: 通常のJavaプロジェクトで使用されるタスクの1つ。
        // jarファイルはプロジェクトのソースコードとリソースを含み、依存関係を含まない自己完結型のjarファイルが生成される。
        withType<Jar>().configureEach {
            if (this.project == rootProject) {
                enabled = false
            } else {
                archiveBaseName.set("${rootProject.name}-${this.project.name}")
            }
        }
    }
}
```

### `subprojects`
サブプロジェクト全体への設定。
なお、Gradleのマルチプロジェクトではルートプロジェクトを作成する必要はなく、全てサブプロジェクトで構成されたプロジェクトでも良い。　
```kotlin
subprojects {
    // サブプロジェクトのコーディングで使用するプラグイン
    // Gradleプラグイン
    // ビルドスクリプトの依存関係以外ではpluginsブロックではなくapplyブロックを使用する。
        apply {
            plugin("kotlin")
            plugin("kotlin-spring")
            plugin("kotlinx-serialization")
            plugin("org.springframework.boot")
            plugin("io.spring.dependency-management")
        }

    // サブプロジェクトのコーディングで使用するプラグイン
    // Gradle以外のプラグイン
    dependencies {
        // implementation: コンパイルからビルドまで必要なプラグインを記述
        implementation("org.jetbrains.kotlin:kotlin-stdlib")
        implementation("org.jetbrains.kotlin:kotlin-reflect")
        implementation("org.jetbrains.kotlin:kotlin-gradle-plugin")
        implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core")
        implementation("org.springframework.boot:spring-boot-gradle-plugin:2.4.1")
        implementation("org.springframework.boot:spring-boot-starter-data-jpa")
        implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
        implementation("org.apache.commons:commons-lang3:3.12.0")
        // runtimeOnly: 実行時のみ必要なプラグインを記述
        runtimeOnly("com.mysql:mysql-connector-j")
        //　testImplementation: テストの実装から実行まで必要なプラグインを記述
        testImplementation("org.springframework.boot:spring-boot-starter-test") {
            // 不要な依存関係を除いている。
            exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
        }
        testImplementation("org.mockito.kotlin:mockito-kotlin:4.0.0")
        // その他主要なもの
        // compileOnly: コンパイル時には必要だが、実行時には必要ないプラグインを記述。
    }

    // configure<DependencyManagementExtension>: 依存関係管理の拡張機能の設定。一般にはmavenBom
    // を使用する際に使われる。
            
    configure<DependencyManagementExtension> {
        imports {
            // mavenBom
            // 親子関係にあるプロジェクトがバージョンの違う同一のモジュールに依存している場合、
            // 依存バージョンの違いからモジュールの競合が発生する。
            // これを防ぐためにモジュールのバージョンを管理および更新するためのもの。
            mavenBom(org.springframework.boot.gradle.plugin.SpringBootPlugin.BOM_COORDINATES)
        }
    }
}
```

### `project`
プロジェクト単位の設定
```kotlin
// サブモジュールの設定
project(":piyo-sample") {
    // プロジェクトのビルドに必要な依存関係(Gradleリポジトリ)
    apply {
        plugin("idea")
    }
    // プロジェクトのビルドに必要な依存関係(Gradleリポジトリ以外)
    dependencies {
        implementation("org.springframework:spring-web")
    }
    // tasks.: 指定したタスクの設定
    tasks.bootJar {
        enabled = false
    }
    tasks.bootRun {
        enabled = false
    }
    tasks.jar {
        enabled = true
    }
}

// メインとなるモジュールの設定
project(":hoge-sample") {
    apply {
        plugin("idea")
    }

    dependencies {
        // サブモジュールの依存関係もここで記述する。
        implementation(project(":piyo-sample"))
        implementation("org.springframework.boot:spring-boot-starter-web")
        implementation("org.springframework.boot:spring-boot-starter-security")
        implementation("org.springframework.boot:spring-boot-starter-aop")
        implementation("org.springframework.boot:spring-boot-starter-validation")
        implementation("org.springframework.boot:spring-boot-starter-actuator")
        implementation("com.opencsv:opencsv:5.8")
        testImplementation("org.springframework.security:spring-security-test")
        testImplementation("org.dbunit:dbunit:2.7.3")
        testImplementation("com.github.springtestdbunit:spring-test-dbunit:1.3.0")
    }

    // 以下の設定をしておくと、自動ビルド有効時ファイルが変更された時点で変更点が反映される。
    idea {
        module {
            inheritOutputDirs = false
            outputDir = file("$buildDir/classes/kotlin/main")
        }
    }
    
    // バージョンやグループといったビルド情報の乗ったファイルが作成され、アプリケーションに載せられる。
    springBoot {
        buildInfo()
    }
}
```