はじめに
本記事では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という位置づけでない以上、やはり都合が悪い場合があり得ます。
ご利用の際は、以上の点に注意してください。
サンプルコード全量
//--------------------------------------
// 適当なタスクを定義しておく
//--------------------------------------
// タスク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を参考にしました。