Gradle DefaultTask クラスの使用

Gradle には標準で DefaultTask クラスが用意されており、多くのタスククラスはこれを継承して実装されている。 このページでは、そのようなクラスを使ったタスク作成について説明する。

DefaultTask を継承するクラス

Gradle には標準でさまざまなタスクが含まれており、それらの多くは DefaultTask を継承したクラスとして用意されている。 自分で DefaultTask を継承したタスククラスを作成することもできる。

DefaultTask を継承するクラスは次のような形で定義する。

class ClassName extends DefaultTask {
    // fields

    void method(arguments) {
        // processing
    }

    @TaskAction
    void method() {
        // processing
    }
}

クラスは DefaultTask を継承し、タスクとして実行する処理をメソッドとして用意する。 タスク実行時に呼び出すメソッドには @TaskAction アノテーションを付ける。

タスクで使用する値はフィールドとして保持できる。 外部から設定する値は private フィールドにし、設定用メソッドを用意すると扱いやすい。

簡単な例は次のとおりである。

class Calc extends DefaultTask {
    private int num
    private String op
 
    void num(p1){
        num = p1
    }
 
    void op(p1){
        op = p1
    }
 
    @TaskAction 
    void calc() {
        switch(op) {
        case 'total':
            int total = 0
            for(def i in 1..num) {
                total += i
            }
            println("total: ${total}")
        break
 
        case 'count':
            for(def i in 1..num) {
                println("NO, ${i}")
            }
        break
 
        default:
            println('not found operator...')
        }
    }
}

Calc クラスには calc というタスクアクションが用意されている。 numop の値に応じて、合計計算やカウント表示を行う。

Calc クラスを指定したタスク

DefaultTask 継承クラスを使うタスクは次のように書く。

task taskName(type : ClassName) {
    // 実行する処理
}

タスクの引数 type に使用するクラスを指定する。 タスク内では、そのクラスのフィールドに対応する値を設定する。 設定後にタスクアクションが実行される。

task total(type:Calc) {
    group 'devkuma'
    description 'Task for calculating total.'
    num 100
    op 'total'
}
 
task count(type:Calc) {
    group 'devkuma'
    description 'Task for count number.'
    num 10
    op 'count'
}

ここでは Calctype に指定した totalcount の 2 つのタスクを作成している。 gradle total を実行すると 100 までの合計が計算される。

$ gradle total

> Task :total
total: 5050


BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

gradle count を実行すると、1 から 10 までの数字が順に表示される。

$ gradle count

> Task :count
NO, 1
NO, 2
NO, 3
NO, 4
NO, 5
NO, 6
NO, 7
NO, 8
NO, 9
NO, 10


BUILD SUCCESSFUL in 0s
1 actionable task: 1 executed

(type:Calc) を指定することで、Calc クラスのタスクアクションを実行するタスクとして定義される。 タスク内では groupdescriptionnumop などのメソッドを呼び出している。 groupdescriptionDefaultTask にあるもので、numopCalc クラスに定義したメソッドである。

JavaExec クラスの利用

DefaultTask 継承クラスを使ったタスク作成の基本を確認したので、Gradle が提供する主なタスククラスの使い方を見ていく。

JavaExec クラス

JavaExec は Java プログラムを実行するためのタスクを実装するクラスである。 実行に必要な各種メソッドが用意されている。

main "ClassName"

実行するクラスを指定する。

classpath "text"

実行時に使う classpath を指定する。 デフォルトの classpath を使う場合は sourceSets.main.runtimeClasspath を指定する。

args "Iterator"
args "value1, value2, ..."

プログラムに渡す引数を指定する。 Iterator としてまとめることも、個別の値として指定することもできる。

jvmArgs "Iterator"
jvmArgs "value1, value2, ..."

Java 仮想マシンに渡す引数を指定する。

workingDir "text"

作業ディレクトリを指定する。 プロジェクトディレクトリからの相対パスで指定する。

JavaExec を使った例は次のとおりである。

task appRun(type: JavaExec) {
    group 'devkuma'
    description 'exec App class.'
    main 'App'
    classpath sourceSets.main.runtimeClasspath
     
    doFirst {
        println()
        println('---------- Start ----------')
        println()
    }
    doLast {
        println()
        println('----------- end -----------')
        println()
    }
}

これは App クラスを実行する appRun タスクである。 gradle appRun を実行すると次のように表示される。

$ gradle appRun

> Task :appRun

---------- Start ----------

Hello world.

----------- end -----------

Gradle の実行結果は出力が多く、実際の結果が分かりにくいことがある。 そのため doFirstdoLast で区切りを出力し、実行内容を見やすくしている。 必要な JavaExec 設定は次の 2 つである。

main 'App'
classpath sourceSets.main.runtimeClasspath

この 2 つは有効なデフォルト値がないため、省略しない。

Exec を使ってコマンドを実行する

開発中の Java プログラムではなく、別のプログラムを実行したい場合がある。 その場合に使用するのが Exec クラスである。

Exec はコマンドラインでコマンドを実行する機能を持ち、実行に関する設定メソッドを提供する。

commandLine "command", "argument"...

実行するコマンドを指定する。 最初の引数にコマンドを書き、その後にオプションなどを指定する。

workingDir "text"

作業ディレクトリを指定する。

args "Iterator"
args "value1, value2, ..."

コマンドに渡す引数を指定する。

Windows で実行する

次の例は Windows を前提にしている。 プロジェクトフォルダに java.bat というファイルを作成する。

java.exe -version

そして次のタスクを定義する。

task javaVer(type:Exec) {
    group 'devkuma'
    description 'print java version.'
    workingDir '.'
    commandLine 'cmd'
    args '/c', 'java.bat'
    doFirst {
        println()
        println('***** Java Version *****')
    }
}

gradle javaVer を実行する。 表示はインストールされている JDK によって変わるが、おおむね次のようになる。

> Task :javaVer

***** Java Version *****

C:\dev\GradleApp>java.exe -version
java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)

この設定では cmd /c java.bat が実行され、java.bat に書かれた java.exe -version が実行される。

macOS と Linux 系で実行する

Windows 以外では次のように書ける。

task javaVer(type:Exec) {
    group 'devkuma'
    description 'print java version.'
    workingDir '.'
    commandLine './javaver'
    doFirst {
        println()
        println('***** Java Version *****')
    }
}

javaver ファイルを作成して次の内容を保存し、chmod で実行権限を付与する。

java -version

出力は Windows の例と同様である。

Copy を使ってファイルをコピーする

プログラム実行以外にも、覚えておくと便利なファイル関連クラスがある。

Copy クラス

Copy クラスはファイルコピー機能を提供する。 主なメソッドは次のとおりである。

from "source path"

コピー元のファイルやディレクトリのパスを指定する。

into "destination path"

コピー先のパスを指定する。

include "pattern", ...

コピー対象に含めるファイルを Ant 形式のパターンで指定する。

exclude "pattern", ...

コピー対象から除外するファイルを Ant 形式のパターンで指定する。

簡単な例は次のとおりである。

task copyJava(type: Copy) {
    group 'devkuma'
    description 'backup java files.'
    from 'src/main/java'
    into '../java_backup'
 }

これは main 配下の java ディレクトリを、プロジェクトフォルダの外側にある java_backup にコピーする。 gradle copyJava で実行できる。

Delete クラス

Delete クラスはファイルやディレクトリを削除する。

delete "file", ...

削除対象のファイルをパスで指定する。