プロジェクト

全般

プロフィール

Gradleの使い方

2024-03-24時点のGradle最新バージョンは 8.7 です。

はじめに

Javaは仮想マシン(仮想CPU)上で実行されるバイトコードを生成するコンパイラ言語で、Linux OS、Mac OS、Windows OSなど色々な計算機上で実行されるプログラムを生成します。そのため、開発環境も色々な計算機上で動くものが提供されています。そこで、Javaで開発する際に特定のOSや特定の開発環境(IDE)に依存しない汎用的なビルドツールが整備されてきました。

GradleもOSやIDEに依存しない汎用的なビルドツールとして登場しました。それまでのAntやMavenとの違いは、ビルド定義の記述をXMLではなくスクリプトで記述できる点、スクリプトなのでゴリゴリと実行コードを書くことができる点にあります。

Gradleでは、ビルド定義をGroovyまたはKotlinのスクリプトとして記述します。初期のGradleはGroovyのスクリプトでビルド定義を記述するツールとして登場しました。その後、Kotlinのスクリプトでビルド定義を記述することも可能となりました。

また、Gradleではgradle wrapperという方法によって、Gradleでビルドするプロジェクト(ソースファイル、ビルド定義などをまとめたディレクトリ)にGradleツール自身を含めることで、最初にプロジェクトを用意する際にGradleツールを使用すれば、以降はプロジェクトを展開するだけでその中に含まれるGradleツールを使ってビルドが可能になります。つまり、プロジェクトを作成する最初だけGradleツールを用意する必要があり、プロジェクトを利用する環境ではJavaが動けばGradleツールを別途用意する必要がないということです。

この記事では、ビルドスクリプトをKotlinで記述するGradleの使い方を示していきます。(現在書き換え作業中)

Gradleを使う最初の一歩

Gradleツールのセットアップ

Gradleのプロジェクトを新規に作成するときにGradleツールが必要になります。gradle wrapperを組み込んだGradleプロジェクトを一旦作成した後は、そのGradleプロジェクトを利用する場合は、Gradleプロジェクトの中にGradleツールが含まれるため、ビルド環境においてGradleツールを別途インストールすることは不要です。

Gradle公式サイトのリリースページ(次のURL)にアクセスし、ダウンロードするバージョンの[binary-only]または[complete]のリンクをクリックします。
https://gradle.org/releases/

  • binary-only
    gradle実行スクリプトファイル、実行に必要なライブラリファイル(JARファイル群)が含まれています。
  • complete
    binary-onlyに、ドキュメントおよびソースファイルが追加されています。

Windows OS環境へのGradleのインストール

インストール先(例、C:\Program Files\Java の下)にダウンロードしたアーカイブファイルを解凍し展開します。
環境変数PATHに、C:\Program Files\Java\gradle-8.4\bin (例)を追加します。
Gradleはシステム(環境変数PATH)上にあるJavaを使用します。また、環境変数JAVA_HOMEを指定してシステム上とは別のJavaを使用することが可能です。

MacOS環境へのGradleのインストール

Homebrewを使うと簡単にインストールできます。HomebrewのGradle項参照。

最初のJavaアプリケーション・ビルドプロジェクト

まず最初は、コマンドラインで実行するJavaアプリケーションをビルドするGradleプロジェクトを作成します。
Gradleのinitタスクを実行し、必要な設定や雛形を自動生成します。

プロジェクトディレクトリの作成

開発するプロジェクトのディレクトリを作成します。

Windows MacOS
D:\work> mkdir HelloApp
D:\work> cd HelloApp
D:\work\HelloApp>
work % mkdir HelloApp
work % cd HelloApp
HelloApp %

ひとまず空のディレクトリ D:\work\HelloApp (MacOS: ~/work/HelloApp) を用意しました。

gradleのinitタスクを実行

ビルドの実行と生成される成果物ディレクトリ・ファイル

gradlew.bat を実行します。コマンドラインオプションには、ターゲット(ビルドの場合は build)を指定します。

