gradle init script task not invoked : Gradle 2.14.1 - gradle

Please find below init.gradle file that has a common task for all my projects :-
rootProject { apply plugin: "eclipse" }
gradle.allprojects{
ext.commonTaskForEveryBuild = {
println "Common task for every build starts here..."
println "Common task for every build ends here..."
}
}
Also find below sample build.gradle for one of my project :-
apply plugin : 'java'
clean.doFirst{
println "Before invoking commonTaskForEveryBuild"
//This is invocation of commonTaskForEveryBuild
commonTaskForEveryBuild
println "After invoking commonTaskForEveryBuild"
}
Below are the logs for the execution of "gradle clean" task for the sample build.gradle file :-
:clean
Before invoking commonTaskForEveryBuild
After invoking
commonTaskForEveryBuild
:clean UP-TO-DATE
BUILD SUCCESSFUL
Total time: 3.722 secs
Looks like clean.doFirst is called, but it's not invoking definition of commonTaskForEveryBuild. Although, there is no compile time or runtime error.
Please suggest.

It's all right, that your task is not invoked, since your script doesn't attempt to do it and it's not even a task. You just getting your commonTaskForEveryBuild instance, but do nothing with it.
You may need to read the official user guide to find out, how to call one task from another. In short - this is usually done via task dependencies. You have to make your clean task depending on commonTaskForEveryBuild task to run it before the clean task execution. This could be done like so:
clean.dependsOn commonTaskForEveryBuild
Furthermore, it's all about tasks, but in your case ext.commonTaskForEveryBuild = {...} is not even a task, but just a closure and it must be executed as commonTaskForEveryBuild()

Related

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.

Why does gradle run every task in gradle.build

I'm very new to gradle and have a basic question.
When I add a custom task to my gradle.build file and call "gradlw build" or "gradle clean" or any other gradle command,
it automatically runs my custom task.
Is that how things work in gradle? run every task in the build file?
Is there way to run a task only when I want it manually?
task foo {
println 'hello'
}
That creates a task, and during the configuration of the task, it tells gradle to execute println 'hello'. Every task is configured at each build, because gradle needs to know what its configuration is to know if the task must be executed or not.
task foo << {
println 'hello'
}
That creates a task, and during the execution of the task, it tells gradle to execute println 'hello'. So the code will only be executed if you explicitly chose to run the task foo, or a task that depends on foo.
It's equivalent to
task foo {
doLast {
println 'hello'
}
}
You chose not to post your code, probably assuming that gradle was acting bizarrely, and that your code had nothing to do with the problem. So this is just a guess, but you probably used the first incorrect code rather than the second, correct one.

How do I make Gradle rerun a task when its dependencies are run?

Let's say that I have a task "main" that depends on another task "dependency." I would like "main" to be rerun any time its dependency (or its dependency's dependencies) is rebuilt because "main" relies on the artifacts produced by "dependency" (or the dependencies of "dependency").
A build.gradle file containing an example of what I'm dealing with is the following:
defaultTasks 'main'
task baseDependency {
outputs.file 'deps.out'
outputs.upToDateWhen { false }
doLast {
exec {
commandLine 'bash', '-c', 'echo hello world > deps.out'
}
}
}
task dependency(dependsOn: baseDependency)
task main(dependsOn: dependency) {
outputs.file 'main.out'
doLast {
exec {
commandLine 'bash', '-c', 'echo hello world > main.out'
}
}
}
Executing gradle the first time:
:baseDependency
:dependency
:main
BUILD SUCCESSFUL
Total time: 0.623 secs
Executing it a second time:
:baseDependency
:dependency
:main UP-TO-DATE
BUILD SUCCESSFUL
Total time: 0.709 secs
I would really love if "main" were not marked "UP-TO-DATE" if its dependencies had to be rebuilt. That seems essential. How do you make sure that's the case?
The standard way to specify dependency between tasks is via task's inputs and outputs. This can be any file, fileset or directory.
In your case you should modify main task and add inputs.file 'deps.out' to its definition.
Note that gradle has an optimization that may lead to unexpected behavior in a simplistic example that you provided.
Before a task is executed for the first time, Gradle takes a snapshot
of the inputs. This snapshot contains the set of input files and a
hash of the contents of each file. Gradle then executes the task. If
the task completes successfully, Gradle takes a snapshot of the
outputs. This snapshot contains the set of output files and a hash of
the contents of each file. Gradle persists both snapshots for the next
time the task is executed.
Each time after that, before the task is executed, Gradle takes a new
snapshot of the inputs and outputs. If the new snapshots are the same
as the previous snapshots, Gradle assumes that the outputs are up to
date and skips the task. If they are not the same, Gradle executes the
task. Gradle persists both snapshots for the next time the task is
executed.
So even if you specify correct inputs in a simple example where the same file is generated the dependent task will be marked as up to date on the second and subsequent runs.
If you do not want or cannot hardcode dependency on the file you can override upToDateWhen for dependent task and calculate the condition if the task is up to date based on dependencies of this task and their state like this:
outputs.upToDateWhen { task ->
task.taskDependencies.inject(true) { r, dep ->
r && dep.values.inject(true) { res, v ->
res && (!(v instanceof Task) || v?.state.getSkipped())
}
}
}
upToDateWhen should return true if this task should not be run at all (because its output are already up-to-date). And this is the case when no dependent task was run (the gradle documentation is a bit vague about this I must admit but getSkipped seems work as expected).

gradle 'build' task confusion

Hi I have multi project gradle setup
-root_project
|-sub_project1
|-sub_project2
|-sub_project3
All works great but one thing drives me crazy. In my build script:
defaultTasks 'build' <- this works just fine
task buildroom (description: 'This task is invoked by build room script, invokes default task plus publishes artifacts') {
// dependsOn('build') <-- this doesn't work
// alternative
dependsOn(":sub_project1:build")
dependsOn(":sub_project2:build")
when i call from command line 'gradlew' <- default task gets executed
when i call from command line 'gradlew tasks' <- task under 'all task runnable from root project' i see 'build'
but when i try to add dependsOn('build'), dependsOn(':build') or dependsOn(':root:build') it tells me
What went wrong: Execution failed for task ':tasks'.
Could not determine the dependencies of task ':buildroom'.
'base' plugin adds 'assemble', and 'clean' task but not build...
any tips?
The build task is declared by the java-base plugin. It's likely that your root project doesn't (directly or indirectly) apply java-base and therefore doesn't have a build task. This is why dependsOn("build"), which adds a task dependency on a task named build in the same project, eventually causes an error. defaultTasks is different in that:
It only accepts task names (whereas dependsOn also accepts task paths and Task objects).
Its task names get resolved to tasks as if the task names had been entered on the command line. In other words, all projects are searched for a task with the given name, and the set of matching tasks is returned.

Resources