いい感じのbuild.gradleが書きたい

build.gradleについて調べた時に引っかかったこととか見つからなかったこととか

# 環境

- Gradle6.4 (2020/5/6リリース)

# 始めに

とりあえず[Gradleのドキュメント](https://docs.gradle.org/6.4/userguide/userguide.html)見てみると良いかもしれない

# 便利なプラグイン

名前のリンクはドキュメントへ

- [java](https://docs.gradle.org/6.4/userguide/java_plugin.html)プラグイン。これがないとJavaのソースがコンパイルできない
- [checkstyle](https://docs.gradle.org/6.4/userguide/checkstyle_plugin.html)プラグイン。スタイルを揃える時にあると便利([説明セクションへ](#checkstyleを導入する))
- [shadow](https://imperceptiblethoughts.com/shadow/)プラグイン。Fat-Jar(Uber-Jar)プラグインの生成に必要([説明セクションへ](#shadowプラグインを使ってfat-jaruber-jarを生成する))
- [ErrorProne](https://github.com/tbroyer/gradle-errorprone-plugin)プラグイン。静的解析ツール。アンチパターンを探してくれるやつ([説明セクションへ](#errorproneを導入する))

# Wrapperを使う

`./gradlew`とか`./gradlew.bat`とかのこと。`wrapper`タスクの実行で初期化したり更新できたりする
これさえあれば開発者の環境にインストールされているgradleのバージョンが違っても大丈夫！

公式ドキュメント: [The Gradle Wrapper](https://docs.gradle.org/6.4/userguide/gradle_wrapper.html)

# エンコーディングを指定する

指定しないとLinuxとWindowsでビルド結果が変わったりする

例えばUTF-8に指定する時はこういう感じ

```groovy:build.gradle
// compileJavaタスクのエンコーディング
compileJava.options.encoding = 'UTF-8'
// compileTestJavaタスクのエンコーディング
compileTestJava.options.encoding = 'UTF-8'
// javadocタスクのエンコーディング
javadoc.options.encoding = 'UTF-8'
```

# 依存関係の宣言

**`compile`とか`testCompile`は非推奨のため使わない**
`implementation`とか`testImplementation`とか色々あるが、面倒なので公式ドキュメント
[The Java Plugin](https://docs.gradle.org/6.4/userguide/java_plugin.html#sec:java_plugin_and_dependency_management)
`api`とかは
[The Java Library Plugin](https://docs.gradle.org/6.4/userguide/java_library_plugin.html#sec:java_library_configurations_graph)に書いてある

一応簡単な説明
`compileOnly`はコンパイル時に必要な依存関係。FatJarなどには入らない(Mavenでいう`provided`スコープ)
`runtimeOnly`は実行時に必要な依存関係。FatJarなどには入るがソースコード内からは参照不可(だと思うが使ったことがないのでわからない)
`implementation`はコンパイル時にも実行時にも必要な依存関係。FatJarにも入るしソースコード内からも参照可能だが、これを依存関係とするプロジェクトからは参照不可能(Mavenでいう`provided`として認識される)
参照できるようにするにはJava Library Pluginの`api`を使う

また、先頭に`test`とついているもの(例えば`testImplementation`など)は、テスト時にしか有効でない

## バージョンを範囲指定する

公式ドキュメントはここ: [Declaring Versions and Ranges](https://docs.gradle.org/6.4/userguide/single_versions.html)

```groovy:build.gradle
testImplementation 'org.junit.jupiter:junit-jupiter:5.6.+'
```
とかすれば5.6.以下はその時の最新バージョンを使うようになる。  
この影響でビルドした環境によってビルド結果が変わるかもしれないので、防止したい場合は[依存関係を固定する](#依存関係を固定する))

## 依存関係を固定する

公式ドキュメントはここ: [Locking dependency versions](https://docs.gradle.org/6.4/userguide/dependency_locking.html)

# ErrorProneを導入する

pluginsに追加する

```groovy:build.gradle
    id 'net.ltgt.errorprone' version '1.1.1'
```

依存関係に追加する

```groovy:build.gradle
dependencies {
    // ErrorProne
    errorprone 'com.google.errorprone:error_prone_core:2.+'
}
```

Java8の場合はJava9コンパイラを突っ込む

```groovy:build.gradle
dependencies {
    errorproneJavac 'com.google.errorprone:javac:9+181-r4173-1'
}
```

Java8の環境でもJava9以上でも実行できるようにしたい場合はこうすると良いかも

```groovy:build.gradle
if (!JavaVersion.current().isJava9Compatible()) {
    dependencies {
        errorproneJavac 'com.google.errorprone:javac:9+181-r4173-1'
    }
}
```

javacが置き換えられるっぽいので全部のコンパイルタスクに適用される

# CheckStyleを導入する

pluginsに追加する

```groovy:build.gradle
plugins {
    id 'checkstyle'
}
```

config/checkstyle/checkstyle.xmlをいじる。例えばこう

```xml:checkstyle.xml
<?xml version="1.0"?>
<!DOCTYPE module PUBLIC
          "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
          "https://checkstyle.org/dtds/configuration_1_3.dtd">
<module name="Checker">
    <module name="FileTabCharacter"/>
    <module name="TreeWalker">
        <module name="Indentation">
            <property name="lineWrappingIndentation" value="8"/>
        </module>
        <!-- Imports -->
        <module name="UnusedImports"/>
        <module name="RedundantImport"/>
        <module name="ImportOrder">
            <property name="separated" value="true"/>
            <property name="sortStaticImportsAlphabetically" value="true"/>
        </module>
        <!-- Brackets -->
        <module name="LeftCurly"/>
        <module name="RightCurly"/>
        <module name="NeedBraces"/>
    </module>
</module>
```

[公式ドキュメントがいい感じ](https://checkstyle.sourceforge.io/checks.html)

buildタスク実行すれば勝手に実行される

# JUnitを使って単体テストをする

依存関係に追加して

```build.gradle
testImplementation 'org.junit.jupiter:junit-jupiter:5.6.+'
```

こういう感じで設定するといい感じになる

```groovy:build.gradle
tasks.test {
    testLogging.showStandardStreams = true // System.outとかerrをログに表示する
    useJUnitPlatform()
    testLogging {
        events('passed', 'skipped', 'failed')
    }
}
```

[JUnit 5 User Guide](https://junit.org/junit5/docs/current/user-guide/#writing-tests)

# shadowプラグインを使ってFat Jar(Uber Jar)を生成する

プラグインとして追加する

```build.gradle
plugins {
    id 'com.github.johnrengelman.shadow' version '5.2.0'
}
```

`shadowjar`タスクを実行すればbuild/libs下に完成

relocateしたりminimizeしたりjar名変えたりできるけど面倒なので公式ドキュメントを
https://imperceptiblethoughts.com/shadow/introduction/

# 検索できるJavadocを生成する

```build.gradle
javadoc {
    if(JavaVersion.current().isJava9Compatible()) {
        options.addBooleanOption('html5', true)
    }
}
```

これでjavadocタスクがいい感じになる(Java9以上が必要)