Understanding Gradle task dependency (dependsOn) - gradle

Two questions:
What is the gradle way to specify that 1 task is comprised of several other tasks?
It seems like gradle's taskName.execute() method does not honor the dependsOn relationships of taskName is this true and what is the work-around?
More background:
Right now I have a build script that has no plugins (not Java in other words). I want a task called tests that will run all my test tasks. I have 3 such tasks. Call them task1, task2, and task3.
I could say tests.dependsOn ['task1', 'task2', 'task3']
This is a bit wonky because the relationship seems to be tests.isComprisedOf ['task1', 'task2', 'task3']
I could say:
task tests << {
task1.execute()
task2.execute()
task3.execute()
}
but then task3, which itself depends on taskSetup, runs without running taskSetup. In other words the execute() call does not seem to honor gradle's dependencies resolution strategy.
One last small gripe (I really do love gradle by the way), is that it is hard to search on this topic because dependency means two different things in gradle: dependsOn style dependencies and library style dependencies.

Typically, you do not invoke task.execute().
You can specify that one task is comprised of other tasks in the following manner:
task task1 << {
println "Hello"
}
task task2 << {
println "World"
}
task task3(dependsOn: 'task3dependency') << {
println "QBert"
}
task task3dependency << {
println "MR"
}
task tests(dependsOn: ['task1', 'task2', 'task3'])
This outputs:
$ gradle tests
:task1
Hello
:task2
World
:task3dependency
MR
:task3
QBert
:tests
BUILD SUCCESSFUL
Keep in mind that the order in which your dependency tasks are run is not always guaranteed, but you can mitigate this by specifying the order task2.mustRunAfter task1. Usually though, the tasks are run in the order you would expect.
Also, you should read up on Gradle's Build Lifecycle. When you use the syntax task task1 << {...}, you are specifying a closure that is run in the execution phase of the task. Before execution is run, the configuration phase evaluates your build script and determines the tasks to be run and in what order. When you manually execute tasks, as in:
task tests << {
task1.execute()
task2.execute()
task3.execute()
}
you have bypassed Gradle's ability to evaluate the task dependencies of task3, hence it runs only task3.

