What lifecycle hooks and APIs does the Settings object expose that a Settings plugin can use beyond repository/project setup?
answer
- settings.gradle = Gradle object
- settingsEvaluated / projectsLoaded / projectsEvaluated
- buildCache {} centralization
- rootProject descriptor tree
- enableFeaturePreview, allprojects
basics
~10 sBeyond 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 sThe `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 linesoverride 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
Know the Settings object can do more than include — e.g. set rootProject.name and configure the build cache.
Name the main lifecycle hooks (settingsEvaluated, projectsLoaded, projectsEvaluated) and when they fire.
Explain centralizing buildCache and cross-project conventions via a settings plugin, plus configuration-cache caveats of imperative hooks.
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.