how to always run gradle task B after task A - gradle

Anyone knows how to get B to always run after A even if I only use 'gradle A' on the command line? My first thought was that I could use mustRunAfter, but that seems to require me to specify B on the command line.
task A << {
println 'A'
}
task B << {
println 'B'
}

The (only) way to do so (not counting hacks) is A finalizedBy B. Note that this will run B even if A failed.

You need to use dependsOn feature in Gradle task.
For ex: If you run "gradle ohohWorldTask", it'll always calls myHelloTask to echo "hello" first.
// Say hello
task myHelloTask() << {
println "hello"
}
// Say world
//task ohohWorldTask( dependsOn: [ myHelloTask ] ) << {
//or - using the above you can specify multiple tasks comma separated within [ aTask, bTask, cTask ]
task ohohWorldTask( dependsOn: myHelloTask ) << {
println "-- World!"
}

Related

Gradle Plugin: Task C should run if Task A or Task B:

I am creating Custom Plugin tasks and got into a situation where I need some help.
I create 3 tasks. Task A, B, C in gradle.
Task C should get executed only if A or B got success.
Note that A and B are 2 separate tasks and are not related.
class A extends DefaultTask { }
class B extends DefaultTask { }
class C extends DefaultTask { }
If I try C.dependsOn(A); C.dependsOn(B);, then I think C is dependent on both A and B (not A or B). Is there any way to specify A or B condition here.
Gradle offers four methods (and related containers) for task dependencies and ordering:
Style: t1.<method>(t2)
dependsOn - Ensures, that t2 is executed if and before t1 is executed.
finalizedBy - Ensures, that t2 is executed if and after t2 is executed.
mustRunAfter - Ensures, that if both t2 and t1 are executed (caused by other triggers), t1 is executed after t2.
shouldRunAfter - Basically the same as mustRunAfter, but may be ignored for special cases (check the docs).
Your requirement is special and won't be solved by a simple method like above. If I understand your question right, you want to ensure that task C gets executed after tasks A and B, but only if it will be executed anyhow (and not trigger it automatically). You can use mustRunAfter for this first part of the requirement. However, you also want to ensure that either task A or task B was executed before. I suggest to use the onlyIf method to skip task execution for task C, if neither A or B were executed before. Example:
task A { }
task B { }
task C {
mustRunAfter A, B
onlyIf { A.state.executed || B.state.executed }
}
You can add multiple dependencies.
task B << {
println 'Hello from B'
}
task C << {
println 'Hello from C'
}
task D(dependsOn: ['B', 'C'] << {
println 'Hello from D'
}
The output is:
> gradle -q D
Hello from B
Hello from C
Hello from D
I think the answer to the PM question in gradle 7.x+ would be something like:
A.finalizedBy('C')
B.finalizedBy('C')
tasks.register('C'){
onlyIf{
(gradle.taskGraph.hasTask('A') &&
tasks.A.getState().getExecuted() &&
tasks.A.getState().getFailure() == null)
||
(gradle.taskGraph.hasTask('B') &&
tasks.B.getState().getExecuted() &&
tasks.B.getState().getFailure() == null)
}
}
With this condition you can't execute C by itself as in 'gradle C'.
Another option could be a Task listener:
A.finalizedBy('C')
B.finalizedBy('C')
gradle.taskGraph.afterTask { Task task, TaskState taskState ->
if (['A','B'].contains(task.getName())){
if(taskState.getFailure() == null){
project.tasks.getByName('C').setEnabled(true)
}else{
project.tasks.getByName('C').setEnabled(false)
}
}
}
With this option it is possible to just execute C with 'gradle C'.
Yes another option could be to declare inputs to C and then in a task listener change C's input as necessary to influence its upToDate check.
Then A and B are executed directly or by some other trigger. if both A and B are in the tasks graph then C will probably be executed twice. if A and B are executed in parallel the result IMO is unpredictable.

Gradle: need help to understand

Have in build.gradle
task hello {
doLast {
println 'Hello World!'
}
}
task count {
println "one"
doLast{
4.times {print "$it "}
}
println "two"
doFirst{
2.times {println "$it - 1 "}
}
3.times {println( "$it -3")}
}
task intro(dependsOn: hello){
doLast{
println("I'm Gradle!")
}
}
run in shell
gradle intro
and get
one
two
0 -3
1 -3
2 -3
:hello
Hello World!
:intro
I'm Gradle!
BUILD SUCCESSFUL
but it's not correct!!!
the correct output is
:hello
Hello World!
:intro
I'm Gradle!
BUILD SUCCESSFUL
What did I do wrong?
ps
adding details to because there is too much code here :(
adding details to because there is too much code here :(
adding details to because there is too much code here :(
adding details to because there is too much code here :(
Why do you think it's wrong? Probably it is absolutely correct. This is all due to configuration of the build. Read about it in the official user guide.
There are a number of phases take place during the build. One of them is configuration phase. All the output you don't expect to see - is the configuration's output. When you do something in task's closure, it's executed at the configuration of your build, untill you place it into the doLast or doFirst closure to run at the execution phase (or task's closure is declared with << that's the same as doLast).
Note that configuration is executed for all tasks, no matter if they will be executed or not. That is the reason of your unexpected output - it's just done as a part of your build configuration, though they are declared within some task.

What is the meaning of << in gradle task definition

What is the difference between these two tasks. Only task with << in its definition is shown in the output of ./gradlew tasks.
task greet(type: GreetingToFileTask) {
destination = { project.greetingFile }
}
task sayGreeting(dependsOn: greet) << {
println file(greetingFile).text
}
The lines above are from gradle documentation Here
The << is a shortcut to the toLast configuration item of a task definition. I.e. the following two declarations are equivalent:
task hello << {
println 'Hello world!'
}
and:
task hello {
doLast {
println 'Hello world!'
}
}
(example taken from Gradle documentation here).
Now, in the first code snippet you just define a task and configuring its destination property. However, the task will only be executed if needed.
In the second code snippet, however, you are actually defining an action that will always be executed during the configuration phase, regardless of the tasks targeted for execution (cite from here):
A task has both configuration and actions. When using the <<, you are
simply using a shortcut to define an action. Code defined in the
configuration section of your task will get executed during the
configuration phase of the build regardless of what task was targeted.

Gradle executes all tasks?

I have a very simple build script like so
task hello{
println("hello World")
}
task bye {
println("bye")
}
On the command line I run
gradle hello and I get the following output:
hello World
bye
:hello UP-TO-DATE
Why is it executing the task "bye" (I'm assuming it gets executed since "bye" gets printed)? Thanks.
It's a common pitfall:
task hello {
println("Any code in here is about *configuring* the\
task. By default, all tasks always get configured.")
doLast {
println("Any code in here is about *executing* the task.\
This code only gets run if and when Gradle decides to execute the task.")
}
}
The distinction between configuration phase and execution phase is probably the single most important concept to understand in Gradle. It can be confusing at first, and may go away in the future. A kind of analogue in the Ant/Maven world is that these tools first parse XML build scripts and build an object model (perhaps resolving some properties along the way), and only then execute the build.
Adding to Peter answer, If you want to execute all task , you can specify the defaultTasks list.
defaultTasks 'clean', 'run'
task clean {
doLast {
println 'Default Cleaning!'
}
}
task run {
doLast {
println 'Default Running!'
}
}
task other {
doLast {
println "I'm not a default task!"
}
}
Output
Output of gradle -q
> gradle -q
Default Cleaning!
Default Running!
More details can be found here
https://docs.gradle.org/current/userguide/tutorial_using_tasks.html

gradle task build already exists issue

I am getting the error
Cannot add task ':webserver:build' as a task with that name already exists.
The weird thing is my hello task is fine but my build task is not AND YES, I am trying to override the Java plugin's build task.
Master build.gradle file:
allprojects {
apply plugin: 'java'
apply plugin: 'eclipse'
task hello << { task -> println "I'm $task.project.name" }
task build << { task -> println "I'm building now" }
}
subprojects {
hello << {println "- I depend on stserver"}
build << { println "source sets=$sourceSets.main.java.srcDirs" }
}
My child webserver build.gradle file:
sourceSets.main{
java.srcDirs = ['app']
}
build << { println "source sets=$sourceSets.main.java.srcDirs" }
hello << {println "- Do something specific xxxx"}
What is the deal here, is overriding build special or something? Overriding my own hello task worked fine and I thought overriding build would be just as simple?
You aren't overriding the hello task, you are just adding more task actions. You can override a task with task foo(overwrite: true). I haven't come across a good reason to override the build task; there are probably better ways to achieve what you want.
What is the deal here, overriding build is special or something. Overriding my own hello task worked fine and I thought overriding build would be just as simple?
The reason the behaviour seems different is because build task already exists and hello does not (and not because build is special).
In gradle you cannot do this:
task hello << { print "hello" }
task hello << { print "hello again" }
This will fail with the familiar error: "Cannot add task ':hello' as a task with that name already exists.".
Since build task already exists, it's illegal to have a second task build << { ... }. However, it will work for hello task, because it does not exist, and therefore task hello << { ... } is legal, as it's the first declaration of hello task.
If you replace your task build << { ... } with build << { ... }, which just adds more behaviour to an existing task, it will "compile" fine.

Resources