Jakub Chrzanowski
03/18/2024, 7:25 PMproject.tasks.named<Type>("taskName")
, like:
project.tasks.register("myTask") {
val anotherTaskProvider = project.tasks.named<Type>("anotherTask")
foo.convention(anotherTaskProvider.map { ... })
dependsOn(anotherTaskProvider)
}
This works only when anotherTask
is defined before myTask
. Is there a way to retrieve a named task provider even if it doesn’t exist?Adam
03/18/2024, 7:33 PMdependsOn(tasks.matching { it.name == "anotherTask" })
Jakub Chrzanowski
03/18/2024, 7:35 PMmatching
🙂Adam
03/18/2024, 7:43 PMVampire
03/19/2024, 1:24 PMtasks.matching
is a really bad idea here, as it totally breaks task configuration avoidance for each and every task if used like shown by Adam.
Only when combined with configureEach
, it does not break task configuration avoidance and is fine to use.
Exactly to solve this problem tasks.named { ... }
was introduced in latest version. Unfortunately, the implementation is totally broken which makes it behave exactly like matching
. But once that is fixed, it is the way to go if you have recent enough Gradle version.
To minimize the task-configuration breakage while using non-stringy API, you could do tasks.withType<Type>().matching { ... }
, so that it is only broken for tasks of type Type
.
A probably better way in this situation would indeed be to use string-y API:
project.tasks.register("myTask") {
val anotherTask = project.tasks.withType<Type>().matching { it.name == "anotherTask" }.configureEach {
foo.convention(it.map { ... })
}
dependsOn("anotherTask")
}
But actually, all this is just work-around, even with tasks.named { ... }
. The real question is, why do you need an explicit dependsOn
? Every explicit dependsOn
that does not have a lifecycle task on the left-hand side is a code smell. If you properly wire inputs to outputs, you get the necessary task dependencies automatically. There might be situations where you have old tasks that are not property-enabled where you need it, but in your case, you use the task provider to configure a Property
, so as long as you do not break the chain with something like flatMap
to something that is not an output property, you get the task dependency automatically when necessary.
For example if someone sets a custom value for foo
, with your explicit depending, "anotherTask" would still be executed while it is not needed anymore. If it is still needed even though foo
has a different value, then the question is why, and whether then not some other wiring is missing.Jakub Chrzanowski
04/04/2024, 8:29 AMdependsOn
isn’t necessary, indeed. I was unaware that dependencies are set even if you use the task’s output.Jakub Chrzanowski
04/04/2024, 8:30 AM.matching
did the job, thanks!Jakub Chrzanowski
04/04/2024, 8:34 AMinline fun <reified T : Task> Project.resolveTask(name: String) = provider {
tasks.withType<T>().matching { it.name == name }.single()
}
val nameTaskProvider = project.resolveTask<Type>("name")
Vampire
04/04/2024, 8:58 AMsingle()
you make it eager and break task-configuration avoidance.
So when using that snippet, you still break task-configuration avoidance for all tasks of type T
that are already registered and also do not get the task if it is not registered already.
If that construct works in your case, you should just use tasks.named<Type>("name")
which has the same behavior that it only works if the task is already registered while not breaking task-configuration avoidance even for that single task.Jakub Chrzanowski
04/04/2024, 9:01 AMtasks.named()
Jakub Chrzanowski
04/04/2024, 9:02 AMinline fun <reified T : Task> Project.resolveTask(name: String) = provider {
tasks.named<T>(name).get()
}
🥲Vampire
04/04/2024, 9:04 AMprovider { ... }
Vampire
04/04/2024, 9:06 AMnameTaskProvider
?Vampire
04/04/2024, 9:08 AMJakub Chrzanowski
04/04/2024, 9:09 AMnameTaskProvider
to feed the other task with produced data, simple case.Jakub Chrzanowski
04/04/2024, 9:09 AMval patchPluginXmlTaskProvider = project.resolveTask<PatchPluginXmlTask>(Tasks.PATCH_PLUGIN_XML)
pluginXml.convention(patchPluginXmlTaskProvider.flatMap { it.outputFile })
Jakub Chrzanowski
04/04/2024, 9:11 AMproject.tasks.named<Type>("anotherTask")
but the anotherTask
gets registered after the one I currently configure.Vampire
04/04/2024, 9:18 AMVampire
04/04/2024, 9:19 AMJakub Chrzanowski
04/04/2024, 9:19 AMJakub Chrzanowski
04/04/2024, 9:20 AM