What is Gradle DAG (Directed Acyclic Graph)?

What is DAG (Directed Acyclic Graph)
In computer science and mathematics, a directed acyclic graph (DAG) is a graph that is directed and without cycles connecting the other edges. This means that it is impossible to traverse the entire graph starting at one edge. The edges of the directed graph only go one way. The graph is a topological sorting, where each node is in a certain order.

Understanding DAG (Directed Acyclic Graph) in Gradle

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 Directed Acyclic Graph. Gradle builds the complete dependency graph before any task is executed. Gradle models its builds as Directed Acyclic Graphs (DAGs) of tasks (units of work).

What this means is that a build essentially configures a set of tasks and wires them together — based on their dependencies — to create that DAG. Once the task graph has been created, Gradle determines which tasks need to be run in which order and then proceeds to execute them.

In order to understand “Directed Acyclic Graphs” DAG, we need to understand a Gradle build lifecycle.

Gradle build lifecycle consist of three phases: initialization, configuration, and execution:

The initialization phase with settings.gradle

During Initialization, Gradle decides which projects are to participate in the build.

In this phase, Gradle tries to identify all the projects involved in the build process. It is very important for Gradle to know whether it’s a Single-project build or a Multi-project build. In a Multi-project build there are several projects to evaluate. Hence, several build scripts. Gradle looks at the settings.gradle file in order to identify the different projects. At the end of the initialization phase, Gradle creates an instance of org.gradle.api.Project corresponding to each of these projects.

The configuration phase with build.gradle

During Configuration, task objects are assembled into an internal object model, usually called the DAG (for directed acyclic graph).

During this phase, Gradle executes the build script of each project identified in the previous phase. Actually, it is very important to know that just because we say “Gradle executes the build scripts” does not mean that the Tasks in those build scripts are executed too. Instead, after evaluating those scripts as simple Groovy scripts and identify the tasks in it, Gradle builds a Directed Acyclic Graph (DAG) of task objects. A DAG is a mathematical algorithm for representing a graph that contains no cycles. The “directed” term means each dependency arrow goes in one direction. “Acyclic” means that there are no loops in the graph.

The execution phase with doLast and doFirst

During Execution, build tasks are executed in the order required by their dependency relationships.

In nutshell,

  • If you put a code in the settings.gradle file, it is evaluated in the initialization phase
  • The code in your build script files that are not related to actions of your tasks are evaluated in the configuration phase.
  • The code in the actual actions of your tasks like the doLast closures of your tasks are evaluated in the execution phase.

Single project build Example of Gradle DAG (Directed Acyclic Graph)

Output of gradle test

> gradle test

E:\gra>gradle test
This is executed during the initialization phase.

> Configure project :
This is executed during the configuration phase.
This is also executed during the configuration phase.
This is executed during the execution phase.

> Task :test
This is executed during the execution phase with doFirst
This is executed during the execution phase with doLast

BUILD SUCCESSFUL in 1s
1 actionable task: 1 executed

To list task dependencies in Gradle?

$ gradle dependencies - Displays all dependencies declared in root project 'gra'.
$ gradle dependencyInsight - Displays the insight into a specific dependency in root project 'gra'.
$ gradle dependentComponents - Displays the dependent components of components in root project 'gra'. [incubating]

Only lists dependencies in master project  
$ gradle dependencies
$ gradle dependencies --scan

Lists subproject dependencies in project
$  gradle :<subproject>:dependencies
$ ./gradlew app:dependencies	# where app is your project module.

If you want to see dependencies on project and all subprojects use in your top-level build.gradle:
subprojects {
    task listAllDependencies(type: DependencyReportTask) {}
}

Then call gradle:
$ gradle listAllDependencies
Rajesh Kumar
Follow me