Gradle's task model is "flat" and doesn't have a concept of aggregation. (It's important to note that TaskInternal#execute is an internal method, and must not be called from build scripts.) Aggregation is often simulated with a lifecycle task (a task with task dependencies but without any task actions):
task allTests {
dependsOn tasks.withType(Test)
}
Besides dependsOn, the following task relationships are supported: mustRunAfter, shouldRunAfter, and finalizedBy.

Related

Make gradle execute a finalizedBy task for each time it is set (multiple times)

I ran into the problem using the following situation:
To run different native testplugins in a row I dynamically create some tasks to prepare the environment appropriately for each plugin and then create a plugin_task for each testplugin that hosts the dependencies.
To start the tests on the device, the plugin_task is finalizedBy connectedAndroidTest.
So e.g. the call gradle plugin_name_1 works fine, it prepares the environment and starts the tests.
tasks.register("allTests"){}
name_list.each { test_name ->
def prepare_dir = tasks.register("${test_name}_Prepare_Dir") {...}
def copy_files = tasks.register("${test_name}_Copy_Files") {...}
def plugin_task = tasks.register(test_name){
dependsOn prepare_dir
dependsOn copy_files
finalizedBy connectedAndroidTest
}
allTests.configure {
dependsOn pluginTask
}
}
The problem now occurs, when I try run the allTests task:
gradle then correctly operates over all the dynamicly created tasks "prepare_dir", "copy_files" for each of the plugins, all of them are executed.
But the connectedAndroidTest will only be executed at the very end of allTests, so only runs once. But I need this task to be executed at every end of each plugin_task.
The behavior of gradle is correct, as it sees that all plugin_tasks shall be finalized by connectedAndroidTest and so puts it at the end of the graph.
Is there any possibility to make gradle execute this task multiple times?
Would be glad for help.
Wrapping the connectedAndroidTest task into dynamically created tasks and let the plugin_tasks depend on them, does not help. Also the parameter "rerun-tasks" has no effect.
That's not how Gradle works. Each task will execute either 1 or 0 times per Gradle invocation. If you want to execute the same task multiple times (with different task inputs) then you'll need multiple task instances, not one.

Is it possible to execute a task from within doLast?

I have the following:
task copyToLib(type: Copy) {
from configurations.runtime
into "$buildDir/output/lib"
doLast { copyOpcThirdParty() } // this doesnt get executed
}
task copyOpcThirdParty(type: Copy) {
from "$projectDir/libs/opc/thirdparty"
into "$buildDir/output/lib/thirdparty/"
}
How can I call copyOpcThirdParty from copyToLib.doLast?
I tried .execute(), tasks.copyOpcThirdParty, etc, nothing worked..
Is it unsupported?
In Gradle tasks are not executed directly. Instead you can register dependencies and Gradle then decides which tasks to execute in which order to achieve the execution of the tasks you specified (generally via command line). In older versions of Gradle you can call execute() directly on a task, but it should never be used.
When executing the tasks, the execution of one task must always be completely finished until another task can be executed. The execution of a task always covers running all doFirst closures, all internal task actions and all doLast closures.
For your specific example you can use the finalizedBy method. It tells Gradle that whenever a specific task runs, at some point after that another specific task also has to run:
copyToLib.finalizedBy copyOpcThirdParty

Gradle implicity run another task

I have two task
task Hello {
println 'Hello'
}
task World {
println 'Hello1'
}
If I run World task Hellowill run also. If I modify my tasks in this way
task Hello {
doLast {
println 'Hello'
}
}
task World {
println 'Hello1'
}
then task Hellowon't run. How do doLast{} or doFirst{} sections affect running tasks in gradle?
I can't find information in gradle docs about that. Thx.
The task Hello doesn't run. It's configured.
The code inside the curly braces is the code that configures the task. This code is always executed, whatever the task you tell gradle to run. It must run so that gradle knows what the task does, on which other task it depends, which other task it finalizes, etc.
Once the configuration phase has finished, the execution phase starts. And in that phase, the task that you asked to execute is executed/ In that phase, the code passed to doLast is being executed.
Here's the documentation.

Depend on multiple gradle tasks in multi project build

Currently I have task which starts Google Cloud server, runs tests and stops server. It is defined at root project:
buildscript {...}
allprojects {...}
task startServer (dependsOn: "backend:appengineStart") {}
task testPaid (dependsOn: "app:connectedPaidDebugAndroidTest") {}
task stopServer (dependsOn: "backend:appengineStop") {}
task GCEtesting {
dependsOn = ["startServer",
"testPaid",
"stopServer"]
group = 'custom'
description 'Starts GCE server, runs tests and stops server.'
testPaid.mustRunAfter 'startServer'
stopServer.mustRunAfter 'testPaid'
}
I tried multiple ways to write it something like this, short with only one task. I didn't get how to refer to task from another project and call mustRunAfter on it. This doesn't work (I also tried to refer from Project.tasks.getByPath, root.tasks, etc):
task GCEtesting {
dependsOn = ["backend:appengineStart",
"app:connectedPaidDebugAndroidTest",
"backend:appengineStop"]
group = 'custom'
description 'Starts GCE server, runs tests and stops server.'
"app:connectedPaidDebugAndroidTest".mustRunAfter "backend:appengineStart"
"backend:appengineStop".mustRunAfter "app:connectedPaidDebugAndroidTest"
}
Is it possible? What is correct syntax to make this work?
It looks like your problem is that you're treating dependsOn as meaning "invoke this task". It actually means "ensure the result of the depended on task is available before the dependent task starts". That's why your first solution didn't work: statements like testPaid.mustRunAfter only affect the actions of the testPaid task itself, not its dependencies.
Anyway, you can get the behaviour you want using dependsOn and finalizedBy, but they have to be declared in the build file of the app subproject.
app/build.gradle:
task connectedPaidDebugAndroidTest {
//
//...
//
dependsOn 'backend:appengineStart' // Ensure appengineStart is run at some point before this task
finalizedBy 'backend:appendginStop' // Ensure appengineStop is run at some point after this task
}
Then, you can run your tests simply with gradle app:connectedPaidDebugAndroidTest. If you really want to define a task in the root project to run the tests, then that's easy too:
build.gradle:
task GCEtesting {
dependsOn = "app:connectedPaidDebugAndroidTest"
}

Why can't see all task when use 'tasks' task in Gradle?

task startSession << {
chant()
}
def chant() {
ant.echo(message: 'Repeat after me...')
}
3.times {
task "yayGradle$it" << {
println 'Gradle rocks'
}
}
yayGradle0.dependsOn startSession
yayGradle2.dependsOn yayGradle1, yayGradle0
task groupTherapy(dependsOn: yayGradle2)
In my script I have startSession task, groupTherapy task and three dynamically generated tasks yayGradle0-3. When I am executing:
gradle tasks
Part of the output is:
Other tasks
-----------
groupTherapy
Where are the other tasks? If I execute the command above with parameter --all they are visible but not as indipendant tasks but like dependent on groupTherapy. Why Gradle doesn't show task startSession as separate task for example?
gradle tasks show tasks that no other task depends on, and tasks that have task.group set. The idea is that these are the tasks that are clearly meant to be executed directly, whereas the (often many) remaining tasks aren't. gradle tasks --all shows all tasks.

Resources