もうbuild.gradle.ktsに振り回されたくない！タスク実行順編

文献がない（少ない）！

build.gradle(not Kotlin)しかない（検索しても）！

僕がやりたいのはprintlnじゃない（公式ガイドに対する心の叫び！）！！

※結論は一番下ですので、お急ぎの方は一番下までスクロールしてください。

# やりたいこと

私のいる現場のMyBatis Generator周りのビルド手順に
「あれして」「これして」「gradleコマンドを打って」「最後にこれ」
と書かれていたのでなんとかしたかった。

具体的には

- 特定のフォルダの中身を全部削除して
- MyBatis Generatorで自動生成したコードだけをJarに固めて
- GitにCommitできる場所に出す

# 環境
- Gradle 6.8.1
- Kotlin 1.5.20
- MyBatis Generator 1.4.0

# 状況整理

MyBatis Generatorの自動生成コードを作って固めるにあたり、実行しなければいけないのは以下です。

- mbGenerator(自作タスク。※コマンド名には個人差があります、詳しくはMyBatis Generatorで検索）
- build

加えて、GitにCommitするにあたり、古いコードは消す必要があります。

- clean
- cleanDirs（自作タスク。Commit用ディレクトリ・自動生成コードを削除）

```build.gradle.kts
tasks.register("cleanDirs", Delete::class) {
    delete(fileTree("削除したいJarのパス").matching { include("*.jar") }
    delete(fileTree("削除したい自動生成コードのパス").matching { include("*.kt") }
    mustRunAfter("clean") //※後述A
}
```

最後に、build配下に自動生成されたJarをGitにCommitできるパスに持ってくる必要があります。

- copyJar（自作タスク。上述）

```build.gradle.kts
tasks.register("copyJar", Copy::class) {
    from("build/libs")
    include("*.jar")
    into("generated/libs")
    mustRunAfter("build") //※後述A
}
```

# やりたいことを一気に実行してくれるタスクを作る

- generatedJar

```build.gradle.kts
tasks.register("generatedJar") {
    dependsOn(tasks.named("clean"))
    dependsOn(tasks.named("cleanDirs"))
    dependsOn(tasks.named("mbGenerator"))
    dependsOn(tasks.named("build"))
    dependsOn(tasks.named("copyJar"))
```

…Jarができない。
できるときもある。
・・・？

実は
「dependsOnは順番が固定されない」

これはぐぐると色々出てきます。今回はこれがテーマです。

# 順番を指定しよう
## ボツ案１ doFirst, doLast
doFirst, doLastなるものがあるらしい

```（動きません）build.gradle.kts
tasks.register("generatedJar") {
    doFirst {
        dependsOn(tasks.named("clean"))
        dependsOn(tasks.named("cleanDirs"))
    }
    dependsOn(tasks.named("mbGenerator"))
    doLast {
        dependsOn(tasks.named("build"))
        dependsOn(tasks.named("copyJar"))
    }
}
```

なぜ動かないか

それは「依存の"定義を先に"しただけ」だから。先に実行するとは言ってない。

たしかに

## ボツ案２ generatedJarの中でmustRunAfter（後述A）
順番を指定してくれるmustRunAfterを使ってみます。
上述の通り、 `cleanDirs` と `copyJar` にはタスク定義の中にmustRunAfterを書いたので、その間を繋いでみます

```（微妙に動きません※後述B）build.gradle.kts
tasks.register("generatedJar") {
    dependsOn(tasks.named("clean"))
    dependsOn(tasks.named("cleanDirs")) // mustRunAfterと一緒に書かないと実行してくれません
    dependsOn(tasks.named("mbGenerator")) // mustRunAfterと一緒に書かないと実行してくれません
    dependsOn(tasks.named("build"))
        .mustRunAfter("mbGenerator")
        .mustRunAfter("cleaDirs")
    dependsOn(tasks.named("copyJar"))
}
```

一応書いたものの順番は守ってくれるようになりました。
ただ、mustRunAfterの部分だけ逆順になってるのはしんどい。。

あと、※後述B、と書いていますが
「 `build` より先に `mbGenerator` を実行すると言ったが、"コンパイルより先とは言ってない"」
という地獄の状況になっています。

## 最終形（後述B）

１つ１つのタスクに、個別にmustRunAfterを付けていきましょう。これで順番が１つずつ定まります。

そして後述Bのポイントですが、 `build` ではなく `compileKotlin` の前に `mbGenerator` が実行されるようにしてください。

```build.gradle.kts
tasks.register("cleanDirs"), Delete::class) {
    ..
    mustRunAfter("clean")
}

tasks.named("mbGenerator") { mustRunAfter("cleanDirs") }

tasks.named("compileKotlin") { mustRunAfter("mbGenerator") } // 後述Bのポイント！


tasks.register("copyJar"), Copy::class) {
    ..
    mustRunAfter("build")
}

tasks.register("generatedJar") {
    dependsOn(tasks.named("clean"))
    dependsOn(tasks.named("cleanDirs"))
    dependsOn(tasks.named("mbGenerator"))
    dependsOn(tasks.named("build"))
    dependsOn(tasks.named("copyJar"))
}
```

ようやくできました。めでたい

# （おまけ）実行されるタスク順の確認方法
-mをつけたらドライランができます。これで確認してください。
※上述の通り順番が変わることがあるので、何度か実行してみてください。

```
gradle generatedJar -m
```