skip to content

How are distZip and distTar wired into the build lifecycle, and how does assembleDist fit in?

level: middleimportance: should knowfreq 35%

answer

  1. assembleDist dependsOn distZip + distTar
  2. assemble -> assembleDist; build -> assemble
  3. implicit deps on jar + startScripts + runtimeClasspath
  4. named dist => <name>DistZip + assemble<Name>Dist
  5. lifecycle vs work tasks

basics

~10 s

The distribution plugin adds assembleDist, which depends on distZip and distTar. It wires assembleDist into assemble/build, so ./gradlew build produces both archives. Run assembleDist to build only the distribution archives.

solid answer

~40 s

When the distribution plugin (via `application`) is applied, it registers `distZip` (Zip), `distTar` (Tar), and an aggregate **`assembleDist`** lifecycle task that `dependsOn` both. `assembleDist` is itself wired into the standard `assemble` lifecycle task, and `build` depends on `assemble` — so a plain `./gradlew build` builds the archives. For multiple named distributions, each gets `<name>DistZip`/`<name>DistTar` and an `assemble<Name>Dist`, while the top-level `assembleDist` aggregates all of them. The archive tasks also `dependsOn` the things that feed them — `jar`, dependency resolution of `runtimeClasspath`, and `startScripts` — because the CopySpec references those outputs. So the dependency chain is: `build` → `assemble` → `assembleDist` → (`distZip`, `distTar`) → (`jar`, `startScripts`).

code

bash · 5 lines
bash
# Build only the distribution archives (no tests):
./gradlew assembleDist

# The full graph for a single dist:
# build -> assemble -> assembleDist -> distZip, distTar -> jar, startScripts

go deeper

for a junior

Know assembleDist builds both archives and that build produces them.

for a middle

Lay out the build -> assemble -> assembleDist -> distZip/distTar chain and the implicit jar/startScripts deps.

for a senior

Explain lifecycle vs work tasks, implicit task dependencies via output providers, and multi-distribution aggregation.

for a principal

Decide whether release CI should call assembleDist vs build, and how packaging fits a multi-module/multi-distribution release pipeline.

## Lifecycle tasks vs. work tasks Gradle distinguishes **lifecycle** tasks (no action of their own, just aggregate other tasks via `dependsOn`) from **work** tasks (do real work). `assemble`, `build`, and `assembleDist` are lifecycle tasks; `distZip`/`distTar`/`jar`/`startScripts` do real work. ## What the distribution plugin wires For the `main` distribution the plugin registers: - `distZip` (type `Zip`) - `distTar` (type `Tar`) - `installDist` (unpacks the same contents into `build/install/<name>`) - `assembleDist` — a lifecycle task with `dependsOn(distZip, distTar)` It then makes `assemble.dependsOn(assembleDist)` (assemble comes from the base plugin). Since `build.dependsOn(assemble)`, the full graph is: ``` build └─ assemble └─ assembleDist ├─ distZip ──┐ └─ distTar ──┤ (both depend on) ├─ jar ├─ startScripts └─ resolve runtimeClasspath ``` ## Implicit input dependencies You don't hand-wire `distZip.dependsOn(jar)`. Because the distribution's `CopySpec` includes `jar.archiveFile`, the configuration-cache/task-graph machinery infers a task dependency from the producer (`jar`) to the consumer (`distZip`). Same for `startScripts` and for the resolved `runtimeClasspath` files. This is the *implicit task dependency* mechanism — referencing another task's output provider carries its dependency. ## Multiple distributions If you declare extra distributions: ```kotlin distributions { create("docs") { contents { from("src/docs") } } } ``` you get `docsDistZip`, `docsDistTar`, and `assembleDocsDist`. The single top-level `assembleDist` then depends on the zip+tar of **all** distributions, so `assembleDist` builds everything. ## Practical commands - `./gradlew assembleDist` — just the archives, skipping tests. - `./gradlew distZip` — only the zip. - `./gradlew build` — archives + tests + verification.

  • Why don't you need to manually add `distZip.dependsOn(jar)`?
    The distribution CopySpec references `jar`'s output provider, so Gradle infers the task dependency automatically (implicit task dependency).
  • If you add a second distribution named `docs`, what tasks appear and what does top-level assembleDist do?
    `docsDistZip`, `docsDistTar`, `assembleDocsDist` appear; the top-level `assembleDist` aggregates the zip/tar of all distributions.

saying these in an interview costs you the question

  • Claiming you must manually wire distZip's dependencies on jar/startScripts.
  • Saying assembleDist runs tests — it's a packaging lifecycle task; only `build`/`check` pull in tests.

context