When would you reach for the `distribution` plugin to package arbitrary content instead of the `application` plugin, and how do they relate?
answer
- application applies distribution + java
- application => start scripts + classpath + run
- distribution alone = archive only, no launcher
- combine: app main + create(docs)
- raw Zip task = no installDist/lifecycle wiring
basics
~10 sUse distribution when you just need to ship arbitrary files (docs, configs) as an archive with no runtime/launcher. The application plugin is for runnable JVM apps and is built on top of distribution.
solid answer
~40 sThe `application` plugin **applies** the `distribution` plugin internally and configures its `main` distribution to hold the app jar, runtime classpath, and generated start scripts (`bin/<app>` and `bin/<app>.bat`). So it gives you a *runnable* layout: `installDist`, `run`, `distZip`. The bare `distribution` plugin gives you the same archive machinery with **no application semantics** — no `mainClass`, no start scripts, no classpath assembly. You reach for `distribution` directly when the artifact isn't a runnable program: a documentation bundle, a set of config templates, a sample/data pack, SDK headers, or a side-car archive alongside your app. You can even apply both: keep `application` for the runnable `main` distribution and add extra named distributions (`distributions.create("docs")`) for non-code content. Choosing `distribution` avoids paying for launcher generation you don't want.
go deeper
Knows application is for runnable apps and distribution is for arbitrary archives.
Can articulate that application is built on distribution, what each pre-configures, and when to pick which.
Can combine both for app + side-car archives and justify distribution over a raw Zip task by the conventions it adds.
Defines the org packaging strategy: which artifacts ship as distributions, how docs/config bundles are standardized, and reproducibility across teams.
## Two plugins, one engine Both plugins produce archives via the same `distributions` container and `CopySpec` engine. The difference is **how much they pre-configure**. ### `application` plugin Applying `application`: 1. Applies the `java` and `distribution` plugins. 2. Configures the `main` distribution's `contents` to include: the project jar (`lib/`), the runtime dependencies (`lib/`), and OS start scripts (`bin/`). 3. Adds `run` (launch from build), `startScripts` (generate launchers), `installDist` (explode to `build/install`), and `distZip`/`distTar`. 4. Requires `application { mainClass.set(...) }`. So it's opinionated toward a **runnable JVM program**. ### `distribution` plugin Applying `distribution` alone: 1. Adds the `distributions` container with an empty `main`. 2. Adds `assembleDist`, `installDist`, and per-distribution `*DistZip`/`*DistTar`. 3. Configures **nothing** about contents — you declare everything via `contents { }`. No `mainClass`, no scripts, no classpath. Pure archive packaging. ### Decision guide | Need | Plugin | |---|---| | Runnable CLI/server with launcher scripts | `application` | | Docs/config/sample bundle, no executable | `distribution` | | Both a runnable app AND extra side-car archives | `application` + extra `distributions.create(...)` | | Fat/uber jar | Shadow plugin (separate concern) | ### Combining them ```kotlin plugins { application distribution // implied by application, but harmless } application { mainClass.set("com.acme.Main") } distributions { // 'main' already configured by the application plugin create("docs") { contents { from("src/docs") } } } ``` Now `distZip` ships the runnable app and `docsDistZip` ships the documentation — two independent archives from one build. ### Why not just use a Zip task? You *can* register a raw `Zip` task. The distribution plugin adds value: a named container, `installDist` (an exploded view for local testing), lifecycle wiring into `assemble`, and a consistent naming convention. For one-off archives a `Zip` task is fine; for a first-class shippable artifact, distributions are cleaner.
- Can you have a runnable app and a docs-only archive in the same project?Yes. Apply `application` (which configures the `main` runnable distribution) and add `distributions.create("docs") { contents { ... } }`. You then get `distZip` for the app and `docsDistZip` for the docs — two independent archives.
- What does the `distribution` plugin give you over a raw `Zip` task?A named distributions container, `installDist` for an exploded local-test view, automatic `*DistZip`/`*DistTar` task pairs, consistent archive naming with classifiers, and wiring into the `assemble`/`build` lifecycle. A raw `Zip` task is fine for one-offs but lacks these conventions.
saying these in an interview costs you the question
- Saying the application plugin doesn't use distributions — it's built on the distribution plugin.
- Using the application plugin and then fighting it to remove start scripts, when you really wanted the bare distribution plugin.