skip to content

Base and Lifecycle-Base Plugins

The assemble, check, build, and clean lifecycle tasks and the archives configuration other plugins attach to. Asked because it explains why `gradle build` works in a project whose plugins you have never seen before.

on this pageshow

questions

5

What lifecycle tasks does the Gradle 'base' plugin contribute, and what does each one mean?

level: juniorimportance: must knowfreq 70%

answer

  1. assemble = artifacts, no checks
  2. check = verification, no artifacts
  3. build = assemble + check
  4. clean = delete buildDirectory
  5. lifecycle tasks have no actions

basics

~10 s

The base plugin adds 'assemble' (build all artifacts), 'check' (run all verification like tests), 'build' (assemble + check together), and 'clean' (delete the build directory).

solid answer

~40 s

Applying the `base` plugin contributes four standard lifecycle tasks. **`assemble`** produces all the build's outputs/artifacts (e.g. archives) but runs no verification. **`check`** runs all verification tasks (tests, linters) without producing artifacts. **`build`** is the umbrella task that depends on both `assemble` and `check` — it's the default 'do everything' entry point. **`clean`** deletes the project's `layout.buildDirectory`. These are *lifecycle* tasks: they carry no actions themselves, they just aggregate work by depending on other tasks. Other plugins (like `java`) hook into them — e.g. `jar` becomes a dependency of `assemble`, and `test` becomes a dependency of `check`. This convention is why `gradle build` behaves consistently across very different project types.

code

kotlin · 10 lines
kotlin
plugins { base }

// A custom artifact task hooked into the lifecycle
val bundle by tasks.registering(Zip::class) {
    from("src/dist")
    archiveFileName.set("app.zip")
}

tasks.named("assemble") { dependsOn(bundle) }
// now `gradle build` -> assemble (runs bundle) + check

go deeper

for a junior

Name the four tasks and say one sentence each. Knowing assemble=artifacts, check=verify, build=both, clean=delete is enough.

for a middle

Explain that they are action-less lifecycle tasks and that build = assemble + check, plus how java wires jar/test into them.

for a senior

Discuss the lifecycle-base vs base split, the archives configuration, and how custom plugins should hook into the lifecycle rather than redefine it.

for a principal

Frame the lifecycle as a cross-project contract that makes gradle build uniform across heterogeneous modules, and a governance lever for org-wide build conventions.

## What the base plugin is The `base` plugin is one of Gradle's most foundational core plugins. It does not know anything about Java, Kotlin, or any language. Its entire job is to establish the **standard build lifecycle** — a small set of well-known, empty 'umbrella' tasks that every other plugin can attach work to. Because of this convention, `gradle build` means the same thing whether you're building a Java library, a C++ binary, or a documentation site. Internally `base` is split: it applies `lifecycle-base` (which contributes the lifecycle tasks and the `clean` task) and then layers on the archive/artifact conventions (the `archives` configuration, base archive naming via the `base { }` extension). ## The four lifecycle tasks These are **lifecycle tasks**: tasks with no `@TaskAction` of their own. They exist purely to depend on real work tasks, so running them runs everything wired into them. - **`assemble`** — aggregates all tasks that *produce* the project's artifacts. It performs no verification. With the `java` plugin, `jar` is wired in as a dependency, so `assemble` builds the JAR. - **`check`** — aggregates all *verification* tasks. With `java`, the `test` task is wired in. Running `check` runs your tests but does not build distributables. - **`build`** — depends on **both** `assemble` and `check`. It is the canonical 'build the whole thing and verify it' entry point. (Note: `build` is *not* the same as the `build` *directory*.) - **`clean`** — a `Delete` task that removes `layout.buildDirectory` (by default `build/`). `lifecycle-base` also lets plugins register `clean<TaskName>` rules so individual outputs can be cleaned. ## How other plugins hook in The power is in the wiring. A plugin doesn't redefine the lifecycle — it *contributes* to it: ```kotlin tasks.named("assemble") { dependsOn(myArtifactTask) } tasks.named("check") { dependsOn(myVerificationTask) } ``` This is why a single `gradle build` invocation in a multi-language project does the right thing for every plugin applied. ## The `archives` configuration `base` also creates the `archives` configuration. Artifacts added to it (e.g. via `artifacts { archives jarTask }`) are picked up by `assemble`. This is the legacy hook that older plugins used to register their outputs. ## Why it matters Most build authors apply `base` *transitively* (the `java` plugin applies it for you). You apply it directly when writing a custom plugin or a build that produces artifacts but isn't a JVM project, and you want the standard lifecycle vocabulary for free.

  • Does `assemble` run your tests?
    No. `assemble` only produces artifacts. Tests are verification and are wired into `check`. Only `build` (which depends on both) runs both.
  • What's the difference between the `build` task and the `build/` directory?
    Unrelated. `build` is a lifecycle task (assemble + check); `build/` is the default output directory (`layout.buildDirectory`) that `clean` deletes.

Think of the lifecycle tasks as labeled empty boxes on a shelf. Plugins drop their real work into the right box; running build just empties every box in order.

saying these in an interview costs you the question

  • Saying `assemble` runs tests — it explicitly does not.
  • Confusing the `build` task with the `build/` directory.
  • Thinking lifecycle tasks have their own actions rather than just aggregating dependencies.

context

open as a page

You wrote a custom task that packages a distribution. How do you make `gradle build` run it, and where should it hook?

level: middleimportance: must knowfreq 55%

basics

~10 s

Make assemble depend on your packaging task: tasks.named("assemble") { dependsOn(myTask) }. Since build depends on assemble, gradle build will then run it.

open as a page

What exactly does the `clean` task delete, and how do the `base { }` extension and `archives` configuration relate to it?

level: middleimportance: should knowfreq 40%

basics

~20 s

clean is a Delete task that removes the project's build directory (layout.buildDirectory, default build/). The base { } extension sets archive naming and output dirs; the archives configuration collects artifacts that assemble builds — both feed outputs under build/.

open as a page

What is the difference between the `base` plugin and the `lifecycle-base` plugin?

level: middleimportance: should knowfreq 45%

basics

~10 s

lifecycle-base is the smaller plugin that only adds the lifecycle tasks (assemble, check, build) and clean. base applies lifecycle-base and adds archive conventions like the archives configuration and the base { } naming extension.

open as a page

As a build platform owner, how do you leverage the base/lifecycle-base convention so heterogeneous modules (JVM, JS, docs) all respond uniformly to `gradle build` in CI?

level: seniorimportance: should knowfreq 30%

basics

~10 s

Ensure every module applies a plugin in the base family so it has assemble/check/build, then hook each module's real work into assemble (artifacts) or check (verification). CI then just runs gradle build everywhere.

open as a page