Gradleで好きなクラスを実行させよう。

GradleでJava/Groovyなどで作成したクラスを指定して実行したい場合、
JavaExecにmainクラスを指定して実行させるとよいです。

汎用的に実行できるタスクの書き方を記載しておきます。

Gradle とは

JVMで動作するので、Java (JDK) さえインストールされていれば、
必要な依存ライブラリはGradleが勝手にダウンロードして来てくれて、コンパイルを通してくれます。

依存関係を解決してくれるので、
プロジェクトリポジトリをクローンしてもらうだけで、
個々人でコンパイルできる環境が簡単に用意できる超便利なやつ。

依存関係の設定や、タスクランナーとして設定することができますが。

build.gradleの書き方が、初見だとよくわからないかもしれません。
ただの設定ファイルに見えますが、これはgroovyスクリプトになっています。

そのおかげ?で結構柔軟なプロジェクト設定、タスク実装まで可能になっています。

実行クラス

src/main/java
src/main/groovy

とかに実装したクラスをメインクラスとして実行したい場合は、
JavaExecというタスクをbuild.gradleに記述して実装します。

JavaExecリファレンス

apply plugin: 'java'

task runApp(type: JavaExec) {
  classpath = sourceSets.main.runtimeClasspath

  main = 'package.Main'

  // arguments to pass to the application
  args 'appArg1'
}

applicationプラグイン

他に applicationプラグインというのもあります。

./gradlew run で指定のクラスを実行させる事もできますが、
このプラグインは、プロジェクトをパッケージングして配布
配布先で実行してもらうことが主な目的になります。
(パッケージングされたものは、JREさえあれば動作するものにできます。)

JavaExecを使う

で、僕がおすすめするJavaExecの書き方がこれです。

apply plugin: 'groovy'
apply plugin: 'idea'

repositories {
    jcenter()
}

dependencies {
    compile localGroovy()
}

// 指定クラスを実行してくれるタスク
task launch(type: JavaExec) {
    // runtime用の依存クラスPATHを設定 (ここに記載しておくのが大事)
    classpath = sourceSets.main.runtimeClasspath

    doFirst {
        // -Pmain指定がない場合はエラー
        if (!project.hasProperty("main")) {
            throw new IllegalArgumentException("""
                | usage:
                |         ./gradlew $name -Pmain=<ClassName>
                """.stripMargin())
        }

        // システムプロパティを継承する
        systemProperties = System.properties as Map

        // メインクラスを指定
        main = project.main
    }
}

doFirstに、mainクラスの指定があるかどうか事前チェックをしています。

実行例

実行するときは、メインクラス名を指定して実行する事ができます。

./gradlew launch -Pmain=MyClass

-Pオプションについて

Gradleのタスクに付けている、-Pmainですが、
これは、Gradleに渡すプロパティの事です。

Gradleの projectインスタンスのプロパティとして反映されます。
project.main

指定がない時にアクセスすると例外が発生するので、ちゃんと指定されているか予めチェックしておく必要があります。

project.hasProperty("main")

mainクラス指定を強制

$ ./gradlew launch                                                                                                              
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':launch'.
> 
   usage:
           ./gradlew launch -Pmain=<ClassName>


* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 0s
1 actionable task: 1 executed

こんな感じで、もし指定のメインクラスをオプション指定 (-Pmain) できてないとエラーメッセージを表示してくれます。

Systemプロパティを継承できる

引数を渡したい事もあるでしょうが、
引数を渡すのはちょっと癖があります。

それよりも、Javaのシステムプロパティの形で実行クラスに渡す方が直感的でしょう。

-Dオプション

Java で一般的なシステムプロパティとは、
-Dhoge=foo のような形で指定できます。

./gradlew launch -Pmain=sample1 -Dhoge=foo

この場合、Gradleに対してシステムプロパティを指定した事にしかなりませんので、
実行したいクラスにもプロパティが継承されるように、この記述が必要です。

// システムプロパティを継承する
systemProperties = System.properties as Map

タスクに指定した、システムプロパティを実行クラスのもそのまま渡しています。

余談

localGroovy

dependencies {
    compile localGroovy()
}

dependencies に、localGroovy()と書いていますが、
これば、gradleが使うgroovyをそのままコンパイル時に含める事ができます。

もちろん、通常通り指定する事もできます。

compile group: 'org.codehaus.groovy', name: 'groovy-all', version: '2.4.14'

NoClassDefFoundError

Groovyで、FileNameFinderなどのクラスを使ったコードを書くと
以下のようなクラスが見つからないというエラーがでます。

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/tools/ant/BuildLogger

これは、optionalな依存ライブラリなので、
そういったクラスを使う場合は、明示的にコンパイルに含める必要があります。

compile group: 'org.apache.ant', name: 'ant', version: '1.9.4'

おしまい

Gradleはとっつきにくいかもしれませんが、
使いこなすととても便利です。

ちょっと勉強してみてはいかがでしょう。

過去記事:
Gradle taskのdoFirstとdoLast

1件のコメント

コメントを残す