D:\work\HelloApp> gradlew build
Downloading https://services.gradle.org/distributions/gradle-6.4-bin.zip
.........10%..........20%..........30%..........40%.........50%..........60%..........70%..........80%.........90%..........100%

BUILD SUCCESSFUL in 23s
7 actionable tasks: 7 executed

ビルド結果次のディレクトリ・ファイルが生成されます。

C:\work\HelloApp\app
├─build
   ├─classes
   │  └─java
   │      ├─main
   │      │  └─com
   │      │      └─torutk
   │      │          └─hello
   │      │                  App.class
   │      │
   │      └─test
   │          └─com
   │              └─torutk
   │                  └─hello
   │                          AppTest.class
   │
   ├─distributions
   │      app.tar
   │      app.zip
   │
   ├─generated
   │  └─sources
   │      ├─annotationProcessor
   │      │  └─java
   │      │      ├─main
   │      │      └─test
   │      └─headers
   │          └─java
   │              ├─main
   │              └─test
   ├─libs
   │      app.jar
   │
   ├─reports
   │  └─tests
   │      └─test
   │          │  index.html
   │          │
   │          ├─classes
   │          │      com.torutk.hello.AppTest.html
   │          │
   │          ├─css
   │          │      base-style.css
   │          │      style.css
   │          │
   │          ├─js
   │          │      report.js
   │          │
   │          └─packages
   │                  com.torutk.hello.html
   │
   ├─scripts
   │      app
   │      app.bat
   │
   ├─test-results
   │  └─test
   │      │  TEST-com.torutk.hello.AppTest.xml
   │      │
   │      └─binary
   │              output.bin
   │              output.bin.idx
   │              results.bin
   │
   └─tmp
       ├─compileJava
       │  │  source-classes-mapping.txt
       │
       ├─compileTestJava
       │  │  source-classes-mapping.txt
       │  
       ├─jar
       │  │  MANIFEST.MF
       │  
        └─test

プログラムの実行

runタスクでプログラムを実行します。

D:\work\HelloApp> gradlew run

> Task :app:run
Hello world!

BUILD SUCCESSFUL in 3s
2 actionable tasks: 1 executed, 1 up-to-date

D:\work\HelloApp>

buildタスクで生成されたjarファイルをjavaコマンドから実行することも可能です。
実行可能JARファイルは生成されませんので、以下の実行は失敗します。

D:\work\HelloApp> java -jar build\libs\HelloApp.jar
Hello world.
 
D:\work\HelloApp>

プログラムの実行時にコマンドライン引数を渡す

Javaプログラムにコマンドライン引数を渡すには、gradleのrunタスクの後に--argsオプションでコマンドライン引数の全体の文字列を指定します。

D:\work\HelloApp> gradlew run --args="--x=200 --y=300" 
:

ビルド生成物の削除(クリーン)

ビルドによって生成されたディレクトリ・ファイルを削除します。

D:\work\HelloApp> gradlew clean
BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

D:\work\HelloApp> 

ユニットテストの実行

testタスクでユニットテストを実行します。実行結果はレポートファイルに出力されます。

D:\work\HelloApp> gradlew test

BUILD SUCCESSFUL in 2s
3 actionable tasks: 3 executed
D:\work\HelloApp> 

テスト結果は次に生成されます。
D:\work\HelloApp\build\reports\tests\test\index.html

ブラウザに表示させたものは次です。

clipboard-202005081413-sfxun.png

次の一歩

ライブラリを使用する

Mavenリポジトリを指定する

Sonatype社 が提供するソフトウェア配布サービス Central Repository で、mavenのデフォルトのリポジトリです。Central Repository 上のライブラリを利用するときは次のように定義します。

repositories {
  mavenCentral()
}

他の定義済みリポジトリ

  • jcenter()
    JFrog社 が提供するソフトウェア配布サービス Bintray を利用するmaven互換リポジトリですが、2022年1月をもって提供をやめるとのアナウンスが出ています。

