Hey everyone! I’m working on a Gradle plugin that ...
# plugin-development
f
Hey everyone! I’m working on a Gradle plugin that registers some tasks using
project.tasks.register
, and it does it inside the
onVariants
lambda provided by AGP. One of these tasks has to search for another task by name, access its outputs, and map them as an input. Something like this:
Copy code
val targetTaskProvider = project.tasks.named("targetTask") // some task created by another plugin

val myTask = project.tasks.register(...) { task ->
    task.input.set(targetTaskProvider.flatMap { // do some processing on task outputs }
}
When using
project.tasks.named
, if the task I’m looking for has not been registered yet, it will fail to find it. I found that wrapping everything in
project.afterEvaluate
will ensure that the task is already there, but it doesn’t seem optimal. Is there any other alternative?
should I be wrapping the targetTaskProvider in a
project.provider {}
so it’s not searched for immediately?
v
Both options you mentioned are bad actually
m
Usually you have better AGP APIs that expose lazy properties. This repo has lots of examples
v
afterEvaluate
does not ensure anyhting, the main earnings for using it are timing problems, ordering problems and race conditions
If you wrap it in
provider { ... }
you loose task dependencies
If you require tasks from another plugin, there are usually two ways. If your plugin cannot work without that other plugin, apply that other plugin before trying to access stuff it added.
If your plugin can also work without that plugin but wants to integrate with it when it actually is applied, use
pluginManager.withPlugin("...") { ... }
to react to that other plugin being applied.
m
finalizeDsl{}
might also work
v
Unless that other plugin does bad things like itself using
afterEvaluate
to register that task, that is usually the way to go.
Of course Android is always special, so maybe better listen to Martin, I'm not doing Android stuff. 😄
m
Yea Android is always special ^^
@Francisco Prieto what task it is you need access to? IIRC, AGP tries to give you proper APIs so you don't look up the task by name directly. If not, it might be worth filing a feature request.
f
Thanks for your responses! I don’t really have access to the other plugin, it’s React Native. The tasks I need are
bundle[Variant]JsAndAssets
or
createBundle[Variant]JsAndAssets
, depending on the RN version, and I need to get the
index.android.bundle
file from its output
m
That even sounds like a R/N task, not even AGP?
f
The RN plugin itself isn’t really configuration-cache compliant, so things will probably work anyway, but I did want to learn how it should be done 😅
m
v
Is it?
m
But at the end of the day, if the R/N plugin and AGP use
afterEvaluate{}
a lot themselves, you might have to rely on it as well, which is not great but 🤷
v
Isn't it different name, same problems?
f
is there a
tasks.named
alternative that doesn’t eagerly look for the task?
m
It's the "AGP-only"
afterEvaluate{}
v
Yeah, so still, different name, same problems :-)
Main earning is timing problems, ordering problems, and race conditions.
m
is there a
tasks.named
alternative that doesn’t eagerly look for the task?
Copy code
tasks.configureEach {
  if (name == "foo"){
    // do your stuff here
  }
}
👎 1
Yeah, so still, different name, same problems 🙂
Kindof at least you have only one plugin to worry about
v
Nah, you have to worry about every plugin and every build script that also calls it
👍 1
m
True
v
Your snippet I thumbs-downed is not really helpful, is it? He does not use
named
to configure the found task, but to depend on the found task
Otherwise I would use
tasks.named { }.configureEach { }
or
tasks.matching { }.configureEach { }
. But neither is helpful for depending without breaking task-configuration avoidance
m
tasks.all{}
😅
This is the wild west
😂 1
v
o_O
🔫
m
😄
Propably no good solution unless R/N and/or AGP provide the "good" API
f
Oh, no problem. Thanks for your help anyway! We’re trying to fetch the output of that task to be smart about where the index bundle file is going to be. Maybe we should just hardcode it. I doubt RN changes that file location often.