Tasks in Gradle are the basic execution units in the build process. Understanding the concept and configuration of Tasks is crucial for using Gradle efficiently.
Basic Concepts of Task
A Task is an atomic operation unit representing a specific step in the build process, such as compiling code, running tests, or packaging JAR files. Each Task has:
- Name: Uniquely identifies the task
- Type: Inherits from
org.gradle.api.Taskinterface - Action: The actual code that runs when the task executes
- Dependencies: Relationships with other tasks
- Inputs/Outputs: Input files and output files for incremental builds
Ways to Create Tasks
1. Using tasks.register() (Recommended)
groovy// Lazy initialization, created only when needed tasks.register('myTask') { doLast { println 'Executing myTask' } } // Specify task type tasks.register('copyFiles', Copy) { from 'src/main/resources' into 'build/resources' }
2. Using tasks.create() (Immediate Creation)
groovy// Create task instance immediately tasks.create('myTask') { doLast { println 'Executing myTask' } }
3. Direct Definition in build.gradle
groovytask myTask { doLast { println 'Executing myTask' } } task myTask2(type: Copy) { from 'src/main/resources' into 'build/resources' }
Task Configuration
Basic Configuration
groovytasks.register('myTask') { // Task description description = 'This is my custom task' // Task group group = 'Custom Tasks' // Set task dependencies dependsOn 'clean', 'compileJava' // Set task must run after mustRunAfter 'test' // Set task should run after shouldRunAfter 'build' // Set task inputs inputs.file('config.properties') inputs.dir('src/main/java') // Set task outputs outputs.dir('build/output') // Task actions doFirst { println 'Before task execution' } doLast { println 'After task execution' } }
Dynamic Configuration
groovy// Use configure block tasks.register('myTask') { doLast { println "Project name: ${project.name}" } } tasks.named('myTask').configure { enabled = project.hasProperty('enableMyTask') } // Batch configuration tasks.withType(JavaCompile).configureEach { options.encoding = 'UTF-8' options.compilerArgs << '-Xlint:unchecked' }
Task Dependencies
dependsOn
groovytasks.register('taskA') { doLast { println 'Task A' } } tasks.register('taskB') { dependsOn 'taskA' doLast { println 'Task B' } } // Multiple dependencies tasks.register('taskC') { dependsOn tasks.taskA, tasks.taskB doLast { println 'Task C' } }
mustRunAfter and shouldRunAfter
groovytasks.register('taskA') { doLast { println 'Task A' } } tasks.register('taskB') { doLast { println 'Task B' } } // taskB must run after taskA taskB.mustRunAfter taskA // taskC should run after taskA (soft constraint) tasks.register('taskC') { shouldRunAfter taskA doLast { println 'Task C' } }
finalizedBy
groovytasks.register('taskA') { finalizedBy 'cleanupTask' doLast { println 'Task A' } } tasks.register('cleanupTask') { doLast { println 'Cleanup' } }
Task Execution Control
Conditional Execution
groovytasks.register('conditionalTask') { onlyIf { project.hasProperty('runConditional') } doLast { println 'This task runs only if property exists' } } // Use enabled property tasks.register('anotherTask') { enabled = false // Disable task doLast { println 'This will not run' } }
Skip Execution
groovytasks.register('skipTask') { doLast { println 'This task will be skipped' } // Method 1: Use onlyIf onlyIf { false } // Method 2: Throw StopExecutionException doFirst { if (!project.hasProperty('force')) { throw new StopExecutionException() } } }
Common Built-in Task Types
- Copy: Copy files and directories
- Delete: Delete files and directories
- Exec: Execute external commands
- JavaExec: Execute Java applications
- Test: Run tests
- Jar: Create JAR files
- Zip/Tar/GZip: Create compressed files
Best Practices
- Use
tasks.register()instead oftasks.create(): Lazy initialization improves performance - Clearly define task inputs and outputs: Enable incremental builds to improve build speed
- Use task dependencies reasonably: Avoid circular dependencies
- Add descriptions and groups to tasks: Improve readability
- Use
doFirstanddoLast: Instead of writing code directly in the task body to avoid execution during configuration phase