How can I use a variable value from a project inside of a Exec task in gradle? - gradle

I am trying to write an exec task in gradle that would use a variable set on the project.
Something like so:
task upload(type: Exec) {
executable "echo"
args version
}
This always gives me "unspecified"
If I do a task like this
task upload << {
println version
}
It will print the value of the version variable
How can I use the value of version inside an Exec task ?

Thanks for your help Mark Vieira
I found that writing my own task that calls the exec task works the way I need it to.
Like so
task upload << {
exec {
executable "echo"
args version
}
}

Related

Gradle doLast, doFirst behavior in copy task

The
build.gradle
task hello (type: Copy) {
doLast {
println "print from within"
}
println "print from outside"
}
when run
gradle -q hello
the doLast{} closure is not even touched. change doLast to doFirst, I get the same result:
D:\>gradle -q hello
print from outside
without the doLast or doFirst:
task hello (type: Copy) {
//doLast{
println "print from within"
//}
println "print from outside"
}
it works fine:
D:\>gradle -q hello
print from within
print from outside
This seems happening only with tasks of type Copy. can you please help clarifying? I am using gradle 2.4.
I thought it would be helpful for the people who come to this place on the same question. Though the above explanation is conceptually making sense. There is no proper solution mentioned in the answer. Here is the solution on how i achieved Copy task with doLast execution.
task hello () {
doLast{
copy {
println "print from within"
}
}
println "print from outside"
}
This would provide the execution of copy task along with doLast.
$ gradle -q hello
print from outside
print from within
Hope this is useful.
If you run the task without -q switch you'll notice that the task is already marked as UP-TO-DATE - which means that no actions (and you add an action via doLast) were executed.
Why is that? In this particular example, you have configured no inputs and outputs for the task. Copy tasks resolve it's being up-to-date base on the inputs and outputs and since none were configured Gradle assumes there's no need for it to be run.

How to make gradle copy task run on execution only

I have a gradle task for copying, like below:
task hello << {
println "hello"
}
task myCopy(type: Copy) {
println "copy"
from(file('srcDir'))
into(buildDir)
}
but "myCopy" task gets executed even when I execute "hello" like below:
gradle hello
Now I understand this is the intended behavior. I read thru the entire Gradle Task page here: https://docs.gradle.org/current/userguide/more_about_tasks.html . But I want to make "myCopy" task only execute when explicitly executed. In other words, I want to make it so that "myCopy" does not execute when I execute "hello", and only execute when I run the command:
gradle myCopy
Is there a way to do this? Thanks
It's not getting executed, but getting configured. Take a closer look, nothing get copied if you don't run your copy task. Configuration is happenning always and for all the tasks you have, in your case you are printing "copy" during the configuration. Move it into the doLast section to print it at the execution phase, as:
task myCopy(type: Copy) {
doLast {
println 'Copy'
}
from(file('srcDir'))
into(buildDir)
}
Note, that doLast closure is the same as a task closure with << sign and it is executed only if task executed at the execution phase.

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'
}

How do I force a reconfiguration of projects in Gradle?

I have a build.gradle file that calls some SVNKit stuff to svn export some directories that make up a Gradle multi-project.
I have a task dedicated to doing this that looks something like this:
task checkoutIntoDir() << {
mkdir 'dirForSvnProjects_2014_07_17_19_50' // timestamp not hard-coded ;)
// prompt for username/password
// run svn export which places projects in dirForSvnProjects_2014_07_17_19_50
}
with another GradleBuild task that depends on it:
task buildCheckedOutStuff(type: GradleBuild, dependsOn: checkoutIntoDir) {
dir = "dirForSvnProjects_2014_07_17_19_50/svnProjectIExported"
tasks = ['buildMyProj']
}
But it says task 'buildMyProj' not found in root project when it gets there. Now if I take out the task dependency checkoutIntoDir and run it on a directory that's there before I start the build, it works fine. I'm guessing I need to run some kind of "reconfiguration" to make the project aware of the new gradle project in dirForSvnProjects_2014_07_17_19_50?
I finally figured it out.
It was actually related to the way I was setting variables, not about Gradle.
I had a createDir task defined that set a variable that was defined (but not set) at the "root" level of the script. It looked something like this:
def myBuildDir
task createDir << {
def nowDate = String.format('%tY_%<tm_%<td_%<tH_%<tM',Calendar.instance)
myBuildDir= "_build_$nowDate"
mkdir myBuildDir
}
task checkoutIntoDir(dependsOn: createDir) << {
// prompt for username/password
// run svn export which places projects in myBuildDir
}
And as Perryn Fowler pointed out in the comments, any block that's not in a doLast (or the << shorthand)-type block will be run at configuration time when createDir was being run at runtime. Therefore the variable was not set for the buildCheckedOutStuff task.
So I just changed it to set the date at the root as well and it worked:
def nowDate = String.format('%tY_%<tm_%<td_%<tH_%<tM',Calendar.instance)
def eqipBuildDir = "_build_$nowDate"
task createDir << {
mkdir eqipBuildDir
}
That's what I get for leaving out pieces for brevity!

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