Gradle概要
- GroovyベースまたはKotolinベースのDSLで書く
-
プラグインを活用することで車輪の再発明の防止というか一般的な流れの踏襲ができる
- 当然だが、自らの環境にあわせてカスタマイズする分は自作する必要がある
- サードパーティプラグイン
- ビルドタスクを管理する
- 依存関係を管理する
- Antのラッパーになる
-
Gradleラッパーにより個別インストール不要
- アップデートは下記のようにコマンド実行すると、次回コマンド実行時に必要なバージョンをダウンロードしてキャッシュされる。
sample_upgrade_wrapper# Version 6.1.1は2020/02/07時点最新 ./gradlew wrapper --gradle-version=6.1.1 --distribution-type=bin
目的
- CIサーバーでビルドに必要なタスクを定義し、実行できるようにする。
- 取り扱う言語はJava
- Gradle自体はプラグインによって多種のビルド環境に対応しているが必要になったら学習する方向で放置。他言語でデファクトになっているツールがある場合はそちらを優先するか、ビルドツールを統一するかは状況によるため。
環境セットアップ
-
インストール
- Javaセットアップ
- Gradleダウンロード&解凍
- 環境変数へのパス追加
-
ズルをして課金してIntellij IDEA Ultimateによるプロジェクト作成を行うとGradleプロジェクト構成でスタートでき、その中にGradleラッパーも含まれているのでホントにもうセットアップ不要。- この場合はGradle自体ではなくGradleラッパーを使うのでマニュアルなどのコマンドを適宜
gradle
から./gradlew
などに読み替える必要がある。
- この場合はGradle自体ではなくGradleラッパーを使うのでマニュアルなどのコマンドを適宜
プロジェクト初期化
- DSLはGroovyとKotlinを選択可能。
- 学習目的ならGroovyのほうが古いドキュメントも参考にしやすいと思われる。
- 英語に苦手意識がなければ公式にはどちらもサンプルが載っているので問題ないだろう。
- 実運用ではチームスキルと相談。
-
例えばJUnit5を使うアプリケーション開発なら以下。Build Init Plugin
gradle_initgradle init --type java-application --test-framework junit-jupiter
-
プラグインを選択しないでinitした場合にはbuild.gradleに追記すればいいらしい?
- 単純に
gradle init
しても対話的インターフェースで選択できるので安心。対話的インターフェース例
対話的インターフェース$ gradlew init Select type of project to generate: 1: basic 2: application 3: library 4: Gradle plugin Enter selection (default: basic) [1..4] 2 Select implementation language: 1: C++ 2: Groovy 3: Java 4: Kotlin 5: Swift Enter selection (default: Java) [1..5] 3 Select build script DSL: 1: Groovy 2: Kotlin Enter selection (default: Groovy) [1..2] 2 Select test framework: 1: JUnit 4 2: TestNG 3: Spock 4: JUnit Jupiter Enter selection (default: JUnit 4) [1..4] 4 Project name (default: test): testapp Source package (default: testapp): > Task :init Get more help with your project: https://docs.gradle.org/6.1.1/userguide/tutorial_java_projects.html BUILD SUCCESSFUL in 4m 44s 2 actionable tasks: 2 executed
プロジェクト初期構造例
プロジェクト初期構造. ├── build.gradle.kts ├── gradle │ └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── settings.gradle.kts └── src ├── main │ ├── java │ │ └── testapp │ │ └── App.java │ └── resources └── test ├── java │ └── testapp │ └── AppTest.java └── resources 11 directories, 8 files
依存関係の管理
- リポジトリはMavenの公開リポジトリがデフォルトで設定されている。
- もともとあるMaven2を利用する場合は
Pom.xml
と連携してくれるようだが未確認。マニュアルではツールも紹介されている。
- もともとあるMaven2を利用する場合は
-
製品用の依存関係とテスト用の依存関係をそれぞれ定義する。
build.gradledependencies { testImplementation group: 'junit', name: 'junit', version: '4.12' }
フォーマッタ
- checkタスクで実行される。
-
GoogleJavaFormatを適用するフォーマッタプラグインを利用。
build.gradleplugins { id 'com.github.sherter.google-java-format' version '0.8' }
本題:静的コード解析タスク
checkタスクによって実行する。
-
checkstyleプラグインを導入。
- 主に使用されない変数やプログラムの複雑さなどをチェックする。
- 一言で言えばコーディング規約を遵守しているかチェックする。
- 参考を参照してバージョンを指定
- 参考を参照して、google-java-styleを導入
build.gradleplugins { id 'checkstyle' } checkstyle { toolVersion = '8.29' configFile = rootProject.file(new File(tollSettingsDirectory.toString(), "checkstyle/checkstyle.xml").toString()) }
-
SpotBugsプラグインを導入。
- バグになりやすい構造をチェックする。
build.gradleplugins { id "com.github.spotbugs" version "3.0.0" } spotbugs { toolVersion = "3.1.12" excludeFilter = rootProject.file(new File(tollSettingsDirectory.toString(), "spotbugs/exclude_filter.xml").toString()) }
本題:単体テスト
- testタスクで実行。
テストカバレッジ
- jacocoTestReportタスクで実行。
-
jacocoでリポートを作成
- jacocoプラグインを導入。
- Gradleユーザーマニュアルを参照して設定。
build.gradleplugins { id 'jacoco' } jacoco { toolVersion = "0.8.5" reportsDir = file("${buildDir}/JacocoReports") } jacocoTestReport { reports { html.destination file("${buildDir}/JacocoReports/html") } } jacocoTestReport.shouldRunAfter(test)
サンプル:フル
build.gradleplugins { id 'java' id 'com.github.sherter.google-java-format' version '0.8' id 'checkstyle' id "com.github.spotbugs" version "3.0.0" id 'jacoco' } File tollSettingsDirectory = new File("${rootProject.projectDir}/config/") group 'org.example' version '1.0-SNAPSHOT' //noinspection GroovyUnusedAssignment sourceCompatibility = 1.11 repositories { mavenCentral() } dependencies { implementation "org.slf4j:slf4j-api:1.7.30" testImplementation "org.slf4j:slf4j-api:1.7.30" runtimeOnly "ch.qos.logback:logback-classic:1.2.3" testRuntimeOnly "ch.qos.logback:logback-classic:1.2.3" testImplementation "org.junit.jupiter:junit-jupiter-api:5.6.0" testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine:5.6.0" } test { useJUnitPlatform() } checkstyle { toolVersion = '8.29' configFile = rootProject.file(new File(tollSettingsDirectory.toString(), "checkstyle/checkstyle.xml").toString()) } spotbugs { toolVersion = "3.1.12" excludeFilter = rootProject.file(new File(tollSettingsDirectory.toString(), "spotbugs/exclude_filter.xml").toString()) } jacoco { toolVersion = "0.8.5" reportsDir = file("${buildDir}/JacocoReports") } jacocoTestReport { reports { html.destination file("${buildDir}/JacocoReports/html") } } jacocoTestReport.shouldRunAfter(test)
Jarファイルビルドについて
2020/02/28追記:
Jarファイルをビルドすると依存先が含まれないのでリリースには使いづらいという話があったため追記する。
せっかくmaven2で管理しているのに手動でライブラリ配置するのは面倒。
というわけで参考情報を参照してGradle Shadow Pluginを導入する。
(WARの場合は公式のWARプラグインで良さそう。EARはわからん)
この場合はライセンス(再頒布)に引っかからないのかな?っていうのを
きちんと調べておきましょう。build.gradleplugins { id 'com.github.johnrengelman.shadow' version '5.2.0' }
エントリポイントとなる
main()
を実装したクラスをManifestに追加します。エントリポイントを持つクラスの例public class Main { public static void main(String[] args){ // なにがしかする。 new HelloWorld().execute(); } }
build.gradlejar { manifest { attributes "Main-Class" : "Main" // フルパッケージ名.クラス名 } }
shadowJarタスクでビルドする。デフォルトでJarタスクの設定を引き継ぐようだ。
$ java -jar ./build/libs/sample_tdd-1.0-SNAPSHOT-all.jar Hello, World!
参考:
リファレンス
- Gradle User Manual
-
日本語化されたユーザーズガイド
- 2012年あたりで更新が止まっているようでバージョンも2.2あたりと古くなっているが、英語が苦手なら概要をつかむのに役立つだろう。大筋を掴んだあと英語の公式ユーザーマニュアルを参照していけばいいと思う。
- SpotBugs
- CheckStyle
- 単純に