daisukeの技術ブログ

AI、機械学習、最適化、Pythonなどについて、技術調査、技術書の理解した内容、ソフトウェア/ツール作成について書いていきます

GradleでJavaプロジェクトを作ってみる(Ubuntu22.04)

今回は、Java向けのビルドツールである Gradle を使ってみます。

Java用、もしくは、Javaに使えるビルドツールとして、Make、Ant、Mavenなどがありますが、最近は Gradle がよく使われています。

名前も Gradle(グレードル)が一番かっこいいですし、読み方も明らかでいいですね。Mavenは、メイバンと読むと思ってたんですけど、日本の方はメイブンとかメイベンとか呼んでますね。海外の方のYouTube見ると、メイバンとメイベンの中間ぐらいに聞こえます。

あと、Gradle のロゴも特徴的で良いデザインだと思います!(アイキャッチ画像に使わせてもらいました)

今回は、Gradle を使った簡単なプロジェクトを使って理解していきます。

参考文献

はじめに

「Javaでデザインパターンを学ぶ」の記事一覧です。良かったら参考にしてください。

Javaでデザインパターンの記事一覧

エンジニアグループのランキングに参加中です。

気楽にポチッとよろしくお願いいたします🙇

それではやっていきます!

Ubuntu 22.04 に Gradle をインストール

Gradleの公式サイトです。

gradle.org

公式サイトのインストール手順です。最新バージョンは8.7のようです。

Gradle | Installation

公式の手順では、SDKMAN?を使うか、バイナリを手動で入れる方法しかありませんでした。

公式の手順とは違いますが、普通にaptで、Gradleをインストールしてみます。

$ sudo apt install gradle
$ gradle -v

------------------------------------------------------------
Gradle 4.4.1
------------------------------------------------------------

Build time:   2012-12-21 00:00:00 UTC
Revision:     none

Groovy:       2.4.21
Ant:          Apache Ant(TM) version 1.10.12 compiled on January 17 1970
JVM:          17.0.10 (Private Build 17.0.10+7-Ubuntu-122.04.1)
OS:           Linux 6.5.0-28-generic amd64

普通に入れると、かなり古いバージョン(2012年)がインストールされました。

リポジトリを追加してみます。

$ sudo add-apt-repository ppa:cwchien/gradle
$ sudo apt update
$ sudo apt-get upgrade gradle
$ gradle -v

Welcome to Gradle 8.3!

Here are the highlights of this release:
 - Faster Java compilation
 - Reduced memory usage
 - Support for running on Java 20

For more details see https://docs.gradle.org/8.3/release-notes.html


------------------------------------------------------------
Gradle 8.3
------------------------------------------------------------

Build time:   2023-08-17 07:06:47 UTC
Revision:     8afbf24b469158b714b36e84c6f4d4976c86fcd5

Kotlin:       1.9.0
Groovy:       3.0.17
Ant:          Apache Ant(TM) version 1.10.13 compiled on January 4 2023
JVM:          17.0.10 (Private Build 17.0.10+7-Ubuntu-122.04.1)
OS:           Linux 6.5.0-28-generic amd64

8.3が入りました。とりあえず、これでやっていきます。

公式サイトの Getting Started をやってみる

公式サイトの Getting Started です。

Gradle | Gradle Guides

この中の「Building Java Applications」をやってみます。

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

まず、プロジェクトを格納するディレクトリを作ります。demoディレクトリを作ると書かれてましたが、少し変えます。

$ mkdir gradle-demo
$ cd gradle-demo/

初期化タスクを実行する

続いて、init task を実行します。横に値が書いてるのは入力したもので、何も書かれてないのはデフォルトを選択しました。

$ gradle init
Starting a Gradle Daemon (subsequent builds will be faster)

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: Scala
  6: Swift
Enter selection (default: Java) [1..6] 3

Generate multiple subprojects for application? (default: no) [yes, no]
Select build script DSL:
  1: Kotlin
  2: Groovy
Enter selection (default: Kotlin) [1..2]

