How do the archiveBaseName, archiveVersion, and archiveClassifier properties on an archive task (like Jar) combine to form the final published artifact file name?
answer
- baseName-appendix-version-classifier.extension
- AbstractArchiveTask base class
- lazy Property<String>
- empty part drops its dash
- classifier distinguishes same-GAV artifacts
basics
~10 sGradle assembles the name as [baseName]-[appendix]-[version]-[classifier].[extension]. So baseName 'app', version '1.0', classifier 'sources' produces app-1.0-sources.jar. Empty parts are skipped along with their dash.
solid answer
~40 sArchive tasks (`Jar`, `Zip`, `Tar`) compute `archiveFileName` from component `Property` values in a fixed order: `archiveBaseName`-`archiveAppendix`-`archiveVersion`-`archiveClassifier`.`archiveExtension`. Each is a lazy `Property<String>`, so you set them with `.set(...)` (Kotlin) or via assignment in Groovy. Empty/absent components are omitted together with their separating hyphen, so a missing classifier yields `app-1.0.jar` rather than a dangling dash. Defaults come from the project: `archiveBaseName` defaults to the project name, `archiveVersion` to `project.version`, and `archiveExtension` to the task type (jar/zip/tar). For publishing you typically leave baseName/version as defaults and set `archiveClassifier` to distinguish artifacts (e.g. `sources`, `javadoc`) that share the same coordinates. Because these are providers, they're resolved lazily at execution time, so referencing `project.version` set later still works.
code
kotlin · 10 linestasks.named<Jar>("jar") {
archiveBaseName.set("my-lib")
archiveVersion.set("1.2.0")
archiveClassifier.set("") // -> my-lib-1.2.0.jar
}
tasks.register<Jar>("sourcesJar") {
archiveClassifier.set("sources") // -> my-lib-1.2.0-sources.jar
from(sourceSets.main.get().allSource)
}go deeper
Recall the component order and that empty parts drop their dash; give the sources-jar classifier example.
Explain the lazy Property nature, the defaults (project name / project.version / task type), and the read-only archiveFileName/archiveFile providers.
Tie classifier usage to keeping multiple artifacts under one GAV distinct and to how the maven-publish layer maps them; note lazy resolution interplay with versions set by plugins.
Discuss standardizing archive naming conventions across a multi-module org build via a convention plugin so every module produces consistently named, publishable artifacts.
## What archive tasks are Gradle's bundling tasks — `Jar`, `Zip`, `Tar` (and subtypes like `War`, `Ear`) — all extend `AbstractArchiveTask`. That base class defines the naming contract used for every produced artifact, including the ones you publish to a Maven/Ivy repository. ## The naming components The final file name is built from these lazy properties, in this exact order: ``` [archiveBaseName]-[archiveAppendix]-[archiveVersion]-[archiveClassifier].[archiveExtension] ``` - `archiveBaseName: Property<String>` — defaults to the **project name**. - `archiveAppendix: Property<String>` — usually empty; used for things like a feature-variant name. - `archiveVersion: Property<String>` — defaults to `project.version`. - `archiveClassifier: Property<String>` — empty for the main artifact; `sources`, `javadoc`, `tests`, etc. for secondary artifacts. - `archiveExtension: Property<String>` — defaults to the archive type (`jar`, `zip`, `tar`). There is also a read-only `archiveFileName: Provider<String>` (the assembled name) and `archiveFile: Provider<RegularFile>` (the location under `build/libs` or `build/distributions`). ## Empty-part handling If a component is absent or empty, **both it and its leading hyphen are dropped**. So with no classifier you get `app-1.0.jar`, not `app-1.0-.jar`. This is why you never need to conditionally build the name yourself. ## Why these are Providers Each property is a lazy `Property<String>`. You configure it with `.set(...)` (or `=` in Groovy/Kotlin assignment). Lazy evaluation means a value derived from `project.version` is read **at execution time**, so it still reflects a version assigned later in the build script or by a plugin. ## Publishing relevance When you publish multiple jars under the same GAV coordinates (main, sources, javadoc), the **classifier** is what keeps their file names distinct and tells the Maven layer which artifact is which. Setting `archiveClassifier` correctly is therefore central to a clean publication. ```kotlin tasks.named<Jar>("jar") { archiveBaseName.set("my-lib") archiveVersion.set(project.version.toString()) archiveClassifier.set("") // main artifact } ```
- What does archiveBaseName default to if you never set it?The project's name (`project.name`).
- Why use .set() instead of plain assignment in Kotlin DSL?These are lazy `Property` objects; `.set()` (or `=` via the Kotlin property convention) records a value/provider resolved at execution time rather than eagerly.
saying these in an interview costs you the question
- Saying you must manually concatenate the file name with conditionals for missing parts.
- Claiming archiveVersion defaults to '1.0' rather than project.version.
- Confusing the deprecated baseName/classifier (no 'archive' prefix) with the current archive* properties.