At a high level, what is the build configuration phase, and where do project evaluation hooks like afterEvaluate fit within it?
answer
- three phases: init, config, execution
- configuration registers tasks, no actions
- beforeEvaluate before script, afterEvaluate after
- hooks finish before execution
- apply() is early in configuration
basics
~20 sThe configuration phase is when Gradle reads every project's build script and registers tasks (but doesn't run them). Project evaluation hooks like afterEvaluate run at the tail of this phase, right after a project's script has been read.
solid answer
~40 sA Gradle build has three phases: **initialization** (decide which projects participate, create Project objects), **configuration** (evaluate each project's build script and build the task graph — tasks are registered/configured, not executed), and **execution** (run the requested tasks). Project evaluation hooks belong to the **configuration** phase: `project.beforeEvaluate` fires just before a project's script is evaluated, and `project.afterEvaluate` fires just after. They let plugins or scripts run logic that depends on the script having been (or about to be) processed — for example, reading an extension that the user configured. They run during configuration, so they happen before any task action executes. Knowing this placement explains why reading user-set values is safe in afterEvaluate but not at plugin-apply time.
go deeper
Name the three phases and state that afterEvaluate runs at the end of configuration for a project.
Explain the before/after-script ordering and why afterEvaluate is the safe place to read user-set values.
Connect placement to why apply-time reads fail and how configuration-phase cost matters for build performance.
Use the phase model to reason about configuration-time budget, configuration cache, and where to minimize eager work across a large build.
## The three build phases Every Gradle build proceeds through three phases: 1. **Initialization** — Gradle evaluates `settings.gradle(.kts)`, decides which projects are part of the build, and creates a `Project` instance for each. 2. **Configuration** — Gradle evaluates **every** participating project's build script top-to-bottom. This **registers and configures tasks** and builds the **task (dependency) graph**. Crucially, no task *actions* run yet — declaring `tasks.register("foo") { ... }` configures the task but does not execute it. 3. **Execution** — Gradle runs the tasks you asked for (and their dependencies), in dependency order. Task `@TaskAction` methods / `doLast`/`doFirst` blocks run here. ## Where evaluation hooks live Project **evaluation hooks** are part of the **configuration** phase: - `project.beforeEvaluate { }` — runs immediately **before** that project's build script is evaluated. - `project.afterEvaluate { }` — runs immediately **after** that project's build script has been evaluated. So for one project the order is: `beforeEvaluate` → evaluate the build script → `afterEvaluate`. ```kotlin project.beforeEvaluate { println("about to read this project's script") } project.afterEvaluate { println("this project's script is fully read") } ``` ## Why the placement matters Because these hooks run during configuration — and `afterEvaluate` specifically runs *after* the script — they are the right place to read values that the build script set (like extension properties). At **plugin-apply** time (earlier in configuration) those values aren't set yet. And because they all run in configuration, they finish **before** any task executes, so they cannot depend on task outputs. ## Quick mental model - Initialization: *which* projects. - Configuration: *what* tasks exist and how they depend on each other (evaluation hooks here). - Execution: *do* the work.
- Do task actions run during the configuration phase?No — configuration only registers and configures tasks and builds the graph. Task actions (doLast/@TaskAction) run later, in the execution phase.
- Which runs first, a plugin's apply() or that project's afterEvaluate?apply() runs first (early in configuration); afterEvaluate fires later, after the whole build script has been evaluated.
Configuration is like setting up a recipe and ordering ingredients (deciding the steps) — execution is actually cooking. afterEvaluate is the moment right after you've finished reading the whole recipe card, before you turn on the stove.
saying these in an interview costs you the question
- Saying configuration runs task actions — it only configures the task graph.
- Placing afterEvaluate in the execution phase.
- Thinking initialization evaluates build scripts — it evaluates settings and creates Project objects.