Gradle 入門

Java

対象者

  • Gradle って何?
  • Gradle のサンプルコードが欲しい
  • Gradle の公式ドキュメントを読む前に概要を知りたい

わかりやすさ重視で記載しているので、厳密な定義は公式ドキュメントを読んでください。

Gradle とは

Gradle とは Java のビルドツールです。主に以下の2点を実現できます。

  • 任意のタスク(ビルドなど)を実行する
  • モジュールの依存関係を解決して、インストールする

任意のタスクを実行する

Gradle では自分で作成したタスク(例: Hello Worldのコード)、もしくは事前に用意されたタスクを実行することができます。事前に用意されたタスクは以下のとおりです。

何が嬉しいか

大量のオプションがついたビルドコマンドやテストコードを毎回、手動で入力する作業から開放されます。

モジュールの依存関係を解決して、インストールする

モジュールの依存関係とは、「モジュール A を実行するために他のモジュールが必要な状態」のことを表します。

Gradle では、モジュールをインストールする際に、依存関係にある他のモジュールも自動でインストールすることで依存関係を解決してくれます。(例:依存関係のあるモジュールを取得

何が嬉しいか

  • 依存関係にあるモジュールを1つ1つ調べて、手動でインストールする作業から開放される
  • ビルドスクリプトを実行すると、他のコンピュータでも同じモジュールを揃えられる

Gradle のインストール方法

SDKMAN!(パッケージ管理ソフト)を使用して Gradle 6.6.1 をインストールします。

  1. SDKMAN! をインストール(既にインストールされている場合はスキップ)
    $ curl -s "https://get.sdkman.io" | bash
    $ source "$HOME/.sdkman/bin/sdkman-init.sh"

    以下のコマンドでバージョンが表示されるとインストール成功

    $ sdk version
    ==== BROADCAST =================================================================
    * 2020-09-21: micronaut 2.0.3 now available for download.
    * 2020-09-21: jbang 0.47.1 now available for download.
    * 2020-09-20: jbang 0.46.1 @jbangdev https://git.io/JUEb5
    ================================================================================
    
    SDKMAN 5.9.0+555
  2. JDK バージョン 8 以上をインストール(既にインストールされている場合はスキップ)
    $ sdk install java

    以下のコマンドで JDK バージョン 8 以上が表示されるとインストール成功

    $ java -version
    openjdk version "11.0.8" 2020-07-14
    OpenJDK Runtime Environment AdoptOpenJDK (build 11.0.8+10)
    OpenJDK 64-Bit Server VM AdoptOpenJDK (build 11.0.8+10, mixed mode)
  3. Gradle をインストール
    $ sdk install gradle

    以下のコマンドでバージョンが表示されるとインストール成功

    $ gradle -version
    ------------------------------------------------------------ Gradle 6.6.1 ------------------------------------------------------------ Build time: 2020-08-25 16:29:12 UTC Revision: f2d1fb54a951d8b11d25748e4711bec8d128d7e3 Kotlin: 1.3.72 Groovy: 2.5.12 Ant: Apache Ant(TM) version 1.10.8 compiled on May 10 2020 JVM: 11.0.8 (AdoptOpenJDK 11.0.8+10) OS: Linux 4.14.193-149.317.amzn2.x86_64 amd64

補足

SDKMAN! で利用可能なソフトウェアは以下のドキュメントに記載されたソフトウェアだけです。Maven セントラルリポジトリなどから、依存関係を解決しながらモジュールをインストールする場合は、Gradle を利用する必要があります。

Available SDKs - SDKMAN! the Software Development Kit Manager

Gradle の使い方

Gradle ではビルドスクリプト(build.gradle)で暗黙的に宣言されたProject オブジェクトを使用して、モジュールの依存関係の解決やタスクの実行を行います。

ビルドスクリプトで使用できる言語は Groovy DSL もしくは Kotlin DSL であり、今回は Groovy DSL を使用します。

Groovy を用いたビルドスクリプトでは、主に以下の6つの書式を持ちます。

Properties

Properties はざっくり言うと、オブジェクトの持つ変数のことです。

A property represents some state of an object.

https://docs.gradle.org/current/userguide/groovy_build_script_primer.html#groovy:properties

Gradle がデフォルトで利用可能な Project オブジェクトの Properties 一覧は以下のとおりです。

Project - Gradle DSL Version 6.6.1

Properties の書式

Properties の書式は以下のとおりです。

<obj>.<name>  // property の値を取得
<obj>.<name> = <value>  // property に値をセット
"$<name>"  // 文字列に property の値を埋め込みます
"${<obj>.<name>}"  // "$"と同じ。別の書き方

例:Properties を操作する

ビルドスクリプト(build.gradle)で Project オブジェクトの持つ “buildDir” Property を操作してみます。

なお、”buildDir” はプロジェクトのディレクトリを格納する Property です。

$ vim build.gradle
println project.buildDir // property の値を取得

project.buildDir = "test" // property に値をセット
println project.buildDir

println "buildDirの値は $buildDir です。" //文字列に property の値を埋め込みます
println "buildDirの値は ${project.buildDir} です。" //文字列に property の値を埋め込みます

gradle –configure-on-demand コマンドで結果を確認してみましょう。

$ gradle --configure-on-demand

Configuration on demand is an incubating feature.

Configure project :
/home/ec2-user/build
/home/ec2-user/test
buildDirの値は /home/ec2-user/test です。
buildDirの値は /home/ec2-user/test です。

結果は Configure project : に表示されます。

補足

Project オブジェクトは省略可能です。そのため以下のような記載方法が可能です。

println buildDir

Methods

Methods はざっくり言うと、オブジェクトが所有する関数のことです。

A method represents some behavior of an object

https://docs.gradle.org/current/userguide/groovy_build_script_primer.html#groovy:methods

Gradle がデフォルトで利用可能な Project オブジェクトの Methods 一覧は以下のとおりPropertiesです。

Project - Gradle DSL Version 6.6.1

Methods の書式

Methods の書式は以下のとおりです。

<obj>.<name>() // 引数無しで Method を呼び出す
<obj>.<name>(<arg>,<arg>)// 引数ありで Method を呼び出す
<obj>.<name> <arg>,<arg> // 引数ありで Method を呼び出す(丸括弧を省略)

例:Methods の呼び出し

Project オブジェクトの持つ “mkdir” Method を操作してみましょう。

なお、”mkdir” はディレクトリを作成する Method です。

$ vim build.gradle
mkdir("src/main/java") //ディレクトリ src/main/java を作成します。

gradle –configure-on-demand コマンドでメソッドを実行してみましょう。

// Method 実行前のディレクトリ
$ ls
build.gradle

// Method 実行
$ gradle --configure-on-demand

// Method 実行後のディレクトリ
$ ls
build.gradle src

Script blocks (blocks)

メソッドとほぼ同じ機能です。書式が異なります。メソッドとの違いは公式ドキュメントに記載があります。

Blocks are also methods, just with specific types for the last argument.

There are two important aspects of blocks that you should understand:

1. They are implemented as methods with specific signatures.
2. They can change the target (“delegate”) of unqualified methods and properties.

https://docs.gradle.org/current/userguide/groovy_build_script_primer.html#groovy:blocks

Gradle がデフォルトで利用可能な Project オブジェクトの Script blocks 一覧は以下のとおりです。

Project - Gradle DSL Version 6.6.1

なお、上記の公式ドキュメントには Script blocks と Blocks の用語が混在しています。同じ意味で使っていると思うのですが。。。

Script blocks の書式

Script blocks を利用するための書式は以下のとおりです。

// 引数無し
<obj>.<name> { 
     ...
}
// 引数あり

<obj>.<name>(<arg>,<arg>){
     ...
}

具体的なビルドスクリプトの書き方は後述する Tasks, Plugins, Dependencies で記載します。現時点では “{ }”で囲む書式があるんだな。ぐらいの認識でOKです。

Tasks (任意のタスク)

Tasks はざっくり言うと、ビルドの作業内容のことです。

A Task represents a single atomic piece of work for a build

https://docs.gradle.org/current/dsl/org.gradle.api.Task.html

Tasks オブジェクト が持つ PropertiesMethods は以下のとおりです。

Task - Gradle DSL Version 6.6.1

Tasks の書式

Tasks の書式は以下のとおりです。

task <Task名> // Task オブジェクトを作成。処理は無い。
task <Task名> { configure closure } // Task を作成し、block に処理を記載
task <Task名>(type: SomeType) // 引数を渡して Task を作成
task <Task名>(type: SomeType) { configure closure } // 引数を渡して Task を作成し、block に処理を記載

例:Hello World! の Task を作成する

Gradle では任意のタスクを作成可能です。ここでは例として Hello World! Task を作成します。

$ vim build.gradle
task task1 {
        println "Hello world!"
}

gradle <Task名> コマンドで Task を実行してみましょう。

$ gradle task1

Configure project :
Hello world!

BUILD SUCCESSFUL in 1s

Configure project : に Hello world! が表示されることが確認できます。

例:Task 一覧に追加、および確認する

Task 一覧を表示するためには gradle task コマンドを利用します。

$ gradle tasks

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.

Help tasks
----------
(中略)
properties - Displays the properties of root project 'ec2-user'.
tasks - Displays the tasks runnable from root project 'ec2-user'.

先程作成した “task1” が Task 一覧に無いので、登録しましょう

Task 一覧に表示する方法は Task オブジェクト が持つ 「”group“, “description“」 Properties を使用します。

$ vim build.gradle
task task1 {
        group = "Custom" //group property を設定します。task のオブジェクト名は省略します。
        description = "Hello world を表示します。" //task の説明を記載します。
        println "Hello world!"
}

task task2(group: "Custom2", description: "Hello world を表示します。") { //引数で指定することも可能です。 
        println "Hello world!"
}

もう一度 Task 一覧を確認してみましょう。

$ gradle tasks

Build Setup tasks
-----------------
init - Initializes a new Gradle build.
wrapper - Generates Gradle wrapper files.
Custom tasks ------------ task1 - Hello world を表示します。 Custom2 tasks ------------- task2 - Hello world を表示します。
Help tasks
----------
(中略)
properties - Displays the properties of root project 'ec2-user'.
tasks - Displays the tasks runnable from root project 'ec2-user'.

無事、作成した Task が Task 一覧に表示されることを確認できました。

例:タスク指定された時だけタスクを実行

gradle tasks コマンドを実行した際に task1, task2 が実行されています。

> Configure project :
Hello world!
Hello world!

これを Task オブジェクトの “doLast” Method を利用することで、Task 名を指定された時だけ、Task を実行するようにします。

$ vim build.gradle
task task1 {
        group = "Custom" //group property を設定します。task のオブジェクト名は省略します。
        description = "Hello world を表示します。" //task の説明を記載します。
        doLast{
                println "Hello world!"
        }
}

task task2(group: "Custom2", description: "Hello world を表示します。") { //引数で指定することも可能です。 
        doLast{
                println "Hello world!"
        }
}

gradle tasks コマンドを実行しても、println “Hello world!” が実行されていないことが確認できます。

$ gradle tasks

Task 名を指定すると、指定した Task だけが動作します。

$gradle task1

> Task :task1
Hello world!

BUILD SUCCESSFUL in 690ms
1 actionable task: 1 executed

Plugins(既製のタスクを追加)

Plugins はざっくり言うと、誰かが作った project を追加する機能です。

Plugins can be used to modularise and reuse project configuration.

https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#N14FD0

Core Plugins 一覧は以下のとおりです。

Gradle Plugin Reference

Non-core Plugins 一覧は以下のページから検索可能です。

Gradle - Plugins

Plugins の書式

Plugins の書式は以下の2種類があります。

// PluginAware.apply(java.util.Map) Method を利用する場合

apply plugin: '<プラグイン名>'
//PluginDependenciesSpec の plugins script block を利用する場合

plugins{
     id "<プラグイン名1>"
     id "<プラグイン名2>"
}

例:build Task 追加し、ビルドを実行する

JavaPlugin の “build” Task を追加し、実行してみます。なお、ソースコードは src/main/java 配下に置きます。

事前準備

  1. src/main/java ディレクトリを作成します。
    $ mkdir -p src/main/java
  2. コンパイルするソースコードを作成します。
    $ vim src/main/java/HelloWorld.java
    
    public class HelloWorld {
            public static void main(String[] args){
                    System.out.println("Hello world.");
            }
    }

Plugins から build Task 追加、実行する

  1. “Java” plugin を追加します。
    $ vim build.gradle
    apply plugin: 'java'
  2. “Java” plugin の “build” Task が追加されていることを確認します。
    $ gradle tasks > Task :tasks ------------------------------------------------------------ Tasks runnable from root project ------------------------------------------------------------ Build tasks ----------- assemble - Assembles the outputs of this project. build - Assembles and tests this project.
  3. “build” Task を実行します。
    $ gradle build BUILD SUCCESSFUL in 1s 1 actionable task: 1 executed
  4. クラスファイルが生成されたことを確認します。
    $ ls build/classes/java/main/HelloWorld.class build/classes/java/main/HelloWorld.class

例:run Task を追加し、プログラムを実行する

事前の準備としてこちらのソースコードを用意してください

  1. Run Task を持つ application Plugins を追加する
    $vim build.gradle
    plugins {
        id 'application'
    }
    
    mainClassName = 'HelloWorld'
  2. RUN タスクを実行します
    $gradle run
    
    > Task :run
    Hello world.
    
    BUILD SUCCESSFUL in 839ms
    2 actionable tasks: 2 executed

Dependencies(依存関係の解決)

Dependencies はざっくり言うと、モジュールの依存関係を解決する機能です。

Those dependencies are grouped in configurations, and can be retrieved and uploaded from repositories.

https://docs.gradle.org/current/dsl/org.gradle.api.Project.html#N14F9E

Dependencies オブジェクトの持つ Properties, Methods は以下のとおりです。

DependencyHandler - Gradle DSL Version 6.6.1

Dependencies の書式

Dependencies の書式は以下のとおりです。

dependencies {
    <configurationName> '<グループID>:<アーティファクトID>:<バージョン>'
}

<configurationName> の例

  • implementation extends compile
    実装の時のみ依存関係を解決。実装とコンパイルの違いはココ
  • compileOnly
    コンパイルの時のみ依存関係を解決。実行時は依存関係を解決しない。
  • runtimeOnly
    実行時の時のみ依存関係を解決。コンパイルは依存関係を解決しない。
https://docs.gradle.org/current/userguide/java_plugin.html#sec:java_plugin_and_dependency_management

例: 依存関係を解決しながらモジュールを取得する

$ vim build.gradle
apply plugin: 'java' //compileOnly を利用するため

//リポジトリの設定
repositories {
    mavenCentral() //https://repo.maven.apache.org/maven2/ から取得
}

//リポジトリから取得するモジュールの設定
dependencies {
    compileOnly "software.amazon.awssdk:kinesis:2.15.2"
}

// 依存するモジュールを jar ディレクトリにコピーする
task getModule() {
    group = "Hoge"
    description = "依存関係の解決" 
    
    doLast {
        configurations.compileOnly.each {
            def fromJarFile = it.absolutePath
            copy {
                from fromJarFile
                into 'jar'
            }   
        }   
    }   
}

Maven セントラルリポジトリにあるモジュールは下記のサイトで検索可能です。

今回は kinesis モジュールのバージョン 2.15.2 を取得します。

Maven Central Repository Search
Official search of Maven Central Repository
Maven Repository: software.amazon.awssdk » kinesis » 2.15.2
//先程作成した "getModule" Task を確認
$gradle tasks

Hoge tasks
----------
getModule - 依存関係の解決


//"getModule" Task を実行
$gradle getModule

//jar ディレクトリにモジュールを保存したことを確認
$ls jar

annotations-2.15.2.jar
apache-client-2.15.2.jar
auth-2.15.2.jar
aws-cbor-protocol-2.15.2.jar
(中略)
kinesis-2.15.2.jar

kinesis-2.15.2.jar 以外にも、依存関係にあるモジュールを取得できていることがわかります。

例: 独自の Maven リポジトリの指定

$ vim build.gradle
repositories {
    maven {
        url 'http://redshift-maven-repository.s3-website-us-east-1.amazonaws.com/release'
    }   
}

MavenArtifactRepository maven(Closure closure) で url Properties を指定します。

RepositoryHandler - Gradle DSL Version 6.6.1
MavenArtifactRepository - Gradle DSL Version 6.6.1

例: BOM の利用

BOM ファイルは複数のモジュールのバージョン一覧を記載したファイルです。

複数のモジュールをインストールする場合、依存関係がバッティングする場合があります。

  • モジュール A はモジュール C のバージョン 1.0 に依存する
  • モジュール B はモジュール C のバージョン 1.1 に依存する

この場合、モジュール C はどのバージョンを入れればいいの?という話になります。

これを解決するのが BOM ファイルと呼ばれるものです。以下のサイトにわかりやすい説明があります。

BOMプロジェクトとは - Qiita
BOMプロジェクトについて調べたことまとめ。 参考: -

BOM を利用する場合のビルドスクリプトの書き方の例を掲載します。

$ vim build.gradle
//BOM を使わない場合

apply plugin: 'java'
  
repositories {
    mavenCentral()
}

dependencies {
        compileOnly 'software.amazon.awssdk:kinesis:2.1.4'
        compileOnly 'software.amazon.awssdk:s3:2.1.4'
}
//BOM を使う場合

apply plugin: 'java'
  
repositories {
    mavenCentral()
}

dependencies {
  compileOnly platform('software.amazon.awssdk:bom:2.1.4')
  compileOnly 'software.amazon.awssdk:kinesis'
  compileOnly 'software.amazon.awssdk:s3'
}

BOM を利用した場合、BOM にモジュールのバージョンが記載されているため、モジュールにバージョンを記載する必要が無いです。BOM ファイル software.amazon.awssdk:bom:2.1.4 の内容は下記のページを参照してください。

Maven Central Repository Search
Official search of Maven Central Repository

参考文献

# 公式ドキュメント ユーザーガイド

Gradle User Manual

#公式ドキュメント DSL Reference

Gradle DSL Version 6.6.1

#公式ドキュメントの日本語訳

Gradle DSL Version 2.2-20140924021627+0000
0

コメント

タイトルとURLをコピーしました