Understanding tasks

1. Create a task

2. Locate a task

3. Configure a task

4. Create a typed task

5. Configure a typed task

6. Show some sample code to understand printing etc

7. Create task dependencies

8. List all tasks

9. List task tree with dependencies

1. Creating tasks

Basics of tasks and working with tasks is documented at Gradel site here

Next up is the "Authoring Tasks" document at gradle

This is the primary resource I am hoping to use for this document

This was my previous first contact document with gradle

My High level conceptual understanding of Gradle is here

Readme for this knowledge folder is here

Problem with creating tasks is, there are MANY MANY syntactical ways of creating tasks!!


//Simple task: Calls a method project.task()
//you can see the API for project
task('hello') {}


//Copy is a java class
task('copy', type: Copy) {}


//tasks is a property of the project object
//of type TaskContainer
tasks.create('hello') {}

//Apparently this is the same

task(hello) {}

task('hello') {}
task(hello) {}
tasks.create('hello'){}

All 3 ways have a "function" call syntax with "()" with braces to enclose the task name


task(hello) {
   doLast {
      println 'this is from hello task'
   }
}

task('hello') {}
task(hello) {}

task hello {} //No braces or quotes

tasks.create('hello'){}

Creating custom tasks is documented here

I will cover that later

Task API Javadoc is documented here

TaskContainer API is documented here


/*
 * Understand Gradle tasks: Creating tasks
 */

//***************************************************************
//Project.getBuildscript(): ScriptHandler is the closure delegate
//So look for the method signatures on ScriptHanlder class
//***************************************************************
buildscript {
  //This line appears first
   println "1. in buildscript"
}

//Rest of the execution 
println "2. Rest of the script begins"

//**************************************************
//Many ways of creating tasks in gradle
//**************************************************

//Creating without a formality
//**************************************************
task hello {
  println 'Creating a task called hello'
  doLast {
    println 'Executing hello'
  }
}

//Creating with a function call
//**************************************************
task ("hello2") {
  println 'Creating a task called hello2 as a function call'
  doLast {
    println 'Executing hello2'
  }
}

//Strange syntax. Creatin without string quotes
//**************************************************
task (hello3) {
  println 'Creating a task called hello3 as a function call'
  doLast {
    println 'Executing hello3'
  }
}

//Using the taskContainer (collection) to create
//**************************************************
tasks.create('hello4') {
  println 'Creating a task called hello4 using task container'
  doLast {
    println 'Executing hello4'
  }
}

//**************************************************
//Define a task called build 
//so that it can be made a default task
//later, so we have an anchor point to call tasks
//**************************************************
task build {
  //we can define dependencies here during creation
  // Or locate this task by name and define the dependencies there

  //Uncomment the following if you want to define them
  //dependsOn hello, hello2, hello3
}

//**************************************************
// Examine what happens to a task.
// API can be found at org.gradle.api.task;
//
// You will see following printed
// *********************************
// Name of the build task is:(build)
// Path of the build task is:(:build)
// build task object itself:(task ':build')
//**************************************************
println ("Name of the build task is:(" + build.name + ")")
println ("Path of the build task is:(" + build.path+ ")")
println ("build task object itself:(" + build+ ")")

//**************************************************
// Define a default task to execute by running
// gradle (with out any args)
//**************************************************
defaultTasks 'build'

/*
* Invalid Block
**********************************************
* The name build is now allocated to an object
* it points to a task object called build
* defaultTasks is a method that takes a list of strings
**********************************************
defaultTasks build
***********************************************
*/

//**************************************************
// Goal: Define dependencies for the tasks
//
// Locate build task
// Define a dependency on another task
// This is seen as a way to locate the task named build
//**************************************************
build {
  dependsOn hello, hello2, hello3, hello4

  doLast {
    println 'All dependent tasks completed'
    println 'build finished'
  }
}

You can locate this code in github as well

2 Moving on to locating tasks

1. It becomes a member of the task collection (taskContainer) in the project object

2. it is also added with the same name as a property of the project object

3. Because of 2 the task name is available as a direct variable in the script. This is facility in gradle is called dynamic properties where properties are added during run time to a compiled class


//create a task 
task hello {}

//access and configure it now
hello.configure {}

//access it and print it
println "name of hello is: ${hello.name}"

//Or via the project
//access it and print it
println "name of hello is: ${project.hello.name}"

def helloTaskObject = tasks.getByName('hello')
println "From tasks: ${helloTaskObject.name}"

//This will not work to configure it
helloTaskObject {}

//Because it is an object and not a method
//Closures syntax work on methods

//So use the correct method to configure
helloTaskObject.configure {
  doLast {
    println 'hello task explict configuration'
  }
}

//Whereas this works because getByName can take 2 args.
//the second arg is config closure.

//internally the getByName does both
//1. locate the task
//2. Run the configure on it :)

tasks.getByName('hello') {
  doLast {
    println 'hello task implicit configuration'
  }
}

Look at the methods available on a project object

Locates a project by path and configures it using the given action. If the path is relative, it is interpreted relative to this project.


//Locate a project
*****************************
project(':projectA') {
    //Create a task there
    task hello
}

//Local hello task
*****************************
task hello


//There are 2 tasks now named the same
***************************************
println tasks.getByPath('hello').path
println tasks.getByPath(':hello').path
println tasks.getByPath('projectA:hello').path
println tasks.getByPath(':projectA:hello').path

//will print
***************************************
:hello
:hello
:projectA:hello
:projectA:hello