Gradle variable initialization - gradle

I have got a little problem with variables / ext properties in gradle.
In my root project i have this:
task foo {
println project.fooContent
}
in my child project fooContent is defined like this:
ext { fooContent='somethingProjectSpecific' }
When executing :childproject:foo it says variable is not set.
Do you know how to circumvent that problem?

This variable is not set since you try to print it at configuration phase. Try with an action (<<) it will be printed on execution phase:
task foo << {
println project.fooContent
}

Related

Is there a way to access variables from an imported gradle script?

I have a build.gradle file that's fairly long, and I'd like to break some of the logic up into smaller files to make the whole thing more maintainable. After moving some tasks into a new file, I found that none of the variables I had set in the parent script were available in the child script. Below is a pair of source files I reproduced this behavior with:
build.gradle:
apply from: 'repro.gradle'
def foo = "This is a variable"
tasks.register('printFromMainScript') {
println(foo)
}
repro.gradle:
tasks.register('printFromChildScript') {
println(foo)
}
In the above example, printFromMainScript works fine, but printFromChildScript fails. Is there a way to access foo from repro.gradle?
def foo creates a variable that exists only in the scope of build.gradle. Gradle documentation explains this more in detail.
There is ext block in Gradle which is meant for extra properties.
This should work in your case:
build.gradle:
apply from: 'repro.gradle'
ext {
foo = "This is a variable"
}
repro.gradle:
task printFromChildScript {
doLast {
println(project.foo)
}
}
Note: doLast block ensures that the println function is called only when the project is fully configured and printFromChildScript is actually executed. If you put println directly in task body then it will be executed during Gradle project configuration phase.

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.

How to configure lazily a Gradle task?

I'm trying to configure the following custom task:
task antecedeRelease(type: AntecedeReleaseTask) {
antecedeWithVersion = project.'antecede-with-version'
antecedeToVersion = project.'antecede-to-version'
}
The problem is that the properties antecede-with-version and antecede-to-version are to be set through the command line with a -P option. If they're not set and antecedeRelease isn't being called, that shouldn't be a cause for an error:
$ ./gradlew tasks
org.gradle.api.GradleScriptException: A problem occurred evaluating project ...
Caused by: groovy.lang.MissingPropertyException: Could not find property 'antecede-with-version' on project ...
I could conditionally define the antecedeRelease task such that it's defined only if those properties are defined but I'd like to keep the build.gradle file as clean as possible.
If you need the antecedeRelease task to run "lazily" as-in, at the end of the configuration phase, or at the beginning of the execution phase, your best bet is to use doFirst
task antecedeRelease(type: AntecedeReleaseTask) {
doFirst {
antecedeWithVersion = project.'antecede-with-version'
antecedeToVersion = project.'antecede-to-version'
}
}
One option might be to use Groovy's elvis operator like so:
task antecedeRelease(type: AntecedeReleaseTask) {
antecedeWithVersion = project.ext.get('antecede-with-version') ?: 'unused'
antecedeToVersion = project.ext.get('antecede-with-version') ?: 'unused'
}
If this fails still, you can consider project.ext.has('property') when setting the value.

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