独自のリポジトリを使用するときは、そのリポジトリのURLを指定します。

repositories {
  maven {
    url = uri("http://repo.example.com/maven2")
  }
}

ローカルマシン上のファイルを指定する

ローカルマシンに配置したライブラリを使用することができます。

flatDir でライブラリを置くディレクトリをリポジトリ指定する方法

リポジトリ指定でflatDirを用いてライブラリを収めたフォルダを指定します。

repositories {
  flatDir {
    dirs("relative/to/dir", "/absolute/to/dir", "$junit5")
  }
}

junit5 プロパティは、gradle.propertiesファイルやコマンドラインから指定します。

  • gradle.properties
    junit5 = C:/Program Files/Java/junit5
    

ピリオドを含むプロパティ名を使用すると、例えば ${junit5.dir} の様に参照するとエラーとなります。ピリオドがメソッド呼び出し式と扱われるためです。この場合は、次のいずれかの指定をして回避します。

dirs getProperty("junit5.dir")
dirs "${property('junit5.dir')}"
dirs "${project.'junit5.dir'}"

fileTreeでライブラリのディレクトリとファイル名を指定する方法

依存関係指定でfileTreeを用いてライブラリファイルのディレクトリと名前を指定します。

dependencies {
    implementation(fileTree(mapOf("dir" to "javafx-gadgetsupport/dist", "include" to listOf("*.jar")))
}

ディレクトリ指定は相対パス、絶対パスの指定が可能です。

使用するライブラリを指定する

dependencies {
  implementation("org.slf4j:slf4j-api:1.7.13")
  testImplementation("junit:junit:4.12")
}

コンパイル時および実行時の双方に使用するライブラリは、implementationで名称を指定します。
テストのコンパイル時およびテストの実行時に使用する(開発対象プログラムの中では使用しない)ライブラリは、testImplementationで名称を指定します。
その他、compileOnlyruntimeOnlytestCompileOnlytestRuntimeOnlyapiなどの指定があります。

従来使っていたcompileruntimetestCompiletestRuntimeは非推奨となっており、今後のバージョンで使用できなくなります。

Javaのバージョン指定

Javaのソースコード記述、クラスファイルのバージョン指定

ソースファイルの記述(言語仕様)バージョン、およびコンパイル後のクラスファイルのバージョンを指定します。

java {
    sourceCompatibility = JavaVersion.VERSION_21
    targetCompatibility = JavaVersion.VERSION_21
}

ビルドで使う各種ツールのJDKバージョン指定

java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(21))
    }

文字コードの指定

JDK 17までは、Java実行環境のデフォルトエンコーディングがシステム(OS)のエンコーディングとなるので、ソースファイルの文字コードがシステムのエンコーディングと異なる場合は、Javaコンパイラがソースファイルを正しく読み込めないので、コンパイルオプションにエンコーディング指定を追加する必要があります。
例えば、JavaソースファイルをUTF-8エンコーディングで記述し、Windows OS日本語版(エンコーディングはCP932/Windows_31J)でJavaコンパイラを実行すると、ASCIIコードの文字(UTF-8の1バイト文字)以外の文字がエラーとなってしまいます。

Gradleでは、幾つか方法がありますが、以下が柔軟に対応できます。

tasks.withType(JavaCompile) {
    options.encoding = "UTF-8" 
}

JDK 18以降で、ソースファイルをUTF-8エンコーディングで記述している場合は、JavaコンパイラがUTF-8エンコーディングとして動くので、このエンコーディング指定は不要となります。

JVMオプション指定

アプリケーション実行時にjavaコマンドのオプションを指定する

application {
    applicationDefaultJvmArgs = listOf("-Dgreeting.language=en")
}

JPMSのモジュール対応

モジュール対応JAR

Gradle 7.0からこの記述は不要となりました。

java {
    modularity.inferModulePath = true
}

