I have a task that runs a shell script. It resides in my top level gradle file only. So the gradle file im talking about can be seen here:
Now for the interesting part, i have a task in the file called copyFiles which just runs a simple shell script to copy files. Im going to show you my entire build.gradle top level file now:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:1.5.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
task copyFiles(type:Exec) {
exec {
commandLine 'sh', './copyFiles.sh'
}
}
Now whenever i build the project this task gets executed. As long as i build the project (aka compile it) this task runs. Is that normal ? i put a print line in there to make sure and yes it gets run everytime i build the 'app' module. Is this normal. What if i wanted it not to do that ?
UPDATE: Now after researching i found that some gradle tasks can be executed right away without being invoked if defined like this:
//option 1, this runs right away on build
task foo(type: Exec) {
// this is configuration
// i.e. it runs regardless
}
//option 2 this runs only when called on
task bar(type: Exec) << {
// this is execution
// i.e. it only runs if you call the task
}
So then i thought i'd try the same thing with :
task copyFiles(type: Copy) {
from '/Users/myuser/Documents/androidstudio/MyApplication/Common/'
into '/Users/myuser/Documents/androidstudio/MyApplication/app/src/main/assets'
}
but to my surprise it does not get run on its own. I actually have to call it ? How is this different then type:Exec ? why is there no consistency ?
UPDATE:
I wrote a blog about the gradle lifecycle for anyone who needs help after my analysis.
You might have to read about the build lifecycle. When you run your build, this build goes through 3 phases: Initialization, Configuration and Execution.
When you declare a closure as:
task foo(type: Exec) {
// this is configuration
// i.e. it runs regardless
}
then this closure is executed for all the task at the configuration phase, that is why your print line is always called, even if a task shell not be executed. It's just a part of the whole configuration.
But if you declare a closure with <<
, as:
task bar(type: Exec) << {
// this is execution
// i.e. it only runs if you call the task
}
it's executed at the execution phase. Actually, <<
is equals to doLast
for the task.
Furthermore, then you use a exec {}
notation within a task, you create a execution subtask within it.
So, if you don't want to run it at the configuration, then just use it with the <<
, or don't call an additional exec
task within a task, which is by itself of type Exec
and just properly configure it, like:
task copyFiles(type:Exec) {
commandLine 'sh', './copyFiles.sh'
}