Gradle Copy Task is always Up To Date - android

My gradle task looks like this
task xml_file_to_vs_build(type: Copy) {
outputs.upToDateWhen { false }
doLast {
outputs.upToDateWhen { false }
println("copying strings.xml");
from 'src/main/res/values'
into '../vso_build'
include 'strings.xml'
}
}
The task is always up to date . If I put the block in the configuration phase i.e. out of doLast, everything works fine. But then the code executed even if I execute gradlew Tasks which I do not want. What am I doing wrong ?

A Copy task only gets executed if it has something to copy. Telling it what to copy is part of configuring the task, and therefore needs to be done in the configuration phase, rather than the execution phase. These are very important concepts to understand, and you can read up on them in the Gradle User Guide or on the Gradle Forums.
doFirst and doLast blocks get executed in the execution phase, as part of executing the task. Both are too late to tell the task what to copy: doFirst gets executed immediately before the main task action (which in this case is the copying), but (shortly) after the skipped and up-to-date checks (which are based on the task's configuration). doLast gets executed after the main task action, and is therefore clearly too late.

You should define the task in the following way:
task xml_file_to_vs_build(type: Copy) {
println("copying strings.xml")
from 'src/main/res/values'
into '../vso_build'
include 'strings.xml'
}

Related

Is there a way to make gradle task lintRelease do nothing when executed for a particular module?

Currently lintRelease, task depends on the compilation task, and for some modules (which I dont care about since its only used for testing purposes), I want lintRelease to do nothing, just print Not supported is that possible with gradle KTS?
Basically this question is about gradle task replacement, I want to replace the lintRelease gradle task with a task that does nothing.
If you are thinking
You can skip lint checking for debug/release builds
The lintRelease task is manually triggered at the moment by a shell script, so thats not an option, I need this task to not do anything for this particular module lets call it module X
Try this at the top of the Gradle file
tasks.whenTaskAdded { task ->
if (task.name.equals("lint")) {
task.enabled = false
}
}
Even this can also help
android {
lintOptions {
tasks.lint.enabled = false
}
}

Run grade tasks inside a task without dependsOn

Assume that I have set of tasks executed from the cmd line and it works:
gradle processReleaseManifest compileReleaseSources run assembleRelease
Here run is the task which I Defined.
So My requirement is that I need to create a task which executes the above mentioned 4 tasks,
like say new task abc, runs the above mentioned tasks in the same order,
I know I cannot use dependsOn in this case because,processReleaseManifest compileReleaseSource when used in the build gradle it shows,
Could not get unknown property 'assembleRelease' for project ':app' of type org.gradle.api.Project.
So what is the solution?
You can, as #lu.koerfer's answer indicates use strings in the dependsOn list to refer to tasks that are defined further down in the build file.
In other words, this works:
task foo {}
task bar(dependsOn: [foo]) {}
and this also works:
task bar(dependsOn: ['foo']) {}
task foo {}
Now as for getting the tasks to run in the order you want things are not quite as straight forward. The dependsOn property only tells the task which tasks need to run before the task itself runs. It does not tell gradle to run the tasks in the order defined in the dependsOn clause.
An example:
task one {}
task two {}
task three {}
task run(dependsOn: [one, two, three]) {}
results in the following output when run:
~> gradle run
:one UP-TO-DATE
:three UP-TO-DATE
:two UP-TO-DATE
:run UP-TO-DATE
BUILD SUCCESSFUL
...note the fact that we are not running in the order one, two, three, run.
In other words, the command line invocation forces the tasks to run in the order defined whereas the dependsOn is a set and has no ordering.
There are a few ways you can get the tasks to run in the order you want. One is to define dependencies on the tasks (this is probably the common path):
task one {}
task two(dependsOn: ['one']) {}
task three(dependsOn: ['two']) {}
task run(dependsOn: [one, two, three]) {}
which results in:
~> gradle run
:one UP-TO-DATE
:two UP-TO-DATE
:three UP-TO-DATE
:run UP-TO-DATE
BUILD SUCCESSFUL
another is to use the task ordering constructs added in later versions of gradle.
Also, if you need to add a task dependency to a task which was defined somewhere earlier in the file, you can do so via:
task foo {}
someTaskDefinedFurtherUp.dependsOn 'foo'
which adds the task foo to the dependencies of someTaskDefinedFurtherUp.
You need to pass the task names as strings to the dependsOn method, because at the time you call it, the task objects haven't been created yet. However, if you pass strings, the task names will be evaluated later:
task abc {
dependsOn 'processReleaseManifest', 'compileReleaseSources', 'run', 'assembleRelease'
}
As it may be possible but very complicated to specify the task dependencies and ordering via dependsOn and mustRunAfter / shouldRunAfter, I'll propose another possible solution:
You can invoke Gradle from Gradle and specify the tasks in same way you would via command line:
task abc(type: GradleBuild) {
tasks = ['processReleaseManifest', 'compileReleaseSources', 'run', 'assembleRelease']
}
This will call Gradle again from the current build and execute the tasks in the specified order.

Android Gradle - Check which task is being executed

In my gradle file I want to know which task triggered the code block. e.g. If I run
gradle assembleVanillaDebug
from the terminal, I want to know in my gradle file that assembleVanillaDebug task is being executed. This will also help me in figuring out I am running debug build type task or release build type task.
Can we know which task is being executed?
In the end,
gradle.startParameter.taskNames
proved to be my friend. gradle.startParameter.getTaskNames() would return you the list of all tasks being executed in current build.
e.g. For gradle clean assembleVanillaDebug, it will return you a list of tasks clean and assembleVanillaDebug.
Seeing this is still the first hit on google when you search for listing tasks, I thought I'd share the better way I found of getting all tasks that are being scheduled:
// Doc: Returns the tasks which are included in the execution plan.
// The tasks are returned in the order that they will be executed.
gradle.taskGraph.allTasks
As opposed to gradle.startParameter which is meant for finding out how gradle has been started, this gives you a list of actual task objects that gradle queues for execution.
Edit:
Make sure the graph is resolved before using it. It should be available when running a task action, for example in a doFirst {}, or try running your code in the whenReady{} closure like so:
project.gradle.taskGraph.whenReady {
println(project.gradle.taskGraph.allTasks)
}

Want to run a custom gradle task only when running Unit test

How to set up gradle to run a particular custom copy task, only when running unit tests?
EDIT
I want to run these tasks when i press build, i. e only in the flavor of the build with unit test execution included.
I've finally found the solution, with the help of this documentation which presents all the tasks that run during build, test, release etc. in a very concise manner. So by making tasks clean, preBuild depend on my copyTask I can ensure that the copy task is run every time the project is cleaned or built.
But since I don't want to run this during building or cleaning process but want to run it when I only run tests, I identified a task that compiles release unit test sources called the compileReleaseUnitTestSources but just mentioning it in build.gradle as
compileReleaseUnitTestSources.dependsOn(myCopyTask)
doesn't actually work, because gradle will give an error saying it cannot find the task compileReleaseUnitTestSources as for some reason that task is not available yet. Instead by enclosing it in a afterEvaluate block we can ensure that this block is executed after all tasks are evaluated, that way we have access to that task now, So finally I added this to my build.gradle
afterEvaluate {
compileReleaseUnitTestSources.dependsOn(copyResDirectoryToClasses)
}
All the answers here mention to use the dependsOn keyword to attach my task to another task that is run during general build/test execution, but none of them mentioned how to go around the problem where gradle is not able to find the tasks even though you know for sure that these tasks were available and run during build/test execution.
you have to set up a "customCopyTask" and make the "test-task" which does the unittests depend on the "customCopyTask" like this
task customCopyTask(type: Copy) {
from sourceSets.test.resources
into sourceSets.test.output.classesDir
}
test.dependsOn customCopyTask
You can make some task finalizing another, in that case this task will run only if another one was called, right after it. This could be done as:
task runUnitTest << {
println 'running tests'
}
task copyTestResults << {
println 'copying results'
}
//make copyTestResults finalize runUnitTest
runUnitTest.finalizedBy copyTestResults
You can read about it in the official user guide.
Additionally, if your unit test could be up-to-date and you don't want to run you copy task in that case, you can check the test task status and skip copy-task, as:
task copyTestResults {
doFirst {
//chtck anothe task status and skip this one if it didn't actually work
if (!tasks.getByName("runUnitTest").getState().didWork) {
throw new StopExecutionException();
}
}
doLast{
println 'copying results'
}
}
Or, if you just need to run copy-task before unit tests, make the test task depending on copy-task by setting it's dependsOn property, read about it with a number og examples here

How to call android flavor gradle task from another task

In my project I have 3 product flavors (dev, production and testing). I've recently switched from Ant, so maybe I still have Ant mindset, but this is what I am trying to achieve:
create custom task (let's call it "buildAndUpload"), which will call assembleDevRelease and then call another task.
Here is what I've tried:
task myCustomTask {
println "My Custom Task"
}
task buildAndUpload {
tasks.assembleDevRelease.execute()
tasks.myCustomTask.execute()
}
When I call buildAndUpload task (gradlew buildAndUpload) I am getting following output:
:buildAndUpload
"My Custom Task"
As you can see assembleDevRelease task is not called. I know that I can use doLast closure, but I really want to have myCustomTask call contained in separate task.
A task cannot call another task, but it can depend on it. For example:
task myCustomTask {
dependsOn "assembleDevRelease"
doLast {
println "executing..."
}
}
You should set the two tasks as dependencies. You'll want to do something along the lines of
task buildAndUpload(dependsOn: ['assembleDevRelease', 'myCustomTask'] {
}
Also please refer to the Gradle documentation on the build lifecycle for more details on execution order:
http://www.gradle.org/docs/current/userguide/build_lifecycle.html

Categories

Resources