// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.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

We said earlier that the core of Gradle is a language for dependency based programming. In Gradle terms this means that you can define tasks and dependencies between tasks. Gradle guarantees that these tasks are executed in the order of their dependencies, and that each task is executed only once. These tasks form a http://en.wikipedia.org/wiki/Directed_acyclic_graph[Directed Acyclic Graph]. There are build tools that build up such a dependency graph as they execute their tasks. Gradle builds the complete dependency graph _before_ any task is executed. This lies at the heart of Gradle and makes many things possible which would not be possible otherwise.

Your build scripts configure this dependency graph. Therefore they are strictly speaking _build configuration scripts_.

[[sec:build_phases]]
== Build phases

A Gradle build has three distinct phases.

Initialization::
Gradle supports single and multi-project builds. During the initialization phase, Gradle determines which projects are going to take part in the build, and creates a link:{groovyDslPath}/org.gradle.api.Project.html[Project] instance for each of these projects.
Configuration::
During this phase the project objects are configured. The build scripts of _all_ projects which are part of the build are executed.
Execution::
Gradle determines the subset of the tasks, created and configured during the configuration phase, to be executed. The subset is determined by the task name arguments passed to the `gradle` command and the current directory. Gradle then executes each of the selected tasks.


[[sec:settings_file]]
== Settings file

Beside the build script files, Gradle defines a settings file. The settings file is determined by Gradle via a naming convention. The default name for this file is `settings.gradle`. Later in this chapter we explain how Gradle looks for a settings file.

