Gradle 4.4の初歩的な仕組み、使い方を学ぶ

# 概要

この記事はGradle未経験者がGradleの初歩的な仕組みや使い方を学んだ内容をまとめたものです。

**環境**

* Windows 10 Professional
* Gradle 4.4
    * Groovy 2.4.12
* Java 1.8.0_144

**参考**

* [Gradle User Guide] (https://docs.gradle.org/4.4/userguide/userguide.html)
* [Appendix D. Gradle Command Line] (https://docs.gradle.org/4.4/userguide/gradle_command_line.html)
* [Gradle Build Language Reference] (https://docs.gradle.org/4.4/dsl/)
* [Github - gradle/gradle v4.4.0] (https://github.com/gradle/gradle/tree/v4.4.0)

# インストール

インストールはパッケージマネージャを使わず手動で行いました。
[Install] (https://gradle.org/install/)ページよりアーカイブファイルをダウンロードし適当な場所へ展開します。
展開したディレクトリにあるbinを環境変数pathに追加します。

**バージョン確認**

```bat
> gradle -v

------------------------------------------------------------
Gradle 4.4
------------------------------------------------------------

Build time:   2017-12-06 09:05:06 UTC
Revision:     cf7821a6f79f8e2a598df21780e3ff7ce8db2b82

Groovy:       2.4.12
Ant:          Apache Ant(TM) version 1.9.9 compiled on February 2 2017
JVM:          1.8.0_144 (Oracle Corporation 25.144-b01)
OS:           Windows 10 10.0 amd64
```

**Usage**

```text
gradle [option...] [task...]
```

# build.gradleの見方

Spring Bootを利用したアプリケーションのひな型を生成してくれる[SPRING INITIALIZR] (https://start.spring.io/)から、ビルドにGradleを使うWebアプリケーションのひな型を生成し、そこに含まれるbuild.gradleを読んでみました。

また、参考に同じ条件でMavenを使ったひな型を生成し、そのpom.xmlを下記に掲載しました。

**Maven**

```xml:pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>demo</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.9.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-thymeleaf</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>
```

**Gradle**

```groovy:build.gradle
// 1
buildscript {
	ext {
		springBootVersion = '1.5.9.RELEASE'
	}
	repositories {
		mavenCentral()
	}
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}

// 2
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'org.springframework.boot'

// 3
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8

// 4
repositories {
	mavenCentral()
}

// 5
dependencies {
	compile('org.springframework.boot:spring-boot-starter-thymeleaf')
	compile('org.springframework.boot:spring-boot-starter-web')
	runtime('org.springframework.boot:spring-boot-devtools')
	compileOnly('org.projectlombok:lombok')
	testCompile('org.springframework.boot:spring-boot-starter-test')
}
```

## 1. スクリプトの実行に必要な設定

pom.xmlはmavenのビルドに関する設定ファイルですが、gradleのbuild.gradleはGroovyというプログラミング言語で記述されたビルドのスクリプトファイルです。

このbuildscriptという箇所で、スクリプトファイルの実行時に必要なspring-boot-gradle-pluginを依存関係に追加していて、これによりorg.springframework.bootプラグインが利用可能になります。

また、このような`{ ... }`はスクリプトブロックと呼ばれ、ほかにrepositoriesやdependenciesなどがあります。

```groovy
buildscript {
	// A
	ext {
		springBootVersion = '1.5.9.RELEASE'
	}
	// B
	repositories {
		mavenCentral()
	}
	// C
	dependencies {
		classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
	}
}
```

**A**

extはextra propertiesというスクリプトブロックです。ここにプロパティを定義します。

**B**

spring-boot-gradle-pluginを取得するリポジトリを設定しています。この例ではmavenのセントラルリポジトリが使用されています。

**C**

このスクリプトファイルの実行に必要な依存関係を追加しています。
この箇所の記述はスクリプト実行時のclasspathにspring-boot-gradle-pluginという依存関係を追加するという意味になります。

> [43.6. External dependencies for the build script] (https://docs.gradle.org/4.4/userguide/organizing_build_logic.html#sec:build_script_external_dependencies)
> 
> If your build script needs to use external libraries, you can add them to the script’s classpath in the build script itself. 

## 2. プラグインの適用

プラグインを適用するとそのプラグインが提供するタスクが実行できるようになります。

```groovy
// A
apply plugin: 'java'
// B
apply plugin: 'eclipse'
// C
apply plugin: 'org.springframework.boot'
```

**A**

[javaプラグイン]
 (https://docs.gradle.org/4.4/userguide/java_plugin.html)を適用するとjavaソースコードのコンパイルやユニットテストの実行などを行うタスクが実行できるようになります。

**B**

eclipseプラグインを適用しています。このプラグインのeclipseタスクを実行するとeclipseのプロジェクトファイルを生成します。
このプラグインはGradleの標準プラグインです。

```bat
> gradle eclipse
```

プロジェクトファイルを消去したい場合はcleanEclipseタスクを実行します。

```bat
> gradle cleanEclipse
```

**C**

spring bootプラグインを適用しています。このプラグインのbootRunタスクを実行するとspring bootで開発したアプリケーションを実行することができます。

```bat
> gradle bootRun
```

また、assembleタスクに依存するbootRepackageというタスクも追加されます。

```bat
> gradle help --task bootRepackage

> Task :help
Detailed task information for bootRepackage

Path
     :bootRepackage

Type
     RepackageTask (org.springframework.boot.gradle.repackage.RepackageTask)

Description
     Repackage existing JAR and WAR archives so that they can be executed from the command line using 'java -jar'

Group
     build
```

### 利用できるタスクの確認

プロジェクトでどのようなタスクが実行できるかは、tasksタスクで確認することができます。

```bat
> gradle tasks
```

### サポートするプログラミング言語

また、GradleはJavaの他にGroovy、scalaなどもサポートしています。（これだけではありません）

[Groovy] (https://docs.gradle.org/4.4/userguide/groovy_plugin.html)

```groovy
apply plugin: 'groovy'
```

[Scala] (https://docs.gradle.org/4.4/userguide/scala_plugin.html)

```groovy
apply plugin: 'scala'
```

## 3. スクリプトの実行時に参照されるプロパティの設定

group、versionはプロジェクトに関するプロパティ、sourceCompatibilityはjavaプラグインが利用するプロパティです。

```groovy
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = 1.8
```

プロジェクトが参照するプロパティの種類はDSLリファレンスの[Project] (https://docs.gradle.org/4.4/dsl/org.gradle.api.Project.html)で、javaプラグインが利用するプロパティの種類は、ユーザーガイドの[Chapter 48. The Java Plugin] (https://docs.gradle.org/4.4/userguide/java_plugin.html)で確認できます。

プロジェクトにどのようなプロパティがあるかは、properteisタスクで確認することができます。

```bat
> gradle properties
```

### 独自のプロパティを定義する

独自のプロパティはextというスクリプトブロックに定義します。

```groovy:例
ext {
  limitDate = '2017-12-01'
}
```

## 4. リポジトリの設定

repositoriesで、ビルドの依存関係の解決や成果物のアップロード先のリポジトリを設定します。
この例では依存関係に設定したライブラリの取得先をmavenのセントラルリポジトリにしています。

```groovy
repositories {
	mavenCentral()
}
```

ローカルのmavenリポジトリを利用する場合

```groovy
mavenLocal()
```

JCenterリポジトリを利用する場合

```groovy
jcenter()
```

## 5. 外部依存関係の追加

プロジェクトのビルドが依存するライブラリの設定を追加します。
compileやruntimeなどを依存関係のコンフィグレーションといい、たとえばcompileはソースコードのコンパイル時に必要となるライブラリを設定します。

```groovy
dependencies {
	compile('org.springframework.boot:spring-boot-starter-thymeleaf')
	compile('org.springframework.boot:spring-boot-starter-web')
	runtime('org.springframework.boot:spring-boot-devtools')
	compileOnly('org.projectlombok:lombok')
	testCompile('org.springframework.boot:spring-boot-starter-test')
}
```

上記は短縮した記述方法(`group:name:version`)で、依存関係は次のようにも記述できます。
利用するリポジトリによってはversion属性を省略することができます。

```groovy
dependencies {
	compile group: 'org.springframework.boot', name: 'spring-boot-starter-thymeleaf'
	compile group: 'org.springframework.boot', name: 'spring-boot-starter-web'
	runtime group: 'org.springframework.boot', name: 'spring-boot-devtools'
	compileOnly group: 'org.projectlombok', name: 'lombok'
	testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test'
}
```

任意のバージョンを指定する場合は下記のようにversion属性で指定します。

```groovy
compileOnly group: 'org.projectlombok', name: 'lombok', version: '1.16.18'
```

プロジェクトの依存関係の確認はdependenciesタスクで行えます。

```bat
> gradle dependencies
```

また、オプションの`--configuration`を指定することで特定の依存関係だけを出力させることができます。

```bat
> gradle dependencies --configuration compileOnly

> Task :dependencies

------------------------------------------------------------
Root project
------------------------------------------------------------

compileOnly - Compile only dependencies for source set 'main'.
\--- org.projectlombok:lombok: -> 1.16.18

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed
```

### optionalの依存関係

Spring Bootのリファレンスの[B.3 Generating your own meta-data using the annotation processor] (https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/#configuration-metadata-annotation-processor) に記載があります。

mavenでの依存関係の設定では、下記のようにoptionalの指定ができます。

```xml
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-configuration-processor</artifactId>
    <optional>true</optional>
</dependency>
```

これと同じことをGradleで行うには[propdeps-plugin] (https://github.com/spring-gradle-plugins/propdeps-plugin)の利用と下記の設定が必要です。

```groovy
buildscript {
	repositories {
		maven { url 'http://repo.spring.io/plugins-release' }
	}
	dependencies {
		classpath('io.spring.gradle:propdeps-plugin:0.0.9.RELEASE')
	}
}
```

```groovy
apply plugin: 'propdeps'

dependencies {
    optional("org.springframework.boot:spring-boot-configuration-processor")
}

compileJava.dependsOn(processResources)
```


# タスクの実行

Javaプラグインで追加されるタスクで、よく使うタスクには下記のものがあります。

* clean : プロジェクトのビルドディレクトリを削除する
* build : プロジェクトをビルドする
* test : ユニットテストを実行する

 プロジェクトをビルドするにはbuildタスクを実行します。

```bat
> gradle clean build
```

## タスクの依存関係を確認する

タスクの実行が他のタスクに依存している場合があります。以下はbuildタスクの依存関係をツリー表示したものです。
（ツリー表示には[com.dorongold.task-tree] (https://plugins.gradle.org/plugin/com.dorongold.task-tree)というプラグインを利用しました。）

このツリーからbuildタスクはassembleタスクとcheckタスクに依存していることがわかります。

```bat
> gradle build taskTree --no-repeat

> Task :taskTree

------------------------------------------------------------
Root project
------------------------------------------------------------

:build
+--- :assemble
|    +--- :bootRepackage
|    |    +--- :findMainClass
|    |    |    \--- :classes
|    |    |         +--- :compileJava
|    |    |         \--- :processResources
|    |    \--- :jar
|    |         \--- :classes *
|    \--- :jar *
\--- :check
     \--- :test
          +--- :classes *
          \--- :testClasses
               +--- :compileTestJava
               |    \--- :classes *
               \--- :processTestResources


(*) - subtree omitted (printed previously)
```


# [タスクの定義] (https://docs.gradle.org/4.4/userguide/more_about_tasks.html)

build.gradleに独自のタスクを定義して実行することができます。
下記はタスクの定義の基本的なサンプルです。

```groovy
task myTask {
    description = 'My Task description'
    group = 'My Tasks'

    doLast {
        println "running ${name}"
    }
}
```


# [ロギング] (https://docs.gradle.org/4.4/userguide/logging.html)

## ログレベル

1. ERROR
2. QUIET
3. WARNING
4. LIFECYCLE
5. INFO
6. DEBUG

## ログの出力

ログの出力にはloggerを使用します。

```groovy
task logOutput {

	doLast {
		logger.error('error log message')
		logger.quiet('quiet log message')
		logger.warn('warning log message')
		logger.lifecycle('lifecycle log message')
		logger.info('info log message')
		logger.debug('debug log message')
		logger.trace('trace log message')
		println('log message via println')
	}

}
```

コマンドラインのオプションで出力するログレベルを選択することができます。指定しない場合のデフォルトはLIFECYCLEです。
なお、printlnのデフォルトのログレベルはQUIETに設定されています。

```bat
> gradle logOutput

> Task :logOutput
error log message
quiet log message
warning log message
lifecycle log message
log message via println

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed
```

指定できるオプションは

* -q (--quiet) : QUIET以上
* -w (--warn) : WARNING以上
* -i (--info) : INFO以上
* -d (--debug) : DEBUG以上

printlnのログレベルを変更するには下記の設定を追加します。

```
logging.captureStandardOutput LogLevel.INFO
```


# 補足

## その他のタスク

**[buildEnvironment] (https://docs.gradle.org/current/dsl/org.gradle.api.tasks.diagnostics.BuildEnvironmentReportTask.html)**

プロジェクトのビルド環境に関する情報を表示します。

```bat
> gradle buildEnvironment
```

**[components] (https://docs.gradle.org/current/dsl/org.gradle.api.reporting.components.ComponentReport.html)**

コンポーネントの詳細な情報を表示します。

```bat
> gradle components
```

**[dependencies] (https://docs.gradle.org/current/dsl/org.gradle.api.tasks.diagnostics.DependencyReportTask.html)**

プロジェクトの依存関係をツリー表示します。

```bat
> gradle dependencies
```

**[dependencyInsight] (https://docs.gradle.org/current/dsl/org.gradle.api.tasks.diagnostics.DependencyInsightReportTask.html)**

```bat
> gradle dependencyInsight --dependency org.springframework:spring-webmvc

> Task :dependencyInsight
org.springframework:spring-webmvc:4.3.13.RELEASE (selected by rule)
\--- org.springframework.boot:spring-boot-starter-web:1.5.9.RELEASE
     +--- compileClasspath
     \--- org.springframework.boot:spring-boot-starter-thymeleaf:1.5.9.RELEASE
          \--- compileClasspath

(*) - dependencies omitted (listed previously)


BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed
```

**projects**

```bat
> gradle projects
```

**properties**

```bat
> gradle properties
```

**tasks**

```bat
> gradle tasks
```

```bat
> gradle tasks --all
```

**help**

```bat
> gradle help --task <task name>
```

## Build Init Plugin

`currently incubating`

[Chapter 17. Build Init Plugin] (https://docs.gradle.org/4.4/userguide/build_init_plugin.html)

**Usage**

プラグインの明示的な適用は不要です。

> The Build Init plugin is an automatically applied plugin, which means you do not need to apply it explicitly. 

**Tasks**

* init
* wrapper

### initタスク

プロジェクトのひな型を作成します。テスティングフレームワークにはJUnitが選択されます。

```bat
> gradle init --type java-library
```

JUnitの代わりにTestNGかspockを選択することができます。

```bat
> gradle init --type java-library --test-framework testng
```

```bat
> gradle init --type java-library --test-framework spock
```

## Wrapper Plugin

`currently incubating`

[Chapter 23. Wrapper Plugin] (https://docs.gradle.org/4.4/userguide/wrapper_plugin.html)

**Tasks**

* wrapper

### wrapper

Gradleの実行環境を生成します。

```bat
> gradle wrapper
```

```bat
> gradle wrapper --gradle-version=4.4
```

```bat
> gradle wrapper --distribution-type=ALL --gradle-version=4.4
```

## Project Report Plugin

[Chapter 29. The Project Report Plugin] (https://docs.gradle.org/4.4/userguide/project_reports_plugin.html)

**Usage**

```groovy
apply plugin: 'project-report'
```

**Tasks**

* dependencyReport
* htmlDependencyReport
* propertyReport
* taskReport
* projectReport

**dependencyReport**

```bat
> gradle dependencyReport
```

```bat
> gradle dependencyReport --configuration default
```

**htmlDependencyReport**

```bat
> gradle htmlDependencyReport
```

**propertyReport**

```bat
> gradle propertyReport
```

**taskReport**

```bat
> gradle taskReport
```

```bat
> gradle taskReport --all
```

**projectReport**

```bat
> gradle projectReport
```

## Build Dashboard Plugin

`currently incubating`

[Chapter 30. The Build Dashboard Plugin] (https://docs.gradle.org/4.4/userguide/buildDashboard_plugin.html)

**Usage**

```groovy
apply plugin: 'build-dashboard'
```

**Tasks**

* buildDashboard

**buildDashboard**

```bat
> gradle buildDashboard
```

## 3rd party Plugin

サードパーティープラグインは[Gradle - Plugins] (https://plugins.gradle.org/)で探すことができます。

### [Spring Boot Gradle plugin] (https://docs.spring.io/spring-boot/docs/current/reference/html/build-tool-plugins-gradle-plugin.html)

**Usage**

```groovy
apply plugin: 'org.springframework.boot'
```

**Tasks**

* bootRepackage
* bootRun

### [Flyway Gradle plugin] (https://flywaydb.org/documentation/gradle/)

**Usage**

```groovy
plugins {
    id "org.flywaydb.flyway" version "5.0.3"
}
```

**Tasks**

* flywayInfo
* flywayBaseline
* flywayMigrate
* flywayRepair
* flywayValidate
* flywayClean
*