GradleとIntelliJで始めるKotlin (プロジェクト作成編)

## 導入
[前編](https://qiita.com/sjelik22/items/6cd43a627e6f8b6b508c)からの続き。実際にプロジェクトを作成し始めます。

## どうやるの?
IntelliJ IDEAのプロジェクト作成機能を使っても作れます。[(参考)](https://www.jetbrains.com/help/idea/create-your-first-kotlin-app.html#create-project)
すぐにKotlinを書き始めたい人はその機能を使ってやってみてください。

今回は他に説明したいことがあるため、この機能に頼らずにやってみます。

## この記事上の環境
- Windows10 (MacやLinuxは他の方の情報を参照してください。)
- IntelliJ IDEA 2022.1.3 (Community Edition)
- Gradle 7.4.2
- Kotlin 1.6.21

## 1. gradle init
前編で指定したプロジェクト管理のフォルダ内に
好きな名前(2バイト文字は避けたほうがいいです。)でフォルダを作ってください。
今回はその名前をプロジェクトの名前としてプロジェクトを作ってみましょう。

作ったフォルダ内にてpowershell等のターミナルから
`gradle init`コマンドを実行します。

Gradleデーモンが立ち上がった後プロジェクトの初期設定が始まります。
いくつかの質問があり、ユーザーはそれらに回答することで設定が行われます。
#### `Select type of project to generate:`
今回は `1: basic` でいきます。
#### `Select build script DSL:`
`2: Kotlin` です。
#### `Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no)`
`no`を入力します
#### `Project name (default:フォルダの名前)`
空欄のままEnterを押しましょう。

`> Task :init BUILD SUCCESSFUL`
と表示されたらプロジェクトの基礎部分は作成完了です。
作成されたファイル群に肉付けして好みの仕様になるよう変更してきます。

## 2. Gradleの世界とIntelliJ IDEA
ここでいきなりですが、この界隈の要素たちを紹介します。
### プロジェクト
ソースコード等を含むディレクトリの束をひとまとまりにして扱うとき、
これをGradle界隈では、**プロジェクト** と呼びます。

世のプログラマーたちは、自分たちの作ってきたものが大きくなりすぎると管理が面倒だからとかなんか言って
それを細切れに分割したがる傾向があります。

Gradleはそうした人たちの意向を反映してかは知らないが、それをサポートしたような機能を持ち合わせています。

Gradleでは、１つのプロジェクトから１つのソフトウェアBuildを作ることができますが、
複数のプロジェクトから1つのソフトウェアBuildを作ることもできます。

分割したい人は１つのプロジェクトから作り始めていたとしても、自分の好きなタイミングでそれを
複数のプロジェクトに分割すればいいわけです。

ちなみにこのプロジェクトが複数だった場合のことを、**マルチプロジェクト**と呼びます。

### SourceSet
１つのプロジェクトの内部の、意味合いを持ったフォルダ構造に対して
名前を付けることができます。これを **SourceSet** と呼びます。
プロジェクトは、これを１つでも複数でも持つことができます。

### モジュール
上記の２つに似た概念としてIntelliJ IDEAにおける **モジュール** というものが存在します。
このモジュールというものは、１つのプロジェクトにつき(もしくは、SourceSetごと込みの単位で)、
1つないし複数のモジュールが勝手にIntellij IDEAによって作成されます。
このモジュールは、これらのまとまりたちをIDE側から管理する際に使用されるらしいです？。多分。[(参考)](https://www.jetbrains.com/help/idea/creating-and-managing-modules.html)


## 3. 生成されたファイルたちを見る。
ざっくり一つずつ見ていきましょう。
-  `.gradle`フォルダ

gradleのプロジェクト単位のキャッシュが保存されます。

-  `.gitattributes` 
-  `.gitignore`

gitがらみのファイルですが勝手に追加されます。今回は気にしません。

- `gradle`フォルダ

ここには、**Gradle Wrapper** と呼ばれるものの設定ファイルが置かれます。[(参考)](https://docs.gradle.org/current/userguide/gradle_wrapper.html)
フォルダを辿っていった中にある`gradle-wrapper.properties`とかいうファイルがそれです。
Gradleのバイナリをどっから持ってきて、それをどうやってBuildに使うかなど情報をこのファイルに示します。

- `gradlew.bat`

windowsでpowershell等のターミナルで実行できるファイルです。
`gradlew.bat`は`gradle.bat`と同じコマンドを実行することができます。

gradlewへコマンドを投げた場合、↑で書かれてあるGradle Wrapperを使用してGradleを準備してから、
gradleコマンドを実行してくれます。
Gradle Wrapper が用意されてあれば、
プロジェクトをBuildしたい人の手元の環境にGradleが準備されていなくとも、
gradlewコマンドを使うことによってBuildすることができるわけです。

- `setting.gradle.kts`
- `build.gradle.kts`

ビルド時に実行される処理のあれこれたちを記述するのがこれらの設定ファイルたちになります。

gradle init時にDSLの言語をKotlinに選択しましたので、
この先の章(4章から)ではこちらのファイルたちをKotlinで書いていくことにします。

## 3.5. IntelliJ IDEA でプロジェクトを開いてみる。
Welcome to InteliJ IDEA の画面から右上のOpenボタンをクリックすると
フォルダ選択画面が出ますので、先ほどgradle init を実行したフォルダを選択してください。

GradleによってBuildが走った後、
プロジェクトが開かれます。(Buildには多少時間がかかります。)

ここで、次のようなエラーが出ることがあります。
![invalid.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735192/3658c0af-9b88-5cef-fa20-5c18a195f93b.png)
このようなエラーが出た場合、
`File > Settings > Build, Execution, Deployment > Build Tools > Gradle`
の中にある**Gradle JVM**を設定する必要があります。
なぜなら、Gradle自体が動くのにJVMを必要とするからです。

この時必要になるJDKですが、手動でダウンロードしなくてもこのメニューの中の
Download JDK ...からダウンロードできます。
今回は
Version:17
Vendor: Amazon Corretto
のJDKを使ってやってみたいと思います。

設定が終わりましたら、IntelliJ IDEAを再起動してみてください。
またBuildが走って無事終わればプロジェクトが開かれます。

出てきた画面から左のタブのProjectを押すとプロジェクトの階層が表示されます。

よく見ると、先ほどまでにはなかったフォルダが存在しているのがわかりますでしょうか。
IntelliJ IDEAによって開かれることで、新しく`.idea`フォルダが追加されました。
![ここ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735192/33bd5693-04d8-a6a6-600d-51c702b3079c.png)

ここには、基本的にはBuild周りには影響しないような、例えばプロジェクトレベルでの見た目の調整など、
IDE側の設定をいじった時の情報が保存されるみたいです。[(参考)](https://www.jetbrains.com/help/idea/configure-project-settings.html)

そしてここからは実際にファイルを編集してきますが、
それらの操作はIntelliJ IDEA上で行っていきます。

## 4. setting.gradle.ktsをみる。
Gradleでは複数(もしくは1つ)のプロジェクトからなる構成を作る場合、それらのプロジェクトから参照できるような、
１つのルートになるプロジェクトを指定する必要があります。
ファイルの中を開いてみますと、
```kotlin:setting.gradle.kts
rootProject.name = "作成したフォルダ名"
```
の一行だけがあるはずです。
すでにこのプロジェクトがルートとして書かれていることがわかります。

マルチプロジェクトの場合は更に、このルートプロジェクトにぶら下がる形で他のどのプロジェクトを含めるかというのを
この`setting.gradle.kts`にて指定します。（今回はやりません)

## 5. build.gradle.ktsに書き込んでゆく。
このファイルはGradleのBuild周りの処理を全部書いていくためのものになります。

ファイルの中身を見てみてください。空っぽです。
```kotlin:build.gradle.kts
/*
 * This file was generated by the Gradle 'init' task.
 *
 * This is a general purpose Gradle build.
 * Learn more about Gradle by exploring our samples at https://docs.gradle.org/7.4.2/samples
 */

```
プロジェクトを作ったときに`basic`を選択してしまったあまりに、すべてを記述しなければならなくなってしまいました。

私たちはKotlinソースコードを書き、それをBuildしたいはずです。
なにを記述すればいいのでしょうか？

Gradleでは、Pluginと呼ばれるものをインポートすることで機能を拡張することができます。

大体Gradleが使える言語では、言語ごとの機能拡張分がPluginとして提供されていますので、
それのKotlinのものをインポートすることから始めていきます。

下のコードブロックをコピペして貼り付けてみてください。

```kotlin
plugins {
    kotlin("jvm") version "1.6.21"
}
```
貼り付けましたでしょうか。
そしたらなんかコードを張り付けた個所の少し右あたりになにやらボタンが出現しているのが
わかりますでしょうか。
![これ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735192/7f1dfb3a-b5c0-3c93-b9fc-0de3ffa1f37c.png)

２つボタンがありますので左から順に両方とも押してってください。
これらのボタンを押すと、Gradleスクリプトを変更したよ、ということをIntelliJ IDEAに伝えられます。
このボタンたちがでたら、とりあえず押しておくようにするといいと思います。

そして、下のなんかいろいろあるところの中からBuildタブを選んで開いてみてください。
![build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735192/9aaa197a-84ea-fa8a-2b8f-3d2310a342cc.png)
たぶん、こんなエラーが表示されていると思います。
もしかしたら表示されていないかもしれません。
このエラーの理由はあとで説明することになります。

ですが、その説明の前に紹介しておかなければならない事柄があります。

実は、Pluginを追加したことによってこのプロジェクトには、
新たにSourceSetが追加されています。

次のコードを先ほどのpluginsブロックの下とかに張り付けてみてください。(コードはわからなくていいです。)
```kotlin
kotlinSrcDirs().onEach{
    println(it)
}

fun kotlinSrcDirs(): List<String> {
    val paths = mutableListOf("")
    kotlin.sourceSets.onEach {
        it.resources.srcDirs.onEach{
            paths.add(it.absolutePath)
        }
        it.kotlin.srcDirs.onEach {
            paths.add(it.absolutePath)
        }
    }
    return paths
}
```
先ほどと同じように出てきたボタンを押して、
Buildタブを開いて、左半分にあるエラーのリストみたいなのの中から一番上の
プロジェクト名:finished At ~~~  になっているところを　押すと
下の画像に似た感じのものが表示されているはずです。
![path.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735192/245f23aa-331a-84b2-322c-59f83f514c49.png)

表示されたこれらのPathたちは現在、
新たに追加されたSourseSetとしてGradleに存在している形になっています。

Kotlin pluginは、このSourceSetたちの、
これらのパスのフォルダの中にあるソースコードなどを、
コンパイルなどのBuildの対象としてGradleに認識させるようにしてくれています。

ということで、ソースコードを書きたいときはこの中から適切なものを選んで、
そのPathの中に配置したファイルに書いていけばいいということになります。

## 6. Kotlinソースコードを作ってみる。
先ほど表示されたPathの中から **"/src/main/kotlin"** というものを選びまして、
実際にフォルダとソースコードを配置してみたいと思います。

プロジェクトのフォルダの中にsrcフォルダを作成します。
そのsrcフォルダの中にmainフォルダを、そしてその中に
kotlinフォルダを作成することになります。

これは手動でフォルダ作ってもいいですが、
IDE上でも簡単にできます。
![new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735192/c83151c3-a347-5ce7-54ab-c4d9ac927f74.png)
projectのルートを右クリック → New → Directory　から
![これ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735192/0f10c3a0-188d-3d39-519a-7f02d2b75c45.png)
これを選んでクリックすれば勝手に作成されます。

したらば、作成された一番深いkotlinのところのフォルダの中に.ktファイルを作ります。
名前は何でもいいですがとりあえずmain.ktとしておきます。

下のコードを張り付けてみてください。

```kotlin:main.kt
fun main() = println("hello world?")
```
これは画面にhello world?と表示するだけのシンプルなプログラムです。

貼り付けたうえで、
IntelliJ IDEA上でこのファイルを見ると、こんな感じになっていると思います。
![うまくいっていない例.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735192/e5e07d5a-de05-2715-8e4d-7445a4764e88.png)
なんかいろいろ変化がありますね。
IntelliJ IDEAは書いてあるソースコードがミスってたり解釈できないときに
警告を表示してくれるようになっています。

なにかがおかしそうです。
何か間違ってるんでしょうか？

エラーの内容を調べていきましょう。
printlnのところにカーソルを合わせてみてください。
![unresolved.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735192/ec383d67-1381-13ff-403c-43bc15fac549.png)
**Unresolved reference: println**　とでてますね。
どうもprintlnへの参照が解決できないせいでエラーが発生しているようです。

printlnとは何かというと、`kotlin-stdlib` という、
Kotlinが標準で使える関数のライブラリの中に入っている関数です。

これが使えていないということは、現状Kotlinが標準で使える関数が何も使えない、という状態になっています。

ここでBuildタブの左半分のエラーの一覧のところから、
Could not resolve ~~~~ になっているところを選択してください。
![couldnot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2735192/365716ea-5079-c1d2-8a48-2d805555bfbd.png)
ここにエラーの原因が書かれています。
`Cannot resolve external dependency ~~~ because no repositories are defined.`
リポジトリが定義されていないので外部の依存関係が解決できません。とのことです。
repositoriesが定義されていないのが、ダメみたいです。

ということで下のコードを`build.gradle.kts`に追加で張り付けてみてください。
```kotlin
repositories {
    mavenCentral()
}
```
エラーが解消され、警告も表示されなくなりました。


でも、私たちは外部への依存関係を追加してはいないはずです。
なぜこうなるのでしょうか？

その答えが[公式](https://kotlinlang.org/docs/gradle.html#dependency-on-the-standard-library)に書かれています。
```
A dependency on the standard library (stdlib) is added automatically to each source set.
(引用元:https://kotlinlang.org/docs/gradle.html#dependency-on-the-standard-library)
```
Kotlinの標準ライブラリ(stdlib)の依存関係は各SourceSetに対し、自動的に追加されますとのことです。

私たちはこのstdlibを、どこから持ってきたらいいかを、Gradleに対して提示していませんでした。
これによってエラーが発生していたのでした。

このKotlinのstdlibと呼ばれるものはMavenCentralというリポジトリに[保管](https://search.maven.org/artifact/org.jetbrains.kotlin/kotlin-stdlib-jdk8/1.6.21/jar)されています。

リポジトリはこのMavenCentral以外にもありますが、
有名なライブラリはほぼほぼこのリポジトリにある（と思います。）ので、
それ以外のリポジトリは必要になったときに適宜追加していくことになります。



#### 最終的なbuild.gradle.kts
最終的には、このようになりました。
```build.gradle.kts
plugins {
    kotlin("jvm") version "1.6.21"
}

repositories {
   mavenCentral()
}
```
もちろん、これはKotlinが動く最低限度のものになります。

これ以外にもGradleでは、標準以外の他のライブラリを取り込んだりすることも、
また、**Task**と呼ばれるものを使いこなすことによってより便利なことを行うことも、できます。

ですがまぁ、記事が長くなりすぎるのでやめておきたいと思います。

またKotlinには、**Multiplatform** というものがあります。
今回はJVM向けですので、ちょっと違いますが似たような感じで行けますので、[(参考)](https://kotlinlang.org/docs/gradle.html#targeting-multiple-platforms)
興味のある方はやってみてくださいませ。


## 5. プログラムを動かしてみる。
`main.kt`の fun main()とか書いてあるところの左に緑の三角があると思います。
そこを押して、Run 'MainKt' を選んでください。
プログラムが実行されます。

## まとめ
これでKotlinコードを書いて、動かす所までできるようになりました。
お疲れさまでした。

<!-- fixmeリスト
・JDKの説明をしていない(動くかわからない)
・GradleにもJVMがいることを伝えてない
-->