variable $it in Gradle task : Reference : Gradle in Action book - gradle

Whilke going through the book I came across this line
Groovy automatically exposes an implicit variable named it to indicate
the loop iteration index.
from the Gradle in Action book, chapter 2 Listing 2.1
The line says that $it represents loop iteration index. However when I try add
$it to println statement of task yayGradle0/1/2, it prints out the task and not the index. I'm confused about this behavior. Please guide.
3.times{
task "yayGradle$it" <<{
println 'Gradle rocks--->>>'+"$it"
}
}
The output after running task yayGradle0 is :
Gradle rocks--->>>task ':yayGradle0'

You are using the it variable in a different context than presented in the book. In your case you are working in the context of the task's Closure. Therefore, it represents a different object, a org.gradle.api.Task instance. It would be helpful to reference Closure delegation strategies. Please also see Appendix B in the book.

(edit after rereading)
it is the index in loop.
From groovy shell
3.times {
println "${it}"
}
0
1
2
In your code there is another closure, it becomes variable to that closure (which is task name)
Following example uses explicit variable at top level.
3.times{ counter->
task "hello${counter}" <<{
println 'Gradle rocks--->>>'+" ${it} ${counter}"
}
}
$gradle hello2 gets following output.
Task :hello2
Gradle rocks--->>> task ':hello2' 2
references
novice
groovy closures

Related

Is it possible for a Gradle subsiduary script to use a task in a main script?

I've got a main build.gradle script which employs tasks in a secondary script.
If possible I'd like a task in the secondary script to depend upon one in the primary one. But it seems that's not possible. Or is it?
In a.gradle:
...
apply from: 'b.gradle'
task inA {
}
...
In b.gradle:
task inB {
dependsOn inA
}
This give:
A problem occurred evaluating script.
Could not find property 'inA' on task ':app:inB'.
Is this possible to do?
Build scripts are evaluated sequentially (top to bottom) so in this case task 'inA' doesn't exist yet when 'b.gradle' is applied. Simple fix is to use strings instead of symbols when referring to a task.
task inB {
dependsOn 'inA'
}

Passing property to custom gradle task from command prompt

I wrote a custom gradle task class (say PrintNameTask) that accepts some input parameter (say name).
Then if I define a printName task of type PrintNameTask like below:
task printName(type: PrintNameTask) {
name = project.name
}
and invoke it from command prompt like below I can see the passed name printed out
$gradle printName -Pname=myName
myName
However if I invoke any other task like clean or build the build fails because there is no property called name passed. This is fair enough as my printName is a configure closure and is evaluated all the times.
To address this I tried to change the configure closure into a task action closure like below:
task printName(type: PrintNameTask) << {
// What should I put on here?
name = ???
// or
name ???
}
But it was no way to make it work. I tried project.name, getProperty("name") and a few more other combinations but nothing worked. All I get back is:
* What went wrong:
A problem was found with the configuration of task ':printName'.
No value has been specified for property 'name'.
This kind of requirement looks to me quite basic and it is a bit frustrating that tons of books and documentation are published but they only shows trivial examples. Maybe is just me but at the point of asking this question my initial gradle enthusiasm is more than half gone. Anyway thank you in advance for your inputs.
Configure the task in the following way:
task printName(type: PrintNameTask) {
name = project.hasProperty('name') ? project.name : '' // or null
}
Since this closure is evaluated at configuration phase it's executed every time the script is processed. You just need to check if the property is present.

Gradle Task Configuration vs Task Execution

What is the difference between the code below?
task A {
println 'configuration'
}
task B << {
println 'action'
}
I believe it has something to do with evaluation.
ie task A is always evaluated
whereas task B is only evaluated when its executed
Indeed: the 'println' statement of your task A will be executed during 'configuration' phase, whereas the 'println' statement of taks B will only be executed during 'execution' phase (assuming task B is run, directly or indirectly via task dependencies)
For more info, checkout: http://www.gradle.org/docs/current/userguide/build_lifecycle.html. Section 56.2 has a nice example (also demonstrating the third phase, being the 'initialization' phase, BTW)
Note: the "<<" is a shorthand notation for "doLast"

Controlling Gradle task execution

In my build.gradle script, I have a lot of tasks, each depending on zero or more other tasks.
There are three 'main' tasks which can be called: moduleInstallation, backupFiles and restoreFiles.
Here's the question: I would like to be able to tell Gradle which tasks to execute and which don't need to execute. For example, when calling moduleInstallation, I want all depending tasks to execute (regardless of their UP-TO-DATE flag), but not the restore tasks. I've tried altering the phase in which the tasks get executed (e.g. config phase, execution phase,...) and a couple of other things, but all tasks just keep getting executed.
A solution I've thought of was just stating in the main tasks that, when this main task is called (f.e. moduleInstallation), we set the UP-TO-DATE flag of all non-related tasks to false, so they don't get executed. Is that possible?
EDIT: Here's an example:
When moduleInstallation is called (which depends on backupFiles), restoreFiles (which depends on restoreFromDate) is executed too.
First main action
task moduleInstallation << {
println "Hello from moduleInstallation"
}
task backupFiles {
doLast {
println "Hello from backupFiles"
}
}
Second main action
task restoreFiles {
println "Hello from restoreFiles"
}
task restoreFromDate {
println "Hello from restoreFromDate"
}
Dependencies:
moduleInstallation.dependsOn backupFiles
restoreFiles.dependsOn restoreFromDate
So when I type gradle moduleInstallation in the terminal, I get the following output:
Hello from restoreFromDate
Hello from restoreFiles
Hello from backupFiles
Hello from moduleInstallation
The second snippet has to use doLast (or its << shortcut) like the first snippet. Otherwise, the code is configuration code and will always be evaluated, no matter which tasks are eventually going to be executed. In other words, it's not the restoreFiles and restoreFromDate tasks that are being executed here (as one can tell from the bits of command line output that you don't show), but (only) their configuration code.
To better understand what's going on here (which is crucial for understanding Gradle), I recommend to study the Build Lifecycle chapter in the Gradle User Guide.

What is the difference between these task definition syntaxes in gradle?

A)
task build << {
description = "Build task."
ant.echo('build')
}
B)
task build {
description = "Build task."
ant.echo('build')
}
I notice that with type B, the code within the task seems to be executed when typing gradle -t - ant echoes out 'build' even when just listing all the various available tasks. The description is also actually displayed with type B. However, with type A no code is executed when listing out the available tasks, and the description is not displayed when executing gradle -t. The docs don't seem to go into the difference between these two syntaxes (that I've found), only that you can define a task either way.
The first syntax defines a task, and provides some code to be executed when the task executes. The second syntax defines a task, and provides some code to be executed straight away to configure the task. For example:
task build << { println 'this executes when build task is executed' }
task build { println 'this executes when the build script is executed' }
In fact, the first syntax is equivalent to:
task build { doLast { println 'this executes when build task is executed' } }
So, in your example above, for syntax A the description does not show up in gradle -t because the code which sets the description is not executed until the task executed, which does not happen when you run gradle -t.
For syntax B the code that does the ant.echo() is run for every invocation of gradle, including gradle -t
To provide both an action to execute and a description for the task you can do either of:
task build(description: 'some description') << { some code }
task build { description = 'some description'; doLast { some code } }

Resources