skip to content

Explain the difference between the settings (initialization) phase and the build (configuration/execution) phases. When does the settings script run relative to build scripts?

level: middleimportance: must knowfreq 64%

answer

  1. init → configuration → execution
  2. settings = init phase, once, first
  3. settings can't see tasks/configurations
  4. include only works in settings
  5. settingsEvaluated / projectsLoaded hooks

basics

~10 s

Gradle runs in three phases: initialization, configuration, execution. The settings script runs in initialization — first, before any build.gradle. It decides which projects exist; build scripts then configure each project during configuration.

solid answer

~40 s

A Gradle build has three lifecycle phases. **Initialization** comes first: Gradle finds the build root, evaluates the **settings script** to build the `Settings` object, and creates the `Project` instances for the root and every included project. **Configuration** runs next: every `build.gradle(.kts)` is evaluated to configure its `Project` and register tasks (this happens for all projects, even ones you didn't ask to build). **Execution** runs last: only the tasks needed for the requested goals (and their dependencies) actually run. The key consequence: the settings script executes exactly once, *before* any build script, so it cannot reference task outputs or project configuration — it only declares structure. Anything that depends on which projects exist must live in settings; anything that configures a project lives in its build script.

code

kotlin · 5 lines
kotlin
// settings.gradle.kts — initialization phase
rootProject.name = "shop"
include(":api")
gradle.settingsEvaluated { logger.lifecycle("INIT: settings parsed") }
gradle.projectsLoaded { logger.lifecycle("INIT: ${rootProject.allprojects.size} projects") }

go deeper

for a junior

Name the three phases in order and know settings runs first.

for a middle

Explain what each phase does, that settings runs once before all build scripts, and why include must live in settings.

for a senior

Distinguish configuration-time vs execution-time code, cite the lifecycle hooks, and relate the phase model to configuration avoidance.

for a principal

Discuss how the phase model drives performance strategy (configuration cache, project isolation, configuration-on-demand) across a large monorepo.

## The three phases Every Gradle invocation moves through three phases in strict order: 1. **Initialization phase** — Gradle locates the build root (the directory whose `settings.gradle(.kts)` is in effect), evaluates the **settings script**, and from the resulting `Settings` object instantiates a `Project` for the root project and each `include`d/`includeBuild` project. No build script has run yet. 2. **Configuration phase** — Gradle evaluates **every** project's `build.gradle(.kts)`, building the task graph by *registering* tasks and applying plugins. Crucially this happens for all projects in the build, not just the one you targeted (unless configuration-on-demand or project isolation narrows it). 3. **Execution phase** — Gradle determines the subset of registered tasks required by the requested task names, orders them by dependencies, and runs their actions. ## Where the settings script sits The settings script is the *only* thing that runs in the initialization phase. Therefore: - It runs **exactly once**, **before** any `build.gradle`. - It cannot see tasks, configurations, or anything a build script sets up — those don't exist yet. - It is the *only* place to change the **set of projects** (`include`, `includeBuild`, relocation). You cannot add a project from a build script. ```kotlin // settings.gradle.kts (initialization phase) rootProject.name = "shop" include(":api", ":web") gradle.settingsEvaluated { println("settings done") } // init hook gradle.projectsLoaded { println("projects created") } // end of init // api/build.gradle.kts (configuration phase) — runs LATER tasks.register("hello") { doLast { println("exec phase") } } ``` ## Lifecycle hooks tied to the boundary Gradle exposes hooks at the seams: `gradle.settingsEvaluated` (settings script finished), `gradle.projectsLoaded` (Project objects created — end of init), `gradle.beforeProject`/`afterProject` (around each configuration), and `gradle.buildFinished`. These let you observe the transition from init to configuration. ## Why it matters practically Because settings runs first and once, expensive or environment-sensitive *structure* decisions (which modules to include, where they live) belong there. Conversely, never try to read a project property or task output in settings — it hasn't been configured. Mixing these up is a classic source of "cannot get property" or null errors. ## Configuration vs execution distinction A subtle but commonly tested point: code in the *body* of a build script runs at **configuration** time (for every build, regardless of whether the task runs); code inside `doLast {}` / `doFirst {}` runs at **execution** time, only when the task is actually executed. The settings script body is earlier still — pure initialization.

  • Why can't you call include() from a build.gradle?
    include adds a project to the build, which must happen during initialization while the project set is still being built. By the time a build.gradle runs, the configuration phase has started and the Project instances already exist — the set is frozen.
  • Does code in a build script body run during configuration or execution?
    The script body runs at configuration time, for every build, even if the task never executes. Only code inside task actions (doFirst/doLast) runs at execution time, and only when that task is actually run.
  • Which hook fires right after the settings script finishes?
    gradle.settingsEvaluated fires once the settings script is fully evaluated; gradle.projectsLoaded fires slightly later, after the Project objects are created — both are still in the initialization phase.

saying these in an interview costs you the question

  • Saying the settings script runs alongside or after build scripts — it runs strictly before, in initialization.
  • Claiming configuration only happens for the targeted project — by default all projects are configured.
  • Trying to access task outputs or project properties from the settings script.

context