skip to content

What lifecycle hooks and APIs does the Settings object expose that a Settings plugin can use beyond repository/project setup?

level: seniorimportance: nice to knowfreq 25%

answer

  1. settings.gradle = Gradle object
  2. settingsEvaluated / projectsLoaded / projectsEvaluated
  3. buildCache {} centralization
  4. rootProject descriptor tree
  5. enableFeaturePreview, allprojects

basics

~10 s

Beyond include and resolution blocks, a Settings plugin can use settings.gradle hooks like settingsEvaluated, projectsLoaded, and projectsEvaluated, configure buildCache, set rootProject properties, enableFeaturePreview, and iterate rootProject to apply per-project conventions.

solid answer

~40 s

The `Settings` object exposes more than `include`/`pluginManagement`/DRM. A `Plugin<Settings>` can reach the `Gradle` object via `settings.gradle` and register **initialization-phase lifecycle hooks**: `settingsEvaluated {}` (after settings is fully evaluated), `projectsLoaded {}` (after the project hierarchy is created but before configuration), and `projectsEvaluated {}` (after all projects configured). It can configure `buildCache {}` (local/remote cache), set `rootProject.name` and walk `settings.rootProject` descendants to set conventions like project directories, call `enableFeaturePreview(...)`, and apply common configuration to every project via `gradle.beforeProject {}`/`afterProject {}` or `gradle.allprojects {}`. These let a settings convention plugin inject behavior across the whole build — e.g. wiring the remote build cache or applying a base plugin to all projects — that a Project plugin can't do centrally.

code

kotlin · 11 lines
kotlin
override fun apply(settings: Settings) {
    settings.gradle.projectsLoaded {
        rootProject.allprojects {
            // seed a convention onto every project before configuration
            group = "com.example"
        }
    }
    settings.buildCache {
        local { isEnabled = true }
    }
}

go deeper

for a junior

Know the Settings object can do more than include — e.g. set rootProject.name and configure the build cache.

for a middle

Name the main lifecycle hooks (settingsEvaluated, projectsLoaded, projectsEvaluated) and when they fire.

for a senior

Explain centralizing buildCache and cross-project conventions via a settings plugin, plus configuration-cache caveats of imperative hooks.

for a principal

Govern whole-build concerns org-wide (remote cache, feature previews, base conventions) through a settings plugin while staying compatible with configuration cache / isolated projects.

## The Settings object's reach A `Plugin<Settings>` isn't limited to declaring projects and repositories. Through `settings` and `settings.gradle` (the `Gradle` instance) it can hook the initialization phase and influence every project. ## Lifecycle hooks (initialization phase) - **`settings.gradle.settingsEvaluated {}`** — fires once `settings.gradle` has been fully evaluated. Good for validating/finalizing settings. - **`settings.gradle.projectsLoaded {}`** — fires after the `Project` hierarchy is created (descriptors instantiated) but before any build script runs. Useful to seed conventions onto projects. - **`settings.gradle.beforeProject {}` / `afterProject {}`** — run code around each project's configuration. - **`settings.gradle.projectsEvaluated {}`** — fires after all projects are configured; good for cross-project wiring. ## Other Settings APIs - **`buildCache {}`** — configure local and remote build cache (often centralized here so every repo shares one remote cache node). - **`rootProject.name`** and the `ProjectDescriptor` tree under `settings.rootProject` — rename, relocate (`projectDir`), or restructure projects. - **`enableFeaturePreview("...")`** — opt into preview features (e.g. type-safe project accessors). - **`settings.gradle.allprojects {}` / `rootProject {}`** — apply common project configuration centrally. - **`settings.extensions`** — add a settings-level extension to expose typed configuration DSL from your plugin. ## Example: centralize the build cache and a base plugin ```kotlin class PlatformSettingsPlugin : Plugin<Settings> { override fun apply(settings: Settings) { settings.buildCache { remote(HttpBuildCache::class.java) { url = uri("https://cache.example.com/cache/") isPush = System.getenv("CI") != null } } settings.gradle.allprojects { // applies to every project once it is configured plugins.apply("base") } } } ``` ## Why this matters These hooks are why a settings plugin is the lever for *whole-build* concerns — caching, cross-project conventions, feature previews — that no single Project plugin can centralize. Note that the configuration cache constrains some of these hooks; prefer the structured APIs (buildCache, dependency/plugin management) over ad-hoc Gradle-object listeners where possible.

  • Why configure the build cache in a settings plugin rather than each project?
    The build cache is a whole-build concern set on Settings; configuring it once in a settings plugin gives every project and repo the same local/remote cache without duplication.
  • What's the risk of using gradle.beforeProject/allprojects listeners heavily?
    They are imperative cross-project hooks that can hurt the configuration cache and isolated-projects efforts; prefer structured Settings APIs and convention plugins where possible.

saying these in an interview costs you the question

  • Thinking buildCache is configured per project in build.gradle — it's a Settings-level block.
  • Assuming projectsLoaded runs after configuration — it runs after the project hierarchy is created but before build scripts evaluate.

context