【Gradle】規約と異なる構成のJavaプロジェクトをビルドする

# 概要
Gradleは規約の考えを取り入れているため、デフォルトでは想定するフォルダ構成でない
プロジェクトをビルドすることができない。
しかし、Gradleではコンフィグレーション、プロパティを変更することにより
それらの規約を柔軟に変更することが可能である。

# プロパティからのアプローチ
例として、mainソースセットのJavaソースとリソースの配置に関する規約を変更する。

今回は、以下の構成のプロジェクトをビルドする。

```text:プロジェクト構成
<project-root>
└ src
    ├ Mapping.xml
    ├ app.properties
    └ examples
        └ Dummy.java
```

Gradleにおいて、Javaソースはsrc/main/javaディレクトリ以下に、
リソースはsrc/main/resourcesディレクトリ以下に配置されることを想定している。

しかし、上記プロジェクトではJavaソースもリソースもsrcディレクトリにまとめられている。
よって、ビルドスクリプトでJavaソースとリソースの配置パスを設定することで
デフォルトの規約に沿わないプロジェクトをビルドする。

```gradle
apply plugin: 'java'

sourceSets {
    main {
        java {
            // sourceSets.main.java.srcDirsプロパティに設定を追加
            // = Javaソースの配置先を設定
            srcDir 'src'
        }
        resources {
            // sourceSets.test.java.srcDirsプロパティに設定を追加
            // = リソースの配置先を設定
            srcDir 'src'
        }
    }
}

processResources {
    // .javaファイル以外が存在しないディレクトリをコピー対象から除外
    includeEmptyDirs = false
}
```

# コンフィグレーションからのアプローチ

## コンフィグレーションとは

意図としては、依存関係をグループ化して分類するための単位。
実態はタスクが参照するパス(=タスクの処理対象)を設定しているだけ。

Javaプラグインのコンフィグレーションには以下のものがある。

- compile  
mainソースセットコンパイル時のクラスパス。compileJavaタスクが参照する。
- runtime  
mainソースセット実行時のクラスパス。デフォルト値はcompileコンフィグレーションの値。  
testRuntimeを経由してtestタスクが参照。defaultコンフィグレーション経由でも参照。
- testCompile  
testソースセットコンパイル時のクラスパス。compileTestJavaタスクが参照する。
- testRuntime  
testソースセット実行時のクラスパス。デフォルトではruntimeコンフィグレーション、  
testCompileコンフィグレーション両方の値が設定される。
- archives  
プロジェクトのアーティファクトを指定。デフォルトではjarタスクの出力のみだが、  
設定追加によりassembleタスクの出力が追加される。
- default  
プロジェクトに依存する外部プロジェクトが利用するデフォルトのクラスパス。  
デフォルトでruntime、archivesコンフィグレーションの内容が含まれる。

## コンフィグレーションの利用
例えば、ライブラリの依存関係を設定する場合を例とすると、
JUnitのライブラリの追加をテスト関係のタスクにのみ適用したいとする。
その場合、compileTestJavaタスクにのみライブラリの依存関係を設定するために
testCompileコンフィグレーションに対して設定を行う。

```gradle
dependencies {
    testCompile 'junit:junit:4.11'
}
```

# ソースセットからのアプローチ

## ソースセットの追加
ビルドスクリプトに以下のように記述することで、ソースセットを追加できる。

```gradle
sourceSets {
    exampleSet {
        java.srcDir file('src/example/java')
    }
```

## 自動追加されるコンフィグレーション
ソースセットを追加すると、以下のコンフィグレーションが自動で追加される。

- \<sourceSet\>Compile
- \<sourceSet\>Runtime

上記のコンフィグレーションを設定するには、ビルドスクリプトに以下の通り記述する。

```gradle
sourceSets {
    exampleSet {
        compileClasspath = 'src/ex/java'
        runtimeClasspath = 'build/ex/classes'
    }
}
```

## 自動追加されるタスク
ソースセットを追加すると、以下のタスクが自動で追加される。

- \<sourceSet\>CompileJava
- \<sourceSet\>ProcessResources

## タスクの追加
以下では、結合テストを行うためのソースセット(integrationTest)の追加を通して
Test型のタスクの追加をしてみる。

```gradle
sourceSets {
    integrationTest {
        // 結合テスト用のテストコード（Javaソース)の配置先を設定
        java.srcDir file('src/intTest/java')
        // コンパイル時にmainソースセットの出力クラスとtestソースセットのコンパイル時クラスパスを参照
        compileClasspath = sourceSets.main.output + configration.testCompile
        // 実行時に自身の出力クラスとコンパイル時のクラスパス、testソースセットの実行時と同じクラスパスを参照
        runtimeClasspath = output + compileClasspath + configradion.testCompile
    }
}

task doIntegrationTest(type: Test) {
    // ソースセットintegrationTestの出力をテスト対象とする
    testClassDir = sourceSets.integrationTest.output.classDir

    // テスト実行時のクラスパスにintegrationTestのruntimeClasspathを設定する
    classpath = sourceSets.integrationTest.runtimeClasspath
```

# 参照

この記事は以下の書籍を参考に執筆しています。

参考書籍：[Gradle徹底入門 次世代ビルドツールによる自動化基盤の構築](https://www.shoeisha.co.jp/book/detail/9784798136431)