Select test framework:
  1: JUnit 4
  2: TestNG
  3: Spock
  4: JUnit Jupiter
Enter selection (default: JUnit Jupiter) [1..4]

Project name (default: gradle-demo):
Source package (default: gradle.demo):
Enter target version of Java (min. 7) (default: 17):
Generate build using new APIs and behavior (some features may change in the next minor release)? (default: no) [yes, no]

> Task :init
To learn more about Gradle by exploring our Samples at https://docs.gradle.org/8.3/samples/sample_building_java_applications.html

BUILD SUCCESSFUL in 1m 51s
2 actionable tasks: 2 executed

途中の「Generate multiple subprojects for application?」がちょっと分からなくて、デフォルトで no でした。

yes にした場合が気になったので、yesにして作ったプロジェクトと比較してみます。

$ colordiff -u gradle-demo gradle-demo-multi/
共通のサブディレクトリー: gradle-demo/.gradle と gradle-demo-multi/.gradle
共通のサブディレクトリー: gradle-demo/app と gradle-demo-multi/app
gradle-demo-multi/ のみに存在: buildSrc
共通のサブディレクトリー: gradle-demo/gradle と gradle-demo-multi/gradle
gradle-demo-multi/ のみに存在: list
diff -u gradle-demo/settings.gradle.kts gradle-demo-multi/settings.gradle.kts
--- gradle-demo/settings.gradle.kts     2024-04-30 00:24:47.943000000 +0900
+++ gradle-demo-multi/settings.gradle.kts       2024-04-30 00:27:22.604000000 +0900
@@ -10,5 +10,5 @@
     id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0"
 }

-rootProject.name = "gradle-demo"
-include("app")
+rootProject.name = "gradle-demo-multi"
+include("app", "list", "utilities")
gradle-demo-multi/ のみに存在: utilities

multiを選択した場合は、BuildSrcという特別なディレクトリがあって、コードの再利用や、ビルドプロセスのカスタマイズ、プロジェクト構造を整理できるようです(from ChatGPT)。

それでは、multiは選択しない方で、続きをやっていきます。

自動生成されたディレクトリ、ファイルを確認します。

