Gradle調査
Gradleは基本を押さえても,なんだか使いこなすハードルが高い気がします.自分的なまとめとして書いておきます
Taskの基本
基本は公式サイトに書いてある通りなので不要だと思います.
task hello(dependsOn:[build]){ doFirst{ println "hello-doFirst" } doLast{ println "hello-doLast" println project.tasks //projectのtasksを表示可能 println tasks //上記と同様 println defaultTasks //defaultTasksを参照可能 } println project.tasks //ここに書いてあるのは読み込まれて全て実行される dependsOn build //ここで,dependsOnでタスク依存も追加可能 mustRunAfter build //buildより前に必ず実行される shouldRunAfter build //コンカレントなプロセス時にはbuildより前に実行されることが保証されない }
なお,以下の書き方はGradle5.0で廃止されました.
task hello << { println "hello-doFirst" }
mustRunAfterとshouldRunAfter
詳細はここに記載してあります.mustRunAfterはコンカレントに実行されても順序が保障されますが,shouldRunAfterはコンカレント時には順序は保証されません.厳密に順序を保証する必要があるときには,mustRunAfterを使用しましょう.(わざわざこういう指定をしたいということは,基本はmustRunAfterでよいのでは?)
また,この2つは依存性を追加するものではありません.二つのタスクを実行する際に順序が保障されるだけであって,一方のタスクだけを実行することは可能です.
finalizer
finalizerByを設定することでそのタスクを必ず最後に実行することが可能になります.これは実行タスクが途中でfailしたとしても実行されます.
taskX.configure { finalizedBy taskY }
dependsOn
3種類くらいdepensOnを記載する方法が用意されています.オーソドックスなものが下記の2種類です.
task hello(dependsOn: build){ dependsOn build //ここで,dependsOnでタスク依存も追加可能.どちらでもよい }
また,おそらくあまり使用されていない方法が以下です.
hello.configure { dependsOn bundleReleaseClasses }
dependsOnの注意点
dependsOnでインスタンスで指定できるのは,プラグインにすでに依存性が存在しているものに限ります.(理由については少し確証がありませんが,こういう理解です.)すなわち,otherに存在しているTask(groupが設定されていないtask)やそのほかにも依存性が存在していないTaskは直接参照することができません.
何が言いたいかというと,インスタンスとStringで渡す以下は異なるということです.
task hello(){ dependsOn build }
task hello(){ dependsOn 'build' }
初めの方は,project.tasks内に読み込まれたtaskの中からbuildを探索し,存在した場合にはbuildに依存させます.しかし,tasksに読み込まれていない場合は,以下のようなエラーが発生します.
groovy.lang.MissingPropertyException: Could not get unknown property 'bundleReleaseClasses' for task ':app:hello' of type org.gradle.api.DefaultTask
これはAndroidのGradle taskであるbundleReleaseClassesを利用したいときに滅茶苦茶つまったものです.単独では実行できるのになぜかdependencyを注入しようとするとこうなってしまうのでした・・.
理由は,dependsOnの解釈はInitialization時に読み込まれたtasks内から参照されるためです.Gradleは参照される可能性が低いtasksをわざわざ読み込むことはしません.すなわち,プラグインで指定されていないtasksはInitialization時には読み込まれません.それをインスタンスで渡しても一致するものがないというのはまぁ道理ですか・・
対策としては,hiddenフィールドであるtasksたちにアクセスする場合は,文字列でアクセスします.なので,基本的には2番目の方法で記載したほうがよいです.
また,afterEvaluate時に指定するという方法もありますが,こちらはあまり実用性はないのではないでしょうか.
afterEvaluate{ hello.configure { dependsOn bundleReleaseClasses } }
plugins と apply pluginの違い
公式ドキュメントに以下の記載があります.
The
plugins {}
block serves a similar purpose to thePluginAware.apply()
method that can be used to apply a plugin directly to aProject
object or similar. A key difference is that plugins applied via theplugins {}
block are conceptually applied to the script, and by extension the script target. At this time there is no observable practical difference between the two approaches with regard to the end result. Theplugins {}
block is a new, incubating, Gradle feature that will evolve to offer benefits over theapply()
approach.
pluginsの方が新しくメリットが多いようです.基本的にはpluginsを使用しましょう.