この設定で、モジュール対応JARライブラリ参照をモジュールパスとして扱われます。

メインクラスを持つモジュール対応JAR

application {
    mainModule = "org.gradle.sample.app" // name defined in module-info.java
    mainClass = "org.gradle.sample.Main" 
}

参考

Java 9 Jigsaw support #890
Building JPMS Modules with Gradle (Youtube)

ソースディレクトリの構成を変更

デフォルトでは、Javaのソースファイルは src/main/java ディレクトリの下に置かれている前提となっています。また、ソースファイル以外のリソースファイルは src/main/resources ディレクトリに置かれる前提となっています。

これを変更する場合、例えばJavaソースファイルおよびリソースファイルをともに src ディレクトリ下に置くには、sourceSets を定義します。

sourceSets {
    main {
        java.srcDir("src")
        resources.srcDir("src")
    }
}

サンプル等

単一モジュールのGradleプロジェクト

複数モジュールのGradleプロジェクト

ユニットテスト

JUnit 5

  • [#116] GradleでJUnit5テストをローカルマシンで実施する

応用

依存するライブラリをダウンロードする

参照:調査チケット #79

Gradleでは依存するライブラリを、実行した環境のキャッシュディレクトリ(ユーザー固有のディレクトリで、Windows上であれば%USERPROFILE%\.gradle\caches\modules-2\files-2.1\の下、caches以下のディレクトリ名はGradleのバージョンにより変わるかも)に保持します。
ここにはその環境で過去実施したビルドで使用した依存ライブラリが一緒くたに置かれるので、あるライブラリとその依存ライブラリだけを抽出したいときには対応に苦慮します。

そこで、依存するライブラリをダウンロードする専用のビルド定義を記述し必要なものだけダウンロードします。

依存するライブラリのダウンロード定義

apply plugin: 'java'

def libDir = 'lib'

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.jvnet.com4j:com4j:2.1'
}

task deleteDeps(type: Delete) {
    delete libDir
}

task copyDeps(type: Copy, dependsOn: deleteDeps) {
    from configurations.testRuntime
    into libDir
}

dependencies には、ビルドするときに定義するライブラリの記述と同様にダウンロードしたいライブラリを記述します。
コピータスク(copyDeps)で、testRuntimeを指定しているのは、依存するライブラリの範囲を最大にしているためです。ここをcompileと指定すればコンパイルに必要なものだけダウンロードします(その場合、実行時に必要なライブラリが抜ける可能性があります)。

Gradleのバージョンを更新する

Gradleプロジェクトでwrapperを使用しているときのgradleバージョン更新

  • 現在のGradleプロジェクトが使用するGradleバージョンを確認
    D:\work\myproj> gradlew -v
    
    ------------------------------------------------------------
    Gradle 6.5.1
    ------------------------------------------------------------
     :
    
  • Gradleプロジェクトのwrapperで使用するgradleバージョンを更新
    最新のリリースバージョンである6.8.3に更新するときの例を次に示します。
    D:\work\myproj> gradlew wrapper --gradle-version=6.8.3
    
    

    このコマンドは、gradle/wrapper/gradle-wrapper.properties ファイルを更新します。
  • Gradleの本体、バッチ・スクリプト更新を更新するには次を実行
    D:\work\myproj> gradlew wrapper
    
    

サーブレットアプリケーションの作成

Gradleではサーブレットアプリケーションを作成するwarプラグインが提供されています。ただし、warプラグインを使うGradleプロジェクトは、initでは生成できません。

Gradleの機能

コマンド

UP-TO-DATEとなるタスクを実行したい

proj$ ./gradlew jlinkZip --rerun

cleanタスクを実行しても、タスクがUP-TO-DATEとなることがありました。タスクの実行要否の判断で、インプットとなるファイルに変更がない場合にアウトプットが存在しなくてもUP-TO-DATEとなるケースがあるようです。gladleコマンドに実行したいタスクと--rerunオプションを指定することで、UP-TO-DATEと判断されるタスクを実行します。

ビルド設定

ビルド定義(build.gradle等)の外部から設定を行います。ユーザー/特定のビルド環境に固有の設定をビルドに適用する場合に使用します。

  • Javaのシステムプロパティとして与える
  • Gradleプロパティとして与える
  • 環境変数で与える

システムプロパティ

システムプロパティとして定義した値をビルドで利用します。定義方法は
  • gradleのコマンドラインで、-Dオプションで指定。例: gradlew -Dmy.data.dir=D:\data\myapp
  • gradle.properteisファイルに、systemProp.の後ろにキーと価を指定。例: systemProp.my.data.dir=D:\data\myapp

gradleプロパティ

プロジェクトディレクトリに置いたgradle.propertiesファイル、およびユーザーのホームディレクトリ下の gradle\gradle.properties ファイルに記載します。

systemProp.my.data.dir=D:\data\myapp

プラグイン

Build Init プラグイン

Gradleビルドプロジェクトの新規作成を行うプラグインです。

  1. ビルド種類(build type)
  2. DSL言語(ビルド定義を記述する言語、GroovyかKotlinか)
  3. ビルド種類がJava系の場合、テストフレームワーク

Java用のビルドでは、次のオプションをコマンドライン指定または対話的に入力します。

オプション名 オプション指定 オプションの値 備考
ビルド種類 --build-type java-application, java-library
DSL言語 --dsl groovy, kotlin
テストフレームワーク --test-framework junit4, junit-jupiter, spock, testng
プロジェクト名 --project-name プロジェクト名 成果物(JARファイル等)の名称に使われる
パッケージ名 --package パッケージ名 成果物の代表パッケージ名

javaプラグイン

Javaのライブラリを作成する際に有用なプラグインです。次のタスクが提供されています。

classes
testClasses
compileJava
compileTestJava
jar
test
javadoc
clean
assemble
check
bulid
buildNeeded
buildDependents
processResources
processTestResources
uploadArchives

新規にプロジェクトを作成するときのテンプレート生成も提供されています。

work$ gradle init --type java-library
:wrapper
:init

BUILD SUCCESSFUL

Total time: 1.62 secs

work$ ls
build.gradle*  gradle/  gradlew*  gradlew.bat*  settings.gradle*  src/

生成されるbuild.gradleは次になります(コメントを削除しています)。

apply plugin: 'java'

repositories {
    jcenter()
}

dependencies {
    compile 'org.slf4j:slf4j-api:1.7.13'
    testCompile 'junit:junit:4.12'
}

javacコンパイルオプション

compilerArgsに任意のオプションを記述するとコンパイル時にjavacコマンドのオプションとして適用されます。
Gradle User Manual - CompileOptions

compileJava {
    options.compilerArgs.addAll(['--release', '7'])
}

Gradleの記述方法

Gradleは、Groovy言語で記述します(その後Kotlin言語で記述することもできるようになりました)。

Groovyの記法メモ

Groovy は、一つの事を記述するのに複数の書き方があり、混沌に属する言語です(まるでPerlの再来)。

  • メソッド呼び出し式では括弧を省略
  • プロパティ風な書き方で、setterメソッドの代わりに代入式を書ける
  • 名前付き引数(これと括弧の省略を合わせると何が何だかな記法になる)
  • 波括弧でクロージャー(コードブロック)

Gradleのバージョン

Gradle Compatibility Matrix

バージョンの変遷(トピック)

  • v8.5
    JDK 21への完全対応
  • v8.4
    JDK 21を使ったビルド・テストに対応(Gradle自身のJDK 21上での実行は未サポート)
  • v8.3
    JDK 20への完全対応
  • v7.3
    JDK 17を使うプロジェクトのビルド、JDK 17上でGradleの実行対応
  • v7.0 2021-04-9
    JDK 16対応、Groovy 3に移行
  • v6.4.1 2020-05-15
    Javaモジュールシステムに対応


23日前に更新