イマドキの Kotlin アプリケーション向け build.gradel.kts

f:id:Naotsugu:20211202204709p:plain


はじめに

Gradle Kotlin DSL もいろいろと変わっており、2022年における Kotlin アプリケーション向けの Build.gradle.kts の定義をまとめます。

Gradle は以下のバージョンを使用します。

$ gradle -v
Gradle 7.3

Kotlin は、2021年11月16日にリリースされた Kotlin 1.6 を使うものとします。


Build.gradle.kts

基本的な build.gradle.kts の構成は以下の様になります。

plugins {
    kotlin("jvm") version "1.6.0"
    application
}

repositories {
    mavenCentral()
}

kotlin {
    jvmToolchain {
        (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(17))
    }
}

dependencies {
    testImplementation(kotlin("test"))
}

tasks.test {
    useJUnitPlatform()
}

application {
    mainClass.set("app.AppKt")
}

以下詳細を見ていきます。


kotlin()

org.jetbrains.kotlin のグループIDは、Kotlin DSL の kotlin() で簡略化できます。

kotlin("jvm") version "1.6.0"

これは以下と同義となります。

id("org.jetbrains.kotlin.jvm") version "1.6.0"

kotlin() は、GenerateKotlinDependencyExtensions.kt から自動生成される、PluginDependenciesSpec の拡張関数で、以下のテンプレートから生成されます。

/**
 * Applies the given Kotlin plugin [module].
 * For example: `plugins { kotlin("jvm") version "$embeddedKotlinVersion" }`
 * Visit the [plugin portal](https://plugins.gradle.org/search?term=org.jetbrains.kotlin) to see the list of available plugins.
 * @param module simple name of the Kotlin Gradle plugin module, for example "jvm", "android", "kapt", "plugin.allopen" etc...
 */
fun PluginDependenciesSpec.kotlin(module: String): PluginDependencySpec =
    id("org.jetbrains.kotlin.${'$'}module")


なお、以下のような古いプラグインの適用は、問題があるため使用しないでください。

apply plugin: 'kotlin'


標準ライブラリ(stdlib)の依存

Kotlin 1.4.0 からは dependencies に標準ライブラリ(stdlib)の依存を追加する必要はありません。

Kotlin Gradle plugin と同じバージョンの標準ライブラリが自動的に追加されます。 標準ライブラリが自動的に追加を抑止するには kotlin.stdlib.default.dependency=false を使います。

旧来は以下のように標準ライブラリ(kotlin-stdlib-jdk8 など)の依存を追加していましたが、現在は不要です。

dependencies {
    implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}


Java ツールチェーンサポート

Kotlin 1.5.30 からは、Gradle 6.7 で追加された Java toolchains support が利用できます。

kotlin extension 経由で、以下のように指定できます。

kotlin {
    jvmToolchain {
        (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(17))
    }
}

java extension 経由で以下のように指定しても同様に機能します。

java {
    toolchain {
      languageVersion.set(JavaLanguageVersion.of(17))
    }
}

ツールチェーンを構成した場合、kotlinOptions.jvmTarget で明示的にターゲットバージョンが指定されていなければ、ツールチェーンで指定した JDK のバージョンが jvmTarget に設定されます(Kotlin 1.6.0 からは、JVM 17 に対応するバイトコードバージョンのクラスを生成できるようになりました)。

kotlinOptions.jvmTarget は以下のように指定することができますが、ツールチェーンを使うのが良いでしょう。

tasks {
    compileKotlin {
        kotlinOptions.jvmTarget = "11"
    }
    compileTestKotlin {
        kotlinOptions.jvmTarget = "11"
    }
}


kotlin.testAPI

以前は以下のように指定することが多かったですが、

dependencies {
    testImplementation("org.jetbrains.kotlin:kotlin-test")
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}

以下だけ指定すれば十分です。

dependencies {
    testImplementation(kotlin("test"))
}

Kotlin プラグインにより、ソースセットに依存関係として kotlin-test が追加されると、 kotlin-test-commonkotlin-test-annotations-common に加え、JVM ソースセットの場合は kotlin-test-junit(JSソースセットの場合はkotlin-test-js)が依存に追加されます。

デフォルトでは、JUnit4 が選択されます。JUnit5を使う場合は以下とします。

tasks.test {
    useJUnitPlatform()
}

なお、TestNG を使う場合は以下を設定します。

tasks.test {
    useTestNG()
}

org.gradle.api.tasks.testing.Test が参考になります。



JavaFX アプリケーション

一例として、Kotlin で JavaFX アプリケーションを作る場合の定義を見ておきましょう。

plugins {
    kotlin("jvm") version "1.6.0"
    id("org.openjfx.javafxplugin") version "0.0.10"
    application
}

repositories {
    mavenCentral()
}

kotlin {
    jvmToolchain {
        (this as JavaToolchainSpec).languageVersion.set(JavaLanguageVersion.of(17))
    }
}

dependencies {
    testImplementation(kotlin("test"))
}

tasks.test {
    useJUnitPlatform()
}

application {
    mainClass.set("app.AppKt")
}

javafx {
    modules("javafx.controls", "javafx.fxml")
}

src.main.kotlin.app.App.kt は以下のように定義します。

package app

import javafx.application.Application
import javafx.event.ActionEvent
import javafx.event.EventHandler
import javafx.stage.Stage
import javafx.scene.Scene
import javafx.scene.control.Button
import javafx.scene.layout.StackPane

class App : Application() {

    override fun start(primaryStage: Stage) {
        val btn = Button()
        btn.text = "Button"
        btn.onAction = EventHandler<ActionEvent> { println("Hello World!") }

        val root = StackPane()
        root.children.add(btn)

        val scene = Scene(root, 300.0, 250.0)
        primaryStage.title = "Hello World!"
        primaryStage.scene = scene
        primaryStage.show()
    }
}

fun main(args: Array<String>) {
    Application.launch(App::class.java, *args)
}

以下のウィンドウが立ち上がり、ボタンクリックでコンソールに 「Hello World!」を出力します。

f:id:Naotsugu:20211202201247p:plain


まとめ

変化が早く、検索では古い情報が多く見られるため、Gradle Kotlin DSL のイマドキの定義について記しました。



基礎からわかる Kotlin

基礎からわかる Kotlin

Amazon