Help us understand the problem. What is going on with this article?

Gradleに入門する

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などに読み替える必要がある。

プロジェクト初期化

  • DSLはGroovyとKotlinを選択可能。
    • 学習目的ならGroovyのほうが古いドキュメントも参考にしやすいと思われる。
    • 英語に苦手意識がなければ公式にはどちらもサンプルが載っているので問題ないだろう。
    • 実運用ではチームスキルと相談。
  • 例えばJUnit5を使うアプリケーション開発なら以下。Build Init Plugin

    gradle_init
    gradle 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と連携してくれるようだが未確認。マニュアルではツールも紹介されている。
    • 製品用の依存関係とテスト用の依存関係をそれぞれ定義する。

      build.gradle
      dependencies {
          testImplementation group: 'junit', name: 'junit', version: '4.12'
      }
      
    • 参考Gradle の compile, api, implementation とかについて

    フォーマッタ

    • checkタスクで実行される。
    • GoogleJavaFormatを適用するフォーマッタプラグインを利用。

      build.gradle
      plugins {
        id 'com.github.sherter.google-java-format' version '0.8'
      }
      

      本題:静的コード解析タスク

    • checkタスクによって実行する。

    • checkstyleプラグインを導入。

      • 主に使用されない変数やプログラムの複雑さなどをチェックする。
      • 一言で言えばコーディング規約を遵守しているかチェックする。
      • 参考を参照してバージョンを指定
      • 参考を参照して、google-java-styleを導入
      build.gradle
      plugins {
        id 'checkstyle'
      }
      checkstyle {
        toolVersion = '8.29'
        configFile = rootProject.file(new File(tollSettingsDirectory.toString(), "checkstyle/checkstyle.xml").toString())
      }
      
    • SpotBugsプラグインを導入。

      • バグになりやすい構造をチェックする。
      build.gradle
      plugins {
        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.gradle
      plugins {
        id 'jacoco'
      }
      jacoco {
        toolVersion = "0.8.5"
        reportsDir = file("${buildDir}/JacocoReports")
      }
      jacocoTestReport {
        reports {
          html.destination file("${buildDir}/JacocoReports/html")
        }
      }
      jacocoTestReport.shouldRunAfter(test)
      

    サンプル:フル

    build.gradle
    plugins {
      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.gradle
    plugins {
        id 'com.github.johnrengelman.shadow' version '5.2.0'
    }
    

    エントリポイントとなるmain()を実装したクラスをManifestに追加します。

    エントリポイントを持つクラスの例
    public class Main {
        public static void main(String[] args){
            // なにがしかする。
            new HelloWorld().execute();
        }
    }
    
    build.gradle
    jar {
      manifest {
        attributes "Main-Class" : "Main" // フルパッケージ名.クラス名
      }
    }
    

    shadowJarタスクでビルドする。デフォルトでJarタスクの設定を引き継ぐようだ。

    $ java -jar ./build/libs/sample_tdd-1.0-SNAPSHOT-all.jar 
    Hello, World!
    

    参考:

    リファレンス

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした