LoginSignup
2
2

More than 5 years have passed since last update.

[gradle 3.5] タスクからタスク呼び出し(※executeを使用)

Last updated at Posted at 2017-06-13

はじめに

 本記事ではAbstractTask.execute()を利用してスクリプト内でタスク実行をするコードを掲載しています。
 この方法は、gradleの正式APIではないと思われるため、予めご了承ください。
 詳しくは後述の「注意事項:executeの利用について」を参照。 

 また、gradleは色んなことができるので、この方法以外にもやり方はあると思います。
 あくまで数ある中の一例としてご覧ください。

こんなときに使う

  • depensOnではなく、task内のクロージャからtaskを制御したい

  • 複数のtaskを制御したい(エラー処理や、スキップ処理を自由に組み替えたい)

 筆者の場合、gradleを使ってCI的なビルドスクリプトを作成したかった。
 例えば、ソースのビルドに失敗したらエラーだけど、静的解析ツールの失敗は継続する、みたいなイメージ。

タスクからタスクを呼ぶスクリプト

依存先を含めてタスクを実行する関数(クロージャ)

// タスク呼び出し関数を定義
Closure callTask
callTask = {Task t ->
    t.taskDependencies.getDependencies().each { callTask it }
    if (!t.didWork) {
        println ":$t.name"
        t.execute()
    }
}

// 関数を利用する
task myTask {
    callTask タスク
}
コマンド実行すると、依存先を含んだ「タスク」が実行される
gradlew myTask

動作環境

Version: Gradle 3.5
Build time: 2017-04-10 13:37:25 UTC
Groovy: 2.4.10
Ant: Apache Ant(TM) version 1.9.6 compiled on June 29 2015
JVM: 1.8.0_111 (Oracle Corporation 25.111-b14)
OS: Windows 10 10.0 x86

注意事項:executeの利用について

 execute()はorg.gradle.api.internal.AbstractTaskクラスに実装されているprotectedメソッドです。
 internalパッケージのprotectedメソッドということなので、推奨されている使い方ではないと思われます。
 ググってみると、非公式だし「使うべきではないよ」と語っている記事もいくつか見つけました。

 そのため、当初はexecute()を使わずにTaskの実行をしようと思っていたのですが、調査不足のためか他に方法が見つからなかったので割り切りました。
 (よりよい方法が見つかった場合、記載内容を更新したいと思います。)

 何かの実験や自作アプリなんかで使用する分には特に問題ないと思いますが、
 公式APIという位置づけでない以上、やはり都合が悪い場合があり得ます。
 ご利用の際は、以上の点に注意してください。

サンプルコード全量

build.gradle
//--------------------------------------
// 適当なタスクを定義しておく
//--------------------------------------

// タスク1:依存先なし
task myTask1 {
    doLast {
        println 'task1 called.'
    }
}

// タスク2:依存先 - タスク1
task myTask2(dependsOn: 'myTask1') {
    doLast {
        println 'task2 called.'
    }
}

// タスク3:依存先 - タスク2
task myTask3(dependsOn: 'myTask2') {
    doLast {
        println 'task3 called.'
    }
}

// タスク4:依存先 - タスク3、タスク2
task myTask4(dependsOn: ['myTask3', 'myTask2']) {
    doLast {
        println 'task4 called.'
    }
}

//--------------------------------------
// 本題:タスクを再帰呼び出しする関数
//--------------------------------------
Closure callTask
callTask = {Task t ->
    t.taskDependencies.getDependencies().each { callTask it }
    if (!t.didWork) {
        println ":$t.name"
        t.execute()
    }
}

//--------------------------------------
// コマンドから呼び出すタスク
//--------------------------------------
task myTask {
    doLast {
        println 'sequential execution of tasks.'
        callTask myTask4
    }
}

実行結果

myTask4をコマンドラインから呼び出した場合

> gradlew myTask4
:myTask1
task1 called.
:myTask2
task2 called.
:myTask3
task3 called.
:myTask4
task4 called.

BUILD SUCCESSFUL

Total time: 1.751 secs

myTaskをコマンドラインから呼び出した場合

> gradlew myTask
:myTask
sequential execution of tasks.
:myTask1
task1 called.
:myTask2
task2 called.
:myTask3
task3 called.
:myTask4
task4 called.

BUILD SUCCESSFUL

Total time: 1.76 secs

おわりに

 筆者はgradleもgroovyもあまり経験がないです。
 変なところがあれば是非ご指摘ください。

参考文献

 Gradle 日本語ドキュメント 
 版数が古いようですが、ここから日本語のユーザーガイドが閲覧できます。

 Gradle API 3.5
 javadocは主に3.5を参考にしました。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2