# Build Lifecycle

version 8.1

Gradle is an example of dependency based programming: you define tasks and dependencies between tasks. Gradle guarantees that these tasks execute in the order of their dependencies. Your build scripts and plugins configure this dependency graph. This page discusses the phases of the lifecycle Gradle passes through as it interprets those scripts. Additionally, this page explains how you can react to events of the lifecycle using notifications.

## Task Graphs

Some build tools assemble a task graph as they execute tasks. Gradle builds the task graph before executing any task. With configuration avoidance, Gradle skips configuration for tasks that aren’t part of the current build.

Within each project, tasks form a Directed Acyclic Graph (DAG).

This diagram shows two example task graphs: one abstract and the other concrete. The diagram represents dependencies between tasks as arrows:

Figure 1. Two examples of Gradle task graphs

Both plugins and your own build scripts contribute to the task graph via the task dependency mechanism.

## Build Phases

A Gradle build has three distinct phases. Gradle runs these phases in order: first initialization, then configuration, and finally execution.

Initialization

  - Detects the settings file.

  - Evaluates the settings file to determine which projects and included builds participate in the build.

  - Creates a `Project` instance for every project.

Configuration

  - Evaluates the build scripts of every project participating in the build.

  - Creates a task graph for requested tasks.

Execution

  - Schedules and executes each of the selected tasks in the order of their dependencies.

### Example

The following example shows which parts of settings and build files correspond to various build phases:

settings.gradle.kts

    rootProject.name = "basic"
    println("This is executed during the initialization phase.")

build.gradle.kts

    println("This is executed during the configuration phase.")

    tasks.register("configured") {
        println("This is also executed during the configuration phase, because :configured is used in the build.")
    }

    tasks.register("test") {
        doLast {
            println("This is executed during the execution phase.")
        }
    }

    tasks.register("testBoth") {
        doFirst {
            println("This is executed first during the execution phase.")
        }
        doLast {
            println("This is executed last during the execution phase.")
        }
        println("This is executed during the configuration phase as well, because :testBoth is used in the build.")
    }

settings.gradle

    rootProject.name = 'basic'
    println 'This is executed during the initialization phase.'

build.gradle

    println 'This is executed during the configuration phase.'

    tasks.register('configured') {
        println 'This is also executed during the configuration phase, because :configured is used in the build.'
    }

    tasks.register('test') {
        doLast {
            println 'This is executed during the execution phase.'
        }
    }

    tasks.register('testBoth') {
    	doFirst {
    	  println 'This is executed first during the execution phase.'
    	}
    	doLast {
    	  println 'This is executed last during the execution phase.'
    	}
    	println 'This is executed during the configuration phase as well, because :testBoth is used in the build.'
    }

The following command configures and executes the `test` and `testBoth` tasks specified above. Because Gradle only configures requested tasks and their dependencies, the `configured` task never configures.

    > gradle test testBoth
    This is executed during the initialization phase.

    > Configure project :
    This is executed during the configuration phase.
    This is executed during the configuration phase as well, because :testBoth is used in the build.

    > Task :test
    This is executed during the execution phase.

    > Task :testBoth
    This is executed first during the execution phase.
    This is executed last during the execution phase.

    BUILD SUCCESSFUL in 0s
    2 actionable tasks: 2 executed

    > gradle test testBoth
    This is executed during the initialization phase.

    > Configure project :
    This is executed during the configuration phase.
    This is executed during the configuration phase as well, because :testBoth is used in the build.

    > Task :test
    This is executed during the execution phase.

    > Task :testBoth
    This is executed first during the execution phase.
    This is executed last during the execution phase.

    BUILD SUCCESSFUL in 0s
    2 actionable tasks: 2 executed

## Initialization

In the initialization phase, Gradle detects the set of projects and included builds participating in the build. Gradle first evaluates the settings file. Then, Gradle instantiates `Project` instances for each project.

### Detect Settings File

When you run Gradle in a directory that contains a `settings.gradle` file, Gradle uses that `settings.gradle` file to initialize the build. You can run Gradle within any subproject of the build.[1] When you run Gradle in a directory that contains no `settings.gradle` file:

1. Gradle looks for a `settings.gradle(.kts)` file in parent directories.

2. If Gradle finds a `settings.gradle(.kts)` file, Gradle checks if the current project is part of the multi-project build. If so, Gradle builds as a multi-project.

3. If Gradle does not find a `settings.gradle(.kts)` file, Gradle builds as a single project.

In the standard Gradle project layout, project paths match the physical subproject layout on disk. The automatic search for a settings file only works for multi-project builds with a standard project layout. To build projects that use a nonstandard layout, execute the build from the directory that contains `settings.gradle(.kts)`.

### Evaluate Settings File

During settings file evaluation, Gradle:

- Adds libraries to your build script classpath.

- Defines which included builds participate in a composite build.

- Defines which projects participate in a multi-project build.

Gradle creates a `Project` for every project in the build. By default, each `Project` has a name equal to the name of its top level directory. Every project except the root project has a parent project. Any project may have child projects.

## Configuration

In the configuration phase, Gradle adds tasks and other properties to the projects generated by the initialization phase. By the end of the configuration phase, Gradle has a complete task execution graph for the requested tasks.

### Project Evaluation

During project evaluation, Gradle evaluates build scripts to build a task hierarchy within a `Project`. This hierarchy includes inputs, actions, and outputs for all tasks.

#### React to Project Evaluation

You can receive a notification immediately before and immediately after a project evaluates. These notifications work even when project evaluation fails. You can configure project evaluation notifications for all projects or a specific project. For example, you could use these notifications for:

- additional configuration after applying all definitions in a build script

- custom logging

- custom profiling

The following example uses `gradle.beforeProject()` to add `hasTests` property to certain tests. Later, the example uses `gradle.afterProject()` to add a `test` task to each project where the `hasTests` property value is `true`:

build.gradle.kts

    gradle.beforeProject {
        // Set a default value
        project.ext.set("hasTests", false)
    }

    gradle.afterProject {
        if (project.ext.has("hasTests") && project.ext.get("hasTests") as Boolean) {
            val projectString = project.toString()
            println("Adding test task to $projectString")
            tasks.register("test") {
                doLast {
                    println("Running tests for $projectString")
                }
            }
        }
    }

project-a.gradle.kts

    extra["hasTests"] = true

build.gradle

    gradle.beforeProject { project ->
        project.ext.set("hasTests", false)
    }

    gradle.afterProject { project ->
        if (project.ext.has("hasTests") && project.ext.get("hasTests") as Boolean) {
            def projectString = project.toString()
            println "Adding test task to $projectString"
            project.task('test') {
                doLast {
                    println "Running tests for $projectString"
                }
            }
        }
    }

project-a.gradle

    hasTests = true

    > gradle -q test
    Adding test task to project ':project-a'
    Running tests for project ':project-a'

To receive these events via a listener instead of a closure, add a ProjectEvaluationListener to a build’s Gradle instance.

### Task Execution Graph Assembly

During project evaluation, Gradle assembles the task execution graph: a DAG representing the dependency relationships between tasks.

### React to Task Execution Graph Assembly

You can receive a notification immediately after Gradle finishes populating a project’s task execution graph.

To receive these events, add a TaskExecutionGraphListener to a project’s TaskExecutionGraph.

### Task Creation

During project evaluation, Gradle registers tasks and their configuration actions. The configuration actions define inputs, outputs, and actions for those tasks. They are evaluated if the task is part of the task graph for the requested tasks.

#### React to Task Creation

You can receive a notification immediately after Gradle adds a task to a project. For example, you could use these notifications to set some default values or methods.

The following example sets a `srcDir` value on each task in a project:

build.gradle.kts

    tasks.whenTaskAdded {
        extra["srcDir"] = "src/main/java"
    }

    val a by tasks.registering

    println("source dir is ${a.get().extra["srcDir"]}")

build.gradle

    tasks.whenTaskAdded { task ->
        task.ext.srcDir = 'src/main/java'
    }

    tasks.register('a')

    println "source dir is $a.srcDir"

    > gradle -q a
    source dir is src/main/java

To receive these events via a listener instead of a closure, add an Action to a TaskContainer.

## Execution

In the execution phase, Gradle runs tasks. Gradle uses the task execution graphs generated by the configuration phase to determine which tasks to execute.

### Task Execution

Task execution includes most of the work you normally associate with a build: downloading libraries, compiling code, reading inputs, and writing outputs.

#### React to Task Execution Notifications

| Task execution events are not compatible with the configuration cache. You can use build services to receive information about task execution in a way compatible with the configuration cache.

You can receive a notification immediately before and after Gradle executes any task. These notifications work even when task execution fails. The following example logs the start and end of each task execution:

build.gradle.kts

    tasks.register("ok")

    tasks.register("broken") {
        dependsOn("ok")
        doLast {
            throw RuntimeException("broken")
        }
    }

    gradle.taskGraph.beforeTask {
        println("executing $this ...")
    }

    gradle.taskGraph.afterTask {
        if (state.failure != null) {
            println("FAILED")
        } else {
            println("done")
        }
    }

build.gradle

    tasks.register('ok')

    tasks.register('broken') {
        dependsOn ok
        doLast {
            throw new RuntimeException('broken')
        }
    }

    gradle.taskGraph.beforeTask { Task task ->
        println "executing $task ..."
    }

    gradle.taskGraph.afterTask { Task task, TaskState state ->
        if (state.failure) {
            println "FAILED"
        }
        else {
            println "done"
        }
    }

    > gradle -q broken
    executing task ':ok' ...
    done
    executing task ':broken' ...
    FAILED

    FAILURE: Build failed with an exception.

    * What went wrong:
    Execution failed for task ':broken'.
    > broken

    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights.

    * Get more help at https://help.gradle.org

    BUILD FAILED in 0s

    > gradle -q broken
    executing task ':ok' ...
    done
    executing task ':broken' ...
    FAILED

    FAILURE: Build failed with an exception.

    * Where:
    Build file '/home/user/gradle/samples/build.gradle' line: 6

    * What went wrong:
    Execution failed for task ':broken'.
    > broken

    * Try:
    > Run with --stacktrace option to get the stack trace.
    > Run with --info or --debug option to get more log output.
    > Run with --scan to get full insights.

    * Get more help at https://help.gradle.org

    BUILD FAILED in 0s

To receive these events via a listener instead of a closure, add a TaskExecutionListener to a project’s TaskExecutionGraph.

1. Gradle supports partial multi-project builds (see Executing Multi-Project Builds).