// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[build_lifecycle]]
= Build Lifecycle

The build lifecycle is the sequence of phases Gradle executes to turn your build scripts into completed work, from initializing the build environment to configuring projects and finally executing tasks.

[[build_phases]]
== Build Phases

A build has three distinct phases.
Gradle runs these phases in order:

[cols="1,1,1", options="header"]
|===
|Phase 1. Initialization
|Phase 2. Configuration
|Phase 3. Execution

| Detects projects and included builds
| Configures projects and builds a task graph
| Schedules and executes the selected tasks
|===

image::build-lifecycle-example.png[]

[[initialization]]
=== Phase 1. Initialization

In the *initialization phase*, Gradle detects the set of projects (root and subprojects) and included builds participating in the build.

Gradle first runs any init scripts, then evaluates the settings file, `settings.gradle(.kts)`, and instantiates a `Settings` object.

Then, Gradle instantiates `Project` object instances for each project included in the build (using `includeBuild()` or `include()` in the settings file).

[[configuration]]
=== Phase 2. Configuration

In the *configuration phase*, Gradle registers tasks and other properties to the projects found by the initialization phase.

Gradle evaluates the build files of every participating project, then constructs the <<#task_graph,task graph>> by analyzing the input and output dependencies of tasks.

NOTE: When the *Configuration Cache* is enabled, the configuration phase also includes a _serialization sub-phase_, where Gradle stores the task graph while simultaneously precomputing some of the task state and resolving dependencies. This is work that would otherwise be deferred to execution. See <<configuration_cache.adoc#config_cache,Configuration Cache - How It Works>> for more details.

[[execution]]
=== Phase 3. Execution

In the *execution phase*, Gradle runs the selected tasks.

Gradle uses the <<#task_graph,task execution graph>> generated by the configuration phase to determine which tasks to execute and in what order.

Gradle can execute tasks that don't depend on each other, in the same project, in parallel.

=== The Phases in Build Scripts

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

====
include::sample[dir="snippets/reference/runtime-configuration/basic/kotlin",files="settings.gradle.kts[];build.gradle.kts[]"]
include::sample[dir="snippets/reference/runtime-configuration/basic/groovy",files="settings.gradle[];build.gradle[]"]
====

The following command executes the `test` and `testBoth` tasks specified above:

====
[.multi-language-text.lang-kotlin]
=====
[source,bash]
----
$ ./gradlew test testBoth
----
[source,text]
----
include::{snippetsPath}/reference/runtime-configuration/basic/tests/buildlifecycle.out[]
----
=====
[.multi-language-text.lang-groovy]
=====
[source,bash]
----
$ ./gradlew test testBoth
----
[source,text]
----
include::{snippetsPath}/reference/runtime-configuration/basic/tests/buildlifecycle.out[]
----
=====
====

Because Gradle only configures requested tasks and their prerequisites, the `configured` task never configures.

== Build Lifecycle Timeline

Understanding the precise sequence in which Gradle evaluates scripts and triggers hooks is the key to mastering build logic.
This timeline provides a comprehensive overview of the Gradle build flow **when the Configuration Cache and Isolated Projects are disabled**:

[cols="~,~,~,~,~", options="header"]
|===
| Phase | Seq. | Hook / Block | Location | Purpose

| *Initialization*
| 1
| <<init_scripts.adoc#init_scripts,Init Scripts>>
| `~/.gradle/init.d/*.gradle`
| Global environment setup (e.g., enterprise repos).

|
| 2
| <<#before_settings,`gradle.beforeSettings`>>
| init script or `settings.gradle(.kts)`
| Runs before the settings file is even parsed.

|
| 3
| `pluginManagement { ... }`
| `settings.gradle(.kts)`
| *Must be first.* Defines plugin repos and version rules.

|
| 4
| `plugins { ... }`
| `settings.gradle(.kts)`
| Applies plugins to the `Settings` object (e.g., Build Scans).

|
| 5
| Settings Script Body
| `settings.gradle(.kts)`
| Evaluates `include(":project")` to define build structure.

|
| 6
| <<#settings_evaluated,`gradle.settingsEvaluated`>>
| init script or `settings.gradle(.kts)`
| Settings are fully processed; Project objects are created.

|
| 7
| <<projects_loaded,`gradle.projectsLoaded`>>
| init script or `settings.gradle(.kts)`
| All project instances exist but aren't configured yet.

| *Configuration*
| 8
| <<before_project,`gradle.lifecycle.beforeProject`>>
| init script or `build.gradle(.kts)`
| *Not recommended.* Fires immediately before *each* project starts evaluating.

|
| 9
| link:{javadocPath}/org/gradle/api/Project.html#beforeEvaluate(groovy.lang.Closure)[`project.beforeEvaluate`]
| init script or parent project's `build.gradle(.kts)`
| Runs before a specific project's build script is evaluated.

|
| 10
| `buildscript { ... }`
| `build.gradle(.kts)`
| Sets the classpath for the build script itself.

|
| 11
| `plugins { ... }`
| `build.gradle(.kts)`
| Applies plugins and adds DSL/Tasks.

|
| 12
| Build Script Body
| `build.gradle(.kts)`
| Registers tasks (`tasks.register`) and configures properties.

|
| 13
| link:{javadocPath}/org/gradle/api/Project.html#afterEvaluate(groovy.lang.Closure)[`project.afterEvaluate`]
| `build.gradle(.kts)`
| *Not recommended.* Runs after a specific project is evaluated; useful for reacting to another project's configuration.

|
| 14
| <<after_project,`gradle.lifecycle.afterProject`>>
| init script or root `build.gradle(.kts)`
| Fires immediately after *each* project finishes evaluating.

|
| 15
| <<projects_evaluated,`gradle.projectsEvaluated`>>
| init script or root `build.gradle(.kts)`
| All project scripts have run; final chance to tweak the graph.

|
| 16
| <<#task_graph,Task Graph>> Construction
| Internal (link:{javadocPath}/org/gradle/api/execution/TaskExecutionGraph.html[`TaskExecutionGraph`], link:{javadocPath}/org/gradle/api/execution/TaskExecutionGraphListener.html[`TaskExecutionGraphListener`], link:{javadocPath}/org/gradle/api/execution/TaskExecutionListener.html[`TaskExecutionListener`])
| Gradle calculates the DAG based on requested tasks.

| *Execution*
| 17a
| Task Input Snapshotting
| Internal (link:{javadocPath}/org/gradle/api/DefaultTask.html#onlyIf(groovy.lang.Closure)[`onlyIf{}`], link:{javadocPath}/org/gradle/api/tasks/TaskOutputs.html#upToDateWhen(groovy.lang.Closure)[`upToDateWhen{}`])
| Evaluated per task to determine whether it should be skipped or executed.

|
| 17b
| <<graph_resolution.adoc#dependency-graph-resolution,Dependency Graph Resolution>>*
| Internal (link:{javadocPath}/org/gradle/api/artifacts/result/ResolutionResult.html[`ResolutionResult`], link:{javadocPath}/org/gradle/api/artifacts/result/ResolvedComponentResult.html[`ResolvedComponentResult`], link:{javadocPath}/org/gradle/api/artifacts/result/ResolvedVariantResult.html[`ResolvedVariantResult`])
| Constructs a dependency graph based on declared dependencies.

|
| 17c
| <<artifact_resolution.adoc#artifact-resolution,Artifact Resolution>>*
| Internal (link:{javadocPath}/org/gradle/api/artifacts/ArtifactCollection.html[`ArtifactCollection`], link:{javadocPath}/org/gradle/api/artifacts/ResolvedArtifact.html[`ResolvedArtifact`])
| Dependencies are downloaded from repositories.

|
| 18
| Task Execution
| Console / CLI (link:{javadocPath}/org/gradle/api/tasks/TaskAction.html[`@TaskAction`],link:{javadocPath}/org/gradle/api/DefaultTask.html#doFirst(groovy.lang.Closure)[`doFirst{}`],link:{javadocPath}/org/gradle/api/DefaultTask.html#doLast(groovy.lang.Closure)[`doLast{}`])
| Tasks run.

|===

+++*+++ *Dependency Graph Resolution* and *Artifact Resolution* are normally deferred until the *Execution Phase*.
However, any build logic that eagerly accesses a configuration's resolved state, such as calling `configuration.files`,
`configuration.resolvedConfiguration`, or iterating a configuration directly, will trigger resolution immediately at that point in the build lifecycle.

IMPORTANT: When the *Configuration Cache is enabled*, *Dependency Graph Resolution* and *Artifact Resolution* must be completed during the *Configuration Phase* rather than at execution time, since they are required to fully describe the task graph before the result can be serialized. You can refer to <<configuration_cache.adoc#config_cache,Configuration Cache - How It Works>> to learn more.

[[task_graph]]
== Task Graphs

As a build author, you write build logic by defining tasks and declaring how they depend on one another.
Gradle uses this information to construct a **task graph** during the *configuration phase* that models the relationships between these tasks.

For example, if your project includes tasks such as `build`, `assemble`, and `createDocs`, and you declare that `assemble` depends on `build`, and `createDocs` depends on `assemble`, Gradle constructs a graph with this order: `build` → `assemble` → `createDocs`.

Gradle builds the task graph *before* executing any task(s).

Across all projects in the build, tasks form a http://en.wikipedia.org/wiki/Directed_acyclic_graph[Directed Acyclic Graph^] (DAG).

This diagram shows two example task graphs, one abstract and the other concrete, with dependencies between tasks represented as arrows:

image::task-dag-examples.png[]

[[lifecycle_api]]
== Hooks into the Gradle Build Lifecycle

Gradle exposes several APIs that let you listen to or react to key points in the build lifecycle.

Some APIs let you hook into those phases in init scripts, `settings.gradle(.kts)` or `build.gradle(.kts)` to customize or inspect the build as Gradle configures it.
These hooks let you:

- react to the structure of the build (root + subprojects),
- configure all projects before their own build scripts are evaluated,
- debug or collect information during configuration.

[[sec:lifecycle_api]]
=== Lifecycle API

The link:{javadocPath}/org/gradle/api/invocation/GradleLifecycle.html[`GradleLifecycle`] API, accessible through the link:{javadocPath}/org/gradle/api/invocation/Gradle.html[`gradle`] object, can be used to register actions to be executed at certain points in the build lifecycle:

[source,text]
----
buildStarted -> DEPRECATED in Gradle 6
 └─ beforeSettings
     └── settingsEvaluated
          └── projectsLoaded
               ├── beforeProject
               ├── afterProject
               └── projectsEvaluated
                     └── buildFinished -> DEPRECATED in Gradle 7
----

Here is a quick overview:

[cols="~,~,~", options="header"]
|===
| # | Hook | Best for

| <<#before_settings,1>>
| link:{javadocPath}/org/gradle/api/invocation/Gradle.html#beforeSettings(groovy.lang.Closure)[`gradle.beforeSettings`]
| Early wiring from an init script: global logging/metrics, tweaking `gradle.startParameter`, choosing different settings files, or setting values on the `Settings` object before it’s evaluated.

| <<#settings_evaluated,2>>
| link:{javadocPath}/org/gradle/api/invocation/Gradle.html#settingsEvaluated(groovy.lang.Closure)[`gradle.settingsEvaluated`]
| Adjusting repositories, enabling build scans, reading environment variables, or changing build layout.

| <<#projects_loaded,3>>
| link:{javadocPath}/org/gradle/api/invocation/Gradle.html#projectsLoaded(groovy.lang.Closure)[`gradle.projectsLoaded`]
| Applying configuration to every project (for example, adding a plugin to all subprojects).

| <<#before_project,4>>
| link:{javadocPath}/org/gradle/api/invocation/GradleLifecycle.html#beforeProject(org.gradle.api.IsolatedAction)[`gradle.lifecycle.beforeProject`]
| Applying defaults, logging project configuration start.

| <<#after_project,5>>
| link:{javadocPath}/org/gradle/api/invocation/GradleLifecycle.html#afterProject(org.gradle.api.IsolatedAction)[`gradle.lifecycle.afterProject`]
| Validating configuration or detecting missing plugins.

| <<#projects_evaluated,6>>
| link:{javadocPath}/org/gradle/api/invocation/Gradle.html#projectsEvaluated(org.gradle.api.Action)[`gradle.projectsEvaluated`]
| Performing cross-project validation, configuration summaries, or creating aggregated tasks.

|===

[[before_settings]]
==== `beforeSettings`

*Where*: init script. +
*When*: By the time `settings.gradle(.kts)` is executing, `beforeSettings` has already fired.

====
include::sample[dir="snippets/reference/runtime-configuration/callbacks/kotlin",files="callbacks.init.gradle.kts[tags=beforesettings]"]
include::sample[dir="snippets/reference/runtime-configuration/callbacks/groovy",files="callbacks.init.gradle[tags=beforesettings]"]
====

[[settings_evaluated]]
==== `settingsEvaluated`

*Where*: `settings.gradle(.kts)`. +
*When*: After the settings file finishes evaluating.

====
include::sample[dir="snippets/reference/runtime-configuration/callbacks/kotlin",files="callbacks.init.gradle.kts[tags=settingsevaluated]"]
include::sample[dir="snippets/reference/runtime-configuration/callbacks/groovy",files="callbacks.init.gradle[tags=settingsevaluated]"]
====

[[projects_loaded]]
==== `projectsLoaded`

*Where*: `settings.gradle(.kts)`. +
*When*: All projects have been discovered but not yet configured.

====
include::sample[dir="snippets/reference/runtime-configuration/callbacks/kotlin",files="callbacks.init.gradle.kts[tags=projectsloaded]"]
include::sample[dir="snippets/reference/runtime-configuration/callbacks/groovy",files="callbacks.init.gradle[tags=projectsloaded]"]
====

[[before_project]]
==== `beforeProject`

*Where*: `build.gradle(.kts)` or anywhere you have access to the Gradle instance. +
*When*: For each project as its build script is evaluated.

====
include::sample[dir="snippets/reference/runtime-configuration/callbacks/kotlin",files="callbacks.init.gradle.kts[tags=beforeproject]"]
include::sample[dir="snippets/reference/runtime-configuration/callbacks/groovy",files="callbacks.init.gradle[tags=beforeproject]"]
====

[[after_project]]
==== `afterProject`

*Where*: `build.gradle(.kts)` or anywhere you have access to the Gradle instance. +
*When*: For each project as its build script is evaluated.

====
include::sample[dir="snippets/reference/runtime-configuration/callbacks/kotlin",files="callbacks.init.gradle.kts[tags=afterproject]"]
include::sample[dir="snippets/reference/runtime-configuration/callbacks/groovy",files="callbacks.init.gradle[tags=afterproject]"]
====

[[projects_evaluated]]
==== `projectsEvaluated`

*Where*: `build.gradle(.kts)` or anywhere you have access to the Gradle instance. +
*When*: After all projects have been evaluated (i.e., all `build.gradle(.kts)` files are read and configuration is complete), but before task graph is finalized and before execution starts.

====
include::sample[dir="snippets/reference/runtime-configuration/callbacks/kotlin",files="callbacks.init.gradle.kts[tags=projectsevaluated]"]
include::sample[dir="snippets/reference/runtime-configuration/callbacks/groovy",files="callbacks.init.gradle[tags=projectsevaluated]"]
====

=== Build Listeners

Listeners are interfaces you implement to react to build lifecycle events.

Many `BuildListeners` are deprecated and/or are *not* Configuration Cache friendly, use them with caution:

[cols="2,3,1", options="header"]
|===
| Interface | What it observes | Works with CC?

| link:{javadocPath}/org/gradle/BuildListener.html[`BuildListener`]
| Fires when projects are loaded/evaluated.
| ❌

| link:{javadocPath}/org/gradle/tooling/events/ProgressListener.html[`ProgressListener`]
| Fires when the execution of an operation progresses.
| ✅

| (Partially Deprecated) link:{javadocPath}/org/gradle/api/execution/TaskActionListener.html[`TaskActionListener`]
| Fires when a task has started or completed its action.
| ❌

| (Deprecated) link:{javadocPath}/org/gradle/api/execution/TaskExecutionListener.html[`TaskExecutionListener`]
| Fires before and after each task executes.
| ❌

| (Deprecated) link:{javadocPath}/org/gradle/api/execution/TaskExecutionGraphListener.html[`TaskExecutionGraphListener`]
| Fires when the task execution graph has been populated.
| ❌

| link:{javadocPath}/org/gradle/tooling/events/OperationCompletionListener.html[`OperationCompletionListener`]
| Fires when an operation completes.
| ✅

| link:{javadocPath}/org/gradle/api/artifacts/DependencyResolutionListener.html[`DependencyResolutionListener`]
| Fires before and after dependency resolution.
| ❌

| link:{javadocPath}/org/gradle/api/ProjectEvaluationListener.html[`ProjectEvaluationListener`]
| Fires before and after each project is evaluated.
| ❌

| link:{javadocPath}/org/gradle/api/tasks/testing/TestListener.html[`TestListener`]
| Fires at different times during test execution.
| ❌

|===

You implement a listener interface and typically register it on the `gradle` object.
The `TaskExecutionGraphListener` fires once after the task graph has been calculated, but before any task executes.

This example uses `graph.allTasks` to inspect what Gradle plans to run, and `graph.hasTask()` to conditionally adjust behaviour:

====
include::sample[dir="snippets/reference/runtime-configuration/buildListener/kotlin",files="build.gradle.kts[tags=task-execution-graph-listener]"]
include::sample[dir="snippets/reference/runtime-configuration/buildListener/groovy",files="build.gradle[tags=task-execution-graph-listener]"]
====

Note that tasks skipped via `onlyIf` still appear in the graph; skipping is evaluated later, per task, during execution:

[source,text]
----
include::{snippetsPath}/reference/runtime-configuration/buildListener/tests/buildlistener.out[]
----

=== Build Services

<<build_services.adoc#build_services,Build Services>> are used to share state or resources across tasks and across the build lifecycle.

This example implements link:{javadocPath}/org/gradle/tooling/events/OperationCompletionListener.html[`OperationCompletionListener`] directly on the service to count tasks as they complete, and uses `close()` as an end-of-build hook to print the final summary, whether the build succeeded or failed:

====
include::sample[dir="snippets/reference/runtime-configuration/buildService/kotlin",files="build.gradle.kts[tags=listener]"]
include::sample[dir="snippets/reference/runtime-configuration/buildService/groovy",files="build.gradle[tags=listener]"]
====

The hooks are used to calculate the duration of the build:

[source,text]
----
include::{snippetsPath}/reference/runtime-configuration/buildService/tests/buildservice.out[]
  Build duration : 510ms
─────────────────────────────────────

BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 executed
----

=== Flow Actions incubating-label:[]

<<dataflow_actions#dataflow_action,FlowAction>> is a newer API (introduced in Gradle 7.6) that lets you run logic in response to build lifecycle events, most commonly, when the build finishes.
It was introduced as a <<configuration_cache.adoc#config_cache,Configuration Cache>> and <<isolated_projects.adoc#isolated_projects,Isolated Projects>> compatible alternative to `BuildListener` and other deprecated lifecycle listeners.

To use a Flow Action, you define a class implementing link:{javadocPath}/org/gradle/api/flow/FlowAction.html[`FlowAction<T>`] and a matching link:{javadocPath}/org/gradle/api/flow/FlowParameters.html[`Parameters`] interface that declares the inputs your action needs.
You then register it inside a `Plugin` using link:{javadocPath}/org/gradle/api/flow/FlowScope.html[`FlowScope`], which is injected by Gradle alongside link:{javadocPath}/org/gradle/api/flow/FlowProviders.html[`FlowProviders`]:

====
include::sample[dir="snippets/reference/runtime-configuration/flowAction/kotlin",files="build.gradle.kts[tags=flow-action]"]
include::sample[dir="snippets/reference/runtime-configuration/flowAction/groovy",files="build.gradle[tags=flow-action]"]
====

As expected, we see the build finish success message:

[source,text]
----
include::{snippetsPath}/reference/runtime-configuration/flowAction/tests/flowaction.out[]
----
