GradleでKotlinプロジェクトを一撃生成する

KotlinアプリケーションのプロジェクトをGradleで生成する方法を紹介する。

プロジェクトを作るディレクトリをこしらえておく:

```
mkdir hellogradle
cd hellogradle
```

次のgraldeコマンドを実行する。

```
gradle init --type=kotlin-application
```

ちなみにこの`kotlin-application`を選択した場合、次のことが起こる。

1. コマンドラインアプリを作るために`org.jetbrains.kotlin.jvm`と`application`プラグインが使われる。
2. 依存リポジトリに`jcenter`を使う。
3. Kotlin 1.xを使う。
4. テストに[Kotlin test](https://kotlinlang.org/api/latest/kotlin.test/index.html)ライブラリを使う。
5. src/{main,test}のようなよくある構成のディレクトリが作られる。
6. App.ktとAppTest.ktが作られる

`kotlin-application`の詳細は公式ドキュメント参照: [Build Init Plugin](https://docs.gradle.org/current/userguide/build_init_plugin.html#sec:kotlinapplication_)

コマンドを実行するといくつか質問されるので答えていく。

1つ目。GradleのDSLはGroovyにするか、Kotlinにするか。昔ながらのGradle DSLを使う場合は1、[Kotlin DSL](https://docs.gradle.org/current/userguide/kotlin_dsl.html)が使いたい場合は2を入力する。


* **[Kotlin DSLを使ってみての感想]** Gradle公式サイトはGroovy DSLとKotlin DSLが併記してあって、Kotlin DSLを選択しても支障がなかったが、サードパーティのプラグインのドキュメントは依然としてGroovy DSLのみで解説が多かったり、Qiitaなどの技術ブログもGroovy DSLでの解説が主流なので、Kotlin DSLの選択は冒険的だった。また、Groovy DSLとKotlin DSLは異なる書き方が多く、両者のDSLをよく知っていないと翻訳は難しかった。ネット上の情報をコピペで済まそうと考えているなら**Groovy DSLを選択したほうが無難**と感じる。今後、Kotlin DSLに自動翻訳する機能が一般化してきたらこの意思決定は変わるかもしれない。


```
Select build script DSL:
  1: groovy
  2: kotlin
Enter selection (default: kotlin) [1..2]
```

2つ目。プロジェクト名は？

```
Project name (default: hellogradle): hello-gradle
```

3つ目。パッケージ名。Javaの規約に習って所有しているドメイン名+プロジェクト名にする。ドメインを持っていない場合は、例示用TLD(`.example`)を使って`example.hellogradle`にする。

```
Source package (default: hello.gradle): io.suin.hellogradle
```

以上。

```
BUILD SUCCESSFUL in 26s
2 actionable tasks: 2 executed
```

## 作られるファイル

```
.
├── build
│   └── classes
│       └── kotlin
│           └── main
│               └── helloworld
│                   ├── App.class
│                   └── AppKt.class
├── build.gradle.kts
├── gradle
│   └── wrapper
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle.kts
└── src
    ├── main
    │   ├── kotlin
    │   │   └── io
    │   │       └── suin
    │   │           └── hellogradle
    │   │               └── App.kt
    │   └── resources
    └── test
        ├── kotlin
        │   └── io
        │       └── suin
        │           └── hellogradle
        │               └── AppTest.kt
        └── resources
```

中身を見てみる。

まず、build.gradle.kts。Kotlinアプリケーションとしてビルドするのに必要な情報などが記述されている。上で設定した、パッケージ名も書いてある。

```kotlin:build.gradle.kts
/*
 * This file was generated by the Gradle 'init' task.
 *
 * This generated file contains a sample Kotlin application project to get you started.
 */

plugins {
    // Apply the Kotlin JVM plugin to add support for Kotlin on the JVM.
    id("org.jetbrains.kotlin.jvm").version("1.3.21")

    // Apply the application plugin to add support for building a CLI application.
    application
}

repositories {
    // Use jcenter for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}

dependencies {
    // Use the Kotlin JDK 8 standard library.
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")

    // Use the Kotlin test library.
    testImplementation("org.jetbrains.kotlin:kotlin-test")

    // Use the Kotlin JUnit integration.
    testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
}

application {
    // Define the main class for the application.
    mainClassName = "io.suin.hellogradle.AppKt"
}
```

次に、settings.gradle.kts。先程設定したプロジェクト名が記述されているようだ。

```kotlin:settings.gradle.kts
/*
 * This file was generated by the Gradle 'init' task.
 *
 * The settings file is used to specify which projects to include in your build.
 *
 * Detailed information about configuring a multi-project build in Gradle can be found
 * in the user manual at https://docs.gradle.org/5.3/userguide/multi_project_builds.html
 */

rootProject.name = "hello-gradle"
```

App.kt。Hello Worldするプログラムが作られてる。

```kotlin:src/main/kotlin/io/suin/hellogradle/App.kt
/*
 * This Kotlin source file was generated by the Gradle 'init' task.
 */
package io.suin.hellogradle

class App {
    val greeting: String
        get() {
            return "Hello world."
        }
}

fun main(args: Array<String>) {
    println(App().greeting)
}
```

最後に、AppTest.kt。`App.greeting`の値をテストするサンプルが作られている。

```kotlin:src/test/kotlin/kotlin/app/AppTest.kt
/*
 * This Kotlin source file was generated by the Gradle 'init' task.
 */
package io.suin.hellogradle

import kotlin.test.Test
import kotlin.test.assertNotNull

class AppTest {
    @Test fun testAppHasAGreeting() {
        val classUnderTest = App()
        assertNotNull(classUnderTest.greeting, "app should have a greeting")
    }
}
```

## 次のステップ

* [Gradleでタスクの一覧を表示する - Qiita](https://qiita.com/suin/items/1dc1b76b60246a45fac9)
* [gradleとgradlewの違い - Qiita](https://qiita.com/suin/items/266830c0ce37e823916d)
* [Gradleでアプリを実行する - Qiita](https://qiita.com/suin/items/58f3f49e67677e62f217)
* [Gradleで生成したKotlinプロジェクトをIntelliJで開く - Qiita](https://qiita.com/suin/items/ec268d029dd0f9a39e46)
* [Gradle: 依存ライブラリ入りのjarを作る - Qiita](https://qiita.com/suin/items/641c1c1ec9ab5447221e)