$ tree
.
|-- app
|   |-- build.gradle.kts
|   `-- src
|       |-- main
|       |   |-- java
|       |   |   `-- gradle
|       |   |       `-- demo
|       |   |           `-- App.java
|       |   `-- resources
|       `-- test
|           |-- java
|           |   `-- gradle
|           |       `-- demo
|           |           `-- AppTest.java
|           `-- resources
|-- gradle
|   `-- wrapper
|       |-- gradle-wrapper.jar
|       `-- gradle-wrapper.properties
|-- gradlew
|-- gradlew.bat
`-- settings.gradle.kts

14 directories, 8 files

プロジェクト名を demo から gradle-demo に変更したことで、App.java までの階層が1つ深くなりました(プロジェクトをdemoにすると、gradleディレクトリは作られないようです)。

重要なファイルは、以下の3ファイルです。

  • settings.gradle.kts:gradle-demoプロジェクトの設定ファイル
  • build.gradle.kts:appプロジェクトのビルドスクリプト
  • App.java:appプロジェクトのJavaソースファイル

settings.gradle.ktsです。「include("xxx")」を追加すると、「app」と同じようにxxxプロジェクトを追加できます。

// settings.gradle.kts
plugins {
    // Apply the foojay-resolver plugin to allow automatic download of JDKs
    id("org.gradle.toolchains.foojay-resolver-convention") version "0.4.0"
}
rootProject.name = "gradle-demo"
include("app")

build.gradle.ktsです。分かることは以下です。

  • JavaのCLIアプリケーションです
  • Maven Centralリポジトリを使っています
  • Google製のJavaライブラリ「Guava」を使っています
  • Javaはバージョン17が使われています
  • エントリポイントは「gradle.demo.App」です
// build.gradle.kts
plugins {
    // Apply the application plugin to add support for building a CLI application in Java.
    application
}

repositories {
    // Use Maven Central for resolving dependencies.
    mavenCentral()
}

dependencies {
    // Use JUnit Jupiter for testing.
    testImplementation("org.junit.jupiter:junit-jupiter:5.9.3")

    testRuntimeOnly("org.junit.platform:junit-platform-launcher")

    // This dependency is used by the application.
    implementation("com.google.guava:guava:32.1.1-jre")
}

// Apply a specific Java toolchain to ease working on different environments.
java {
    toolchain {
        languageVersion.set(JavaLanguageVersion.of(17))
    }
}

application {
    // Define the main class for the application.
    mainClass.set("gradle.demo.App")
}

tasks.named<Test>("test") {
    // Use JUnit Platform for unit tests.
    useJUnitPlatform()
}

App.javaです。「Hello World!」を表示するアプリケーションのようです。

// App.java
package gradle.demo;

public class App {
    public String getGreeting() {
        return "Hello World!";
    }

    public static void main(String[] args) {
        System.out.println(new App().getGreeting());
    }
}

アプリケーションを実行する

アプリケーションを実行してみます。

$ ./gradlew run
Downloading https://services.gradle.org/distributions/gradle-8.3-bin.zip
............10%............20%.............30%............40%.............50%............60%.............70%............80%.............90%............100%
Path for java installation '/usr/lib/jvm/openjdk-17' (Common Linux Locations) does not contain a java executable

> Task :app:run
Hello World!

BUILD SUCCESSFUL in 48s
2 actionable tasks: 2 executed

アプリケーションが実行されて、「Hello World!」が表示されました。

追加されたディレクトリ、ファイルを確認します。

$ tree
.
|-- app
|   |-- build
|   |   |-- classes
|   |   |   `-- java
|   |   |       `-- main
|   |   |           `-- gradle
|   |   |               `-- demo
|   |   |                   `-- App.class
|   |   |-- generated
|   |   |   `-- sources
|   |   |       |-- annotationProcessor
|   |   |       |   `-- java
|   |   |       |       `-- main
|   |   |       `-- headers
|   |   |           `-- java
|   |   |               `-- main
|   |   `-- tmp
|   |       `-- compileJava
|   |           `-- previous-compilation-data.bin
|   |-- build.gradle.kts
|   `-- src
|       |-- main
|       |   |-- java
|       |   |   `-- gradle
|       |   |       `-- demo
|       |   |           `-- App.java
|       |   `-- resources
|       `-- test
|           |-- java
|           |   `-- gradle
|           |       `-- demo
|           |           `-- AppTest.java
|           `-- resources
|-- gradle
|   `-- wrapper
|       |-- gradle-wrapper.jar
|       `-- gradle-wrapper.properties
|-- gradlew
|-- gradlew.bat
`-- settings.gradle.kts

30 directories, 10 files

ディレクトリはたくさん増えてますが、ファイルは2つ追加されました。App.class と、previous-compilation-data.bin です。

アプリケーションをビルドする

配布可能なアプリケーションを構築します。

$ ./gradlew build
Path for java installation '/usr/lib/jvm/openjdk-17' (Common Linux Locations) does not contain a java executable

BUILD SUCCESSFUL in 15s
7 actionable tasks: 6 executed, 1 up-to-date

1行目に警告が出ていますが、stack overflowによると、問題ないそうです。

増えたファイルを確認します。

$ tree
.
|-- app
|   |-- build
|   |   |-- classes
|   |   |   `-- java
|   |   |       |-- main
|   |   |       |   `-- gradle
|   |   |       |       `-- demo
|   |   |       |           `-- App.class
|   |   |       `-- test
|   |   |           `-- gradle
|   |   |               `-- demo
|   |   |                   `-- AppTest.class
|   |   |-- distributions
|   |   |   |-- app.tar
|   |   |   `-- app.zip
|   |   |-- generated
|   |   |   `-- sources
|   |   |       |-- annotationProcessor
|   |   |       |   `-- java
|   |   |       |       |-- main
|   |   |       |       `-- test
|   |   |       `-- headers
|   |   |           `-- java
|   |   |               |-- main
|   |   |               `-- test
|   |   |-- libs
|   |   |   `-- app.jar
|   |   |-- reports
|   |   |   `-- tests
|   |   |       `-- test
|   |   |           |-- classes
|   |   |           |   `-- gradle.demo.AppTest.html
|   |   |           |-- css
|   |   |           |   |-- base-style.css
|   |   |           |   `-- style.css
|   |   |           |-- index.html
|   |   |           |-- js
|   |   |           |   `-- report.js
|   |   |           `-- packages
|   |   |               `-- gradle.demo.html
|   |   |-- scripts
|   |   |   |-- app
|   |   |   `-- app.bat
|   |   |-- test-results
|   |   |   `-- test
|   |   |       |-- TEST-gradle.demo.AppTest.xml
|   |   |       `-- binary
|   |   |           |-- output.bin
|   |   |           |-- output.bin.idx
|   |   |           `-- results.bin
|   |   `-- tmp
|   |       |-- compileJava
|   |       |   `-- previous-compilation-data.bin
|   |       |-- compileTestJava
|   |       |   `-- previous-compilation-data.bin
|   |       |-- jar
|   |       |   `-- MANIFEST.MF
|   |       `-- test
|   |-- build.gradle.kts
|   `-- src
|       |-- main
|       |   |-- java
|       |   |   `-- gradle
|       |   |       `-- demo
|       |   |           `-- App.java
|       |   `-- resources
|       `-- test
|           |-- java
|           |   `-- gradle
|           |       `-- demo
|           |           `-- AppTest.java
|           `-- resources
|-- gradle
|   `-- wrapper
|       |-- gradle-wrapper.jar
|       `-- gradle-wrapper.properties
|-- gradlew
|-- gradlew.bat
`-- settings.gradle.kts

51 directories, 28 files

たくさん増えました。重要なのは、app/build/distributions/app.zip(app.tar)でしょうか。

app.zipを解凍して実行してみます。

$ cd app/build/distributions/
$ unzip app.zip
Archive:  app.zip
   creating: app/
   creating: app/lib/
  inflating: app/lib/app.jar
  inflating: app/lib/guava-32.1.1-jre.jar
  inflating: app/lib/failureaccess-1.0.1.jar
  inflating: app/lib/jsr305-3.0.2.jar
  inflating: app/lib/checker-qual-3.33.0.jar
  inflating: app/lib/error_prone_annotations-2.18.0.jar
   creating: app/bin/
  inflating: app/bin/app
  inflating: app/bin/app.bat
$ cd app/bin/
$ ./app
Hello World!

CLI(コマンドラインインタフェース)アプリケーションが作られていて、実行もできました。

アプリケーションをスキャンする

スキャンすると、ビルドの詳細を教えてくれるようです。

$ ./gradlew build --scan
Path for java installation '/usr/lib/jvm/openjdk-17' (Common Linux Locations) does not contain a java executable

BUILD SUCCESSFUL in 1s
7 actionable tasks: 7 up-to-date

Publishing a build scan to scans.gradle.com requires accepting the Gradle Terms of Service defined at https://gradle.com/terms-of-service. Do you accept these terms? [yes, no] yes

Gradle Terms of Service accepted.

Publishing build scan...
https://gradle.com/s/mtyxq5dwgsw76

提示されたURLにアクセスすると、メールアドレスを入力するフォームがあり、入力してGoをクリックすると、メールが届きます(スクショ忘れました)。そのメールのリンクをクリックすると以下のようなビルド結果のレポートページが作成されてました。

ビルド結果レポート
ビルド結果レポート

全部見れてないですが、豪華で詳細なレポートでした。

おわりに

今回は Gradle を使って、Java のコマンドラインアプリケーションを作ってみました。

次回は、今回作った Gradle プロジェクトを IntelliJ(総合開発環境)でデバッグしたいと思います。

今回は以上です!

最後までお読みいただき、ありがとうございました。