We have a clear approach to task declaration (#9, #10), but have not yet made decisions around how to configure existing tasks that have been created or declared elsewhere, e.g. by a plugin.
In Groovy, this is done as follows:
mytask {
// additional configuration goes here
}
Where mytask is a task already registered with the tasks container.
In Kotlin, we want:
tasks.mytask {
...
}
Consider aggregating all build/project specific extensions, conventions and tasks under a my namespace:
my.artifactory {
...
}
my.taskContributedByPlugin {
...
}
We should start thinking about moving tasks off the top level namespace, so that all task definition and configuration is done via the task container (using whatever API/DSL that the containers happen to provide).
Moving this to 1.0 M3, where we'll focus on polishing syntax and making things more declarative as a theme.
I'm not sure I know the best approach for configuring these kinds of objects, especially when retrieving existing Task objects.
At least with Gradle 3.0, this is what I have tried:
Closure by using closureOf call// Example previously created task
task("myTask")
project.tasks.findByPath("myTask").configure(closureOf<Task> {
description = "Test configuration"
})
The closureOf results in an error like this:
> Value is null
...
Caused by: java.lang.IllegalArgumentException: Value is null
at org.gradle.internal.metaobject.BeanDynamicObject.<init>(BeanDynamicObject.java:89)
at org.gradle.internal.metaobject.BeanDynamicObject.<init>(BeanDynamicObject.java:80)
at org.gradle.api.internal.DynamicObjectUtil.asDynamicObject(DynamicObjectUtil.java:30)
at org.gradle.internal.metaobject.ConfigureDelegate.<init>(ConfigureDelegate.java:35)
at org.gradle.util.ConfigureUtil.configureSelf(ConfigureUtil.java:136)
at org.gradle.api.internal.AbstractTask.configure(AbstractTask.java:519)
at Build_gradle.<init>(build.gradle.kts:100)
Which looks like it comes down from either a delegate or owner not being set.
Closure by using closureOf call and setting delegateYou could also create with closureOf, and then set the delegate.
// Example previously created task
task("myTask")
val myTask = project.tasks.getByName("myTask")
val configureMyTask = closureOf<Task> {
description = "My Task description"
}
configureMyTask.delegate = myTask
myTask.configure(configureMyTask)
But this results in:
> Value is null
...
Caused by: java.lang.IllegalArgumentException: Value is null
at org.gradle.internal.metaobject.BeanDynamicObject.<init>(BeanDynamicObject.java:89)
at org.gradle.internal.metaobject.BeanDynamicObject.<init>(BeanDynamicObject.java:80)
at org.gradle.api.internal.DynamicObjectUtil.asDynamicObject(DynamicObjectUtil.java:30)
at org.gradle.internal.metaobject.ConfigureDelegate.<init>(ConfigureDelegate.java:35)
at org.gradle.util.ConfigureUtil.configureSelf(ConfigureUtil.java:136)
at org.gradle.api.internal.AbstractTask.configure(AbstractTask.java:519)
at Build_gradle.<init>(build.gradle.kts:111)
KotlinClosureCreating an instance of KotlinClosure is not too friendly either:
This code leads to an unfortunate configuration:
// Example previously created task
task("myTask")
val myTask = project.tasks.getByName("myTask")
val configureMyTask = KotlinClosure<Task, Unit>({
description = "My Task Description"
}, owner = project, thisObject = myTask)
Results in:

It is not too bad to create and configure a KotlinClosure, but it does seem that you have to make sure that your return value is correctly typed, liked below I could be missing something with Kotlin, still new to it):
You need to return the V type, which in this case is Unit:
val configureMyTask = KotlinClosure<Task, Any>({
description = "My Task Description"
Unit
}, owner = project, thisObject = myTask)
You can then use it to configure the task:
myTask.configure(configureMyTask)
apply/with?// Example previously created task
task("myTask")
val myTask = project.tasks.getByName("myTask")
myTask.apply {
description = "My Task Description"
}
This _seems_ to work, but I'm not sure if there is any Gradle-Groovy AST magic that is supposed to happen during the _Configuration_ phase. It seems like the nicest of the above options for configuring Tasks, but doesn't help everywhere.
These are just my overall experience when trying to figure this out, hopefully it helps others until this feature is completed!
Similar problem exists with the artifacts closure.
As of #35, it is now possible to select and configure tasks with the following patterns:
Use the collection indexer.
task["jar"].dependsOn("someOtherTask")
Invoke the task container (works with any DomainObjectContainer).
tasks {
"jar" {
dependsOn("someOtherTask")
}
"clean"(Delete::class) { // specify type information so `delete` is available
delete("someOtherDir")
}
}
Declare a delegated property using the container as a delegate (works with any DomainObjectCollection).
val jar: Jar by tasks
jar.apply {
from(sourceSets["main"].allSource)
from(sourceSets["test"].allSource)
}
tasks["build"].dependsOn(jar)
Most helpful comment
I'm not sure I know the best approach for configuring these kinds of objects, especially when retrieving existing
Taskobjects.At least with Gradle 3.0, this is what I have tried:
Passing
Closureby usingclosureOfcallThe
closureOfresults in an error like this:Which looks like it comes down from either a
delegateorownernot being set.Instantiating
Closureby usingclosureOfcall and settingdelegateYou could also create with
closureOf, and then set thedelegate.But this results in:
Insantiating
KotlinClosureCreating an instance of
KotlinClosureis not too friendly either:This code leads to an unfortunate configuration:
Results in:
It is not too bad to create and configure a
KotlinClosure, but it does seem that you have to make sure that your return value is correctly typed, liked below I could be missing something with Kotlin, still new to it):You need to return the
Vtype, which in this case isUnit:You can then use it to configure the task:
Using
apply/with?This _seems_ to work, but I'm not sure if there is any Gradle-Groovy AST magic that is supposed to happen during the _Configuration_ phase. It seems like the nicest of the above options for configuring
Tasks, but doesn't help everywhere.These are just my overall experience when trying to figure this out, hopefully it helps others until this feature is completed!