skip to content

How does the standalone `distribution` plugin relate to the `application` plugin, and when would you apply `distribution` on its own?

level: seniorimportance: should knowfreq 30%

answer

  1. application applies distribution
  2. application adds bin/ scripts + lib/ classpath to main
  3. same distZip/installDist tasks
  4. standalone = no main class needed
  5. docs/config/native bundles

basics

~20 s

The application plugin applies distribution under the hood and configures the main distribution to add launcher scripts and the runtime classpath. You apply distribution alone when you need to package arbitrary files into ZIP/TAR/install bundles without a runnable Java app.

solid answer

~40 s

`distribution` is a generic packaging primitive: a `distributions {}` container with a `main` distribution and `distZip`/`distTar`/`installDist` tasks over arbitrary `CopySpec` contents. The `application` plugin sits on top — it applies `distribution`, then mutates the existing `main` distribution's `contents` to include `bin/` start scripts (from `CreateStartScripts`) and `lib/` runtime jars. So an app project gets `installDist`/`distZip` "for free" because they are the same tasks from this plugin. You apply `distribution` standalone when there is no JVM main class to launch: shipping a docs bundle, a set of config templates, a CLI's native binaries, or any release archive where you simply want the plugin's conventional ZIP/TAR/exploded-install machinery without start scripts or a runtime classpath.

code

kotlin · 9 lines
kotlin
// standalone packaging, no runnable app:
plugins { id("distribution") }
distributions {
    main {
        distributionBaseName.set("acme-docs")
        contents { from("build/docs") }
    }
}
// installDist / distZip -> bundle of docs, no bin/ or lib/

go deeper

for a junior

Know that application builds on distribution and that distribution alone packages files.

for a middle

Explain that application configures main to add bin/ scripts and lib/ jars, reusing the same tasks.

for a senior

Decide which plugin to apply based on whether a runnable main class exists, and articulate the layering.

for a principal

Set conventions for when teams ship runnable apps vs. plain bundles and how packaging plugins compose with publishing.

## Two plugins, one machinery Gradle deliberately layers these: - **`distribution`** — knows only how to bundle files. It owns the `distributions {}` container, the `main` distribution, and the `distZip`/`distTar`/`installDist` task generation over each distribution's `CopySpec`. - **`application`** — applies `distribution` (and `java`), and adds JVM-app semantics: a `mainClass`, generated OS launcher scripts, and the runtime classpath. ## What `application` adds to `main` When you apply `application`, it reaches into the already-present `main` distribution and augments its `contents`: - `bin/` ← the start scripts produced by the `startScripts` (`CreateStartScripts`) task. - `lib/` ← the project's runtime classpath jars. - the root ← anything you already had under `src/main/dist`. That is why `./gradlew installDist` on an application project yields a `bin/`+`lib/` layout you can run, while the same task on a bare `distribution` project yields only whatever you configured into `contents`. ```kotlin // application reuses the distribution plugin's tasks plugins { application // applies `distribution` transitively } application { mainClass.set("com.acme.Main") } // installDist now produces bin/<app> + lib/*.jar ``` ## When to apply `distribution` directly Use the standalone plugin when there is **no runnable main class** but you still want conventional release bundles: - A **documentation** or **examples** archive. - **Config/templates** packaged for ops. - A wrapper around a **non-JVM** deliverable (scripts, native binaries) that just needs ZIP/TAR/install. - A **library** project that additionally ships a supplementary bundle. Applying `application` in these cases would force a `mainClass` and generate start scripts you do not want. ## Practical implications - Both produce outputs in the same locations (`build/distributions`, `build/install/<baseName>`), so downstream tooling is uniform. - If you later need to make a `distribution`-only project runnable, switching to `application` reuses the same `main` distribution — minimal churn. - Avoid applying both yourself; `application` already brings `distribution`. ## Mental model `distribution` = the packaging engine. `application` = that engine plus a JVM-launcher opinion. Choose the lowest layer that meets the need to keep the build honest about what it produces.

  • Concretely, what does `application` add to the `main` distribution's contents?
    The `bin/` directory with OS start scripts (from `CreateStartScripts`) and the `lib/` directory with the project's runtime classpath jars.
  • Should you apply both `application` and `distribution`?
    No. `application` already applies `distribution`. Applying both is redundant; just apply `application` when you need the app semantics.

saying these in an interview costs you the question

  • Saying the two plugins use separate, unrelated tasks — `application` configures the very same `main` distribution and its tasks.
  • Claiming `distribution` generates start scripts — that is exclusively the `application` plugin.

context