The settings file is executed during the initialization phase. A multi-project build must have a `settings.gradle` file in the root project of the multi-project hierarchy. It is required because the settings file defines which projects are taking part in the multi-project build (see <<multi_project_builds.adoc#multi_project_builds,Authoring Multi-Project Builds>>). For a single-project build, a settings file is optional. Besides defining the included projects, you might need it to add libraries to your build script classpath (see <<organizing_gradle_projects.adoc#organizing_gradle_projects,Organizing Gradle Projects>>). Let's first do some introspection with a single project build:

.Single project build
====
include::sample[dir="snippets/userguide/buildlifecycle/basic/groovy",files="settings.gradle[];build.gradle[]"]
include::sample[dir="snippets/userguide/buildlifecycle/basic/kotlin",files="settings.gradle.kts[];build.gradle.kts[]"]
====

=== Output of **`gradle test testBoth`**
[source.multi-language-sample,groovy]
----
> gradle test testBoth
include::{samplesPath}/userguide/buildlifecycle/basic/buildlifecycle.groovy.out[]
----
[source.multi-language-sample,kotlin]
----
> gradle test testBoth
include::{samplesPath}/userguide/buildlifecycle/basic/buildlifecycle.kotlin.out[]
----

For a build script, the property access and method calls are delegated to a project object. Similarly property access and method calls within the settings file is delegated to a settings object. Look at the link:{groovyDslPath}/org.gradle.api.initialization.Settings.html[Settings] class in the API documentation for more information.

[[sec:lifecycle_multi_project_builds]]
== Multi-project builds

A multi-project build is a build where you build more than one project during a single execution of Gradle. You have to declare the projects taking part in the multi-project build in the settings file. There is much more to say about multi-project builds in the chapter dedicated to this topic (see <<multi_project_builds.adoc#multi_project_builds,Authoring Multi-Project Builds>>).


[[sub:project_locations]]
=== Project locations

Multi-project builds are always represented by a tree with a single root. Each element in the tree represents a project. A project has a path which denotes the position of the project in the multi-project build tree. In most cases the project path is consistent with the physical location of the project in the file system. However, this behavior is configurable. The project tree is created in the `settings.gradle` file. By default it is assumed that the location of the settings file is also the location of the root project. But you can redefine the location of the root project in the settings file.

[[sub:building_the_tree]]
=== Building the tree

In the settings file you can use a set of methods to build the project tree. Hierarchical and flat physical layouts get special support.


[[sec:hierarchical_layouts]]
==== Hierarchical layouts


.Hierarchical layout
====
include::sample[dir="snippets/userguide/multiproject/standardLayouts/groovy",files="settings.gradle[tags=hierarchical-layout]"]
include::sample[dir="snippets/userguide/multiproject/standardLayouts/kotlin",files="settings.gradle.kts[tags=hierarchical-layout]"]
====

The `include` method takes project paths as arguments. The project path is assumed to be equal to the relative physical file system path. For example, a path 'services:api' is mapped by default to a folder 'services/api' (relative from the project root). You only need to specify the leaves of the tree. This means that the inclusion of the path 'services:hotels:api' will result in creating 3 projects: 'services', 'services:hotels' and 'services:hotels:api'.
More examples of how to work with the project path can be found in the DSL documentation of link:{groovyDslPath}++/org.gradle.api.initialization.Settings.html#org.gradle.api.initialization.Settings:include(java.lang.String[])++[Settings.include(java.lang.String[\])].

[[sec:flat_layouts]]
==== Flat layouts


.Flat layout
====
include::sample[dir="snippets/userguide/multiproject/standardLayouts/groovy",files="settings.gradle[tags=flat-layout]"]
include::sample[dir="snippets/userguide/multiproject/standardLayouts/kotlin",files="settings.gradle.kts[tags=flat-layout]"]
====

The `includeFlat` method takes directory names as an argument. These directories need to exist as siblings of the root project directory. The location of these directories are considered as child projects of the root project in the multi-project tree.

[[sub:modifying_element_of_the_project_tree]]
=== Modifying elements of the project tree

The multi-project tree created in the settings file is made up of so called _project descriptors_. You can modify these descriptors in the settings file at any time. To access a descriptor you can do:

.Lookup of elements of the project tree
====
include::sample[dir="snippets/userguide/multiproject/customLayout/groovy",files="settings.gradle[tags=lookup-project]"]
include::sample[dir="snippets/userguide/multiproject/customLayout/kotlin",files="settings.gradle.kts[tags=lookup-project]"]
====

Using this descriptor you can change the name, project directory and build file of a project.

.Modification of elements of the project tree
====
include::sample[dir="snippets/userguide/multiproject/customLayout/groovy",files="settings.gradle[tags=change-project]"]
include::sample[dir="snippets/userguide/multiproject/customLayout/kotlin",files="settings.gradle.kts[tags=change-project]"]
====

Look at the link:{javadocPath}/org/gradle/api/initialization/ProjectDescriptor.html[ProjectDescriptor] class in the API documentation for more information.

[[sec:initialization]]
== Initialization

How does Gradle know whether to do a single or multi-project build? If you trigger a multi-project build from a directory with a settings file, things are easy. But Gradle also allows you to execute the build from within any subproject taking part in the build.footnote:[Gradle supports partial multi-project builds (see <<multi_project_builds.adoc#multi_project_builds,Authoring Multi-Project Builds>>).] If you execute Gradle from within a project with no `settings.gradle` file, Gradle looks for a `settings.gradle` file in the following way:

* It looks in a directory called `master` which has the same nesting level as the current dir.
* If not found yet, it searches parent directories.
* If not found yet, the build is executed as a single project build.
* If a `settings.gradle` file is found, Gradle checks if the current project is part of the multi-project hierarchy defined in the found `settings.gradle` file. If not, the build is executed as a single project build. Otherwise a multi-project build is executed.

What is the purpose of this behavior? Gradle needs to determine whether the project you are in is a subproject of a multi-project build or not. Of course, if it is a subproject, only the subproject and its dependent projects are built, but Gradle needs to create the build configuration for the whole multi-project build (see <<multi_project_builds.adoc#multi_project_builds,Authoring Multi-Project Builds>>). If the current project contains a `settings.gradle` file, the build is always executed as:

* a single project build, if the `settings.gradle` file does not define a multi-project hierarchy
* a multi-project build, if the `settings.gradle` file does define a multi-project hierarchy.

The automatic search for a `settings.gradle` file only works for multi-project builds with a physical hierarchical or flat layout. For a flat layout you must additionally follow the naming convention described above (“`master`”). Gradle supports arbitrary physical layouts for a multi-project build, but for such arbitrary layouts you need to execute the build from the directory where the settings file is located. For information on how to run partial builds from the root, see <<multi_project_builds.adoc#sec:running_partial_build_from_the_root,Running tasks by their absolute path>>.

Gradle creates a Project object for every project taking part in the build. For a multi-project build these are the projects specified in the Settings object (plus the root project). Each project object has by default a name equal to the name of its top level directory, and every project except the root project has a parent project. Any project may have child projects.

[[sec:configuration_and_execution_of_a_single_project_build]]
== Configuration and execution of a single project build

For a single project build, the workflow of the _after initialization_ phases are pretty simple. The build script is executed against the project object that was created during the initialization phase. Then Gradle looks for tasks with names equal to those passed as command line arguments. If these task names exist, they are executed as a separate build in the order you have passed them. The configuration and execution for multi-project builds is discussed in <<multi_project_builds.adoc#multi_project_builds,Authoring Multi-Project Builds>>.

[[build_lifecycle_events]]
== Responding to the lifecycle in the build script

Your build script can receive notifications as the build progresses through its lifecycle. These notifications generally take two forms: You can either implement a particular listener interface, or you can provide a closure to execute when the notification is fired. The examples below use closures. For details on how to use the listener interfaces, refer to the API documentation.


[[sec:project_evaluation]]
=== Project evaluation

You can receive a notification immediately before and after a project is evaluated. This can be used to do things like performing additional configuration once all the definitions in a build script have been applied, or for some custom logging or profiling.

Below is an example which adds a `test` task to each project which has a `hasTests` property value of true.

.Adding of test task to each project which has certain property set
====
include::sample[dir="snippets/userguide/buildlifecycle/projectEvaluateEvents/groovy",files="build.gradle[tags=after-evaluate];projectA.gradle[]"]
include::sample[dir="snippets/userguide/buildlifecycle/projectEvaluateEvents/kotlin",files="build.gradle.kts[tags=after-evaluate];projectA.gradle.kts[]"]
====

.Output of `gradle -q test`
----
> gradle -q test
include::{samplesPath}/userguide/buildlifecycle/projectEvaluateEvents/projectEvaluateEvents.out[]
----

This example uses method `Project.afterEvaluate()` to add a closure which is executed after the project is evaluated.

It is also possible to receive notifications when any project is evaluated. This example performs some custom logging of project evaluation. Notice that the `afterProject` notification is received regardless of whether the project evaluates successfully or fails with an exception.

.Notifications
====
include::sample[dir="snippets/userguide/buildlifecycle/buildProjectEvaluateEvents/groovy",files="build.gradle[tags=evaluate-events]"]
include::sample[dir="snippets/userguide/buildlifecycle/buildProjectEvaluateEvents/kotlin",files="build.gradle.kts[tags=evaluate-events]"]
====

==== Output of **`gradle -q test`**
[source.multi-language-sample,groovy]
----
> gradle -q test
include::{samplesPath}/userguide/buildlifecycle/buildProjectEvaluateEvents/buildProjectEvaluateEvents.groovy.out[]
----
[source.multi-language-sample,kotlin]
----
> gradle -q test
include::{samplesPath}/userguide/buildlifecycle/buildProjectEvaluateEvents/buildProjectEvaluateEvents.kotlin.out[]
----

You can also add a link:{javadocPath}/org/gradle/api/ProjectEvaluationListener.html[ProjectEvaluationListener] to the link:{groovyDslPath}/org.gradle.api.invocation.Gradle.html[Gradle] to receive these events.

[[sec:task_creation]]
=== Task creation

You can receive a notification immediately after a task is added to a project. This can be used to set some default values or add behaviour before the task is made available in the build file.

The following example sets the `srcDir` property of each task as it is created.

.Setting of certain property to all tasks
====
include::sample[dir="snippets/userguide/buildlifecycle/taskCreationEvents/groovy",files="build.gradle[]"]
include::sample[dir="snippets/userguide/buildlifecycle/taskCreationEvents/kotlin",files="build.gradle.kts[]"]
====

.Output of **`gradle -q a`**
----
> gradle -q a
include::{samplesPath}/userguide/buildlifecycle/taskCreationEvents/taskCreationEvents.out[]
----

You can also add an link:{javadocPath}/org/gradle/api/Action.html[Action] to a link:{javadocPath}/org/gradle/api/tasks/TaskContainer.html[TaskContainer] to receive these events.

[[sec:task_execution_graph_ready]]
=== Task execution graph ready

You can receive a notification immediately after the task execution graph has been populated (See <<tutorial_using_tasks.adoc#configure-by-dag,Configure by DAG>>).

You can also add a link:{javadocPath}/org/gradle/api/execution/TaskExecutionGraphListener.html[TaskExecutionGraphListener] to the link:{javadocPath}/org/gradle/api/execution/TaskExecutionGraph.html[TaskExecutionGraph] to receive these events.

[[sec:task_execution]]
=== Task execution

You can receive a notification immediately before and after any task is executed.

The following example logs the start and end of each task execution. Notice that the `afterTask` notification is received regardless of whether the task completes successfully or fails with an exception.

.Logging of start and end of each task execution
====
include::sample[dir="snippets/userguide/buildlifecycle/taskExecutionEvents/groovy",files="build.gradle[]"]
include::sample[dir="snippets/userguide/buildlifecycle/taskExecutionEvents/kotlin",files="build.gradle.kts[]"]
====

==== Output of **`gradle -q broken`**
[source.multi-language-sample,groovy]
----
> gradle -q broken
include::{samplesPath}/userguide/buildlifecycle/taskExecutionEvents/taskExecutionEvents.groovy.out[]
----
[source.multi-language-sample,kotlin]
----
> gradle -q broken
include::{samplesPath}/userguide/buildlifecycle/taskExecutionEvents/taskExecutionEvents.kotlin.out[]
----

You can also use a link:{javadocPath}/org/gradle/api/execution/TaskExecutionListener.html[TaskExecutionListener] to the link:{javadocPath}/org/gradle/api/execution/TaskExecutionGraph.html[TaskExecutionGraph] to receive these events.
