スポンサーリンク

【Gradle】簡単なまとめとトラブルシュート

スポンサーリンク

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でよいのでは?)

Understanding Tasks

また,この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'       
}
Task (Gradle API 8.9)

初めの方は,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 the PluginAware.apply() method that can be used to apply a plugin directly to a Project object or similar. A key difference is that plugins applied via the plugins {} 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. The plugins {} block is a new, incubating, Gradle feature that will evolve to offer benefits over the apply() approach.

PluginDependenciesSpec - Gradle DSL Version 2.2-20140924021627+0000

pluginsの方が新しくメリットが多いようです.基本的にはpluginsを使用しましょう.

タイトルとURLをコピーしました