漠然と複雑な作業を処理するカスタム gradle プラグインを作成していますが、プロパティを使用してプラグインが適用するタスクの一部を構成しているときに、イライラする問題に遭遇しました。
apply plugin: myPlugin
//Provide properties for the applied plugin
myPluginProps {
message = "Hello"
}
//Define a task that uses my custom task directly
task thisTaskWorksFine(type: MyTask) {
input = myPluginProps.message
}
//Define a plugin that will apply a task of my custom type
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create('myPluginProps', MyPluginExtension)
project.task(type: MyTask, 'thisTaskWorksIncorrectly') {
input = project.myPluginProps.message
}
}
}
//The extension used by my custom plugin to get input
class MyPluginExtension {
def String message
}
//The task used by both the standard build section and the plugin
class MyTask extends DefaultTask {
def String input
@TaskAction
def action() {
println "You gave me this: ${input}"
}
}
このファイルを使用した結果は次のとおりです。
$ gradle thisTaskWorksFine thisTaskWorksIncorrectly
:thisTaskWorksFine
You gave me this: Hello
:thisTaskWorksIncorrectly
You gave me this: null
BUILD SUCCESSFUL
これは非常に予想外だと思います。私の考えでは、プラグインからタスクを適用して直接記述すると、同じ入力が与えられたときに同じ出力が得られるはずです。この場合、両方のタスクがmyPluginProps.message
入力として与えられますが、プラグインによって適用されるタスクは貪欲で、早い段階で null と評価されます。(適用フェーズ中?)
私が見つけた唯一の解決策は、次のようにプラグイン タスクの構成ブロックでクロージャーを使用することです。
//Define a plugin that will apply a task of my custom type
class MyPlugin implements Plugin<Project> {
void apply(Project project) {
project.extensions.create('myPluginProps', MyPluginExtension)
project.task(type: MyTask, 'thisTaskWorksIncorrectly') {
input = { project.myPluginProps.message }
}
}
}
これにより、貪欲な評価の問題はかなりうまく解決されますが、カスタム タスクを変更して、クロージャを予期して処理する必要があります。実行するのはそれほど難しくありませんが、プラグインに「責任がある」ため、閉鎖に対処するのはタスクの責任であるべきではないと思います。
ここで拡張機能を間違って使用していますか? それとも、それらは十分ではありませんか?公式のスタンスは、拡張機能を使用する必要があるようですが、拡張機能が必要なことを実行できる例をまだ見つけていません。クロージャーの使用を進めて、クロージャーの評価を行う一連のボイラープレート ゲッターと、クロージャーと通常の型を処理できるセッターを作成することはできますが、それは groovy の哲学、したがって gradle に非常に反しているように思えます。拡張機能を使って遅延評価を自動的に取得できる方法があればとてもうれしいです。