How do you configure the MANIFEST.MF of a published Jar using the manifest {} block, and how can manifest attributes be shared across multiple jars?
answer
- manifest { attributes(mapOf(...)) }
- project.manifest then from(shared)
- eachEntry merge rules
- Automatic-Module-Name / Main-Class
- deterministic values for reproducibility
basics
~10 sInside a Jar task, use the manifest {} block and call attributes(mapOf(...)) to add entries like 'Implementation-Version' or 'Main-Class' to META-INF/MANIFEST.MF. To reuse, build a shared manifest and merge it.
solid answer
~40 sEvery `Jar` task exposes a `manifest {}` block backed by a `Manifest` object. You add entries with `attributes(mapOf("Implementation-Title" to "my-lib", "Implementation-Version" to project.version))`. Common entries for publishing include `Implementation-Title/Version/Vendor` and, for executable jars, `Main-Class`. To avoid duplicating attributes across several jars, create a shared manifest with `project.manifest { attributes(...) }` (or `java.manifest`) and merge it into each task via `from(sharedManifest)` inside the task's `manifest {}` block. You can also merge attributes from existing manifest files using `manifest.from("path/to/base.mf")` with optional `eachEntry` merge rules to resolve conflicts. Because attribute values are evaluated lazily by Gradle's task configuration, referencing `project.version` is safe even if set later. For reproducible publications, keep manifest values deterministic — avoid timestamps or build-host names that change between builds.
code
kotlin · 14 linesval sharedManifest = project.manifest {
attributes(mapOf("Implementation-Vendor" to "Acme Corp"))
}
tasks.named<Jar>("jar") {
manifest {
from(sharedManifest)
attributes(mapOf(
"Implementation-Title" to project.name,
"Implementation-Version" to project.version,
"Automatic-Module-Name" to "com.acme.mylib"
))
}
}go deeper
Show the manifest { attributes(mapOf(...)) } block and name a couple of standard attributes.
Demonstrate sharing a manifest via project.manifest + from(), and mention Automatic-Module-Name / Main-Class use cases.
Discuss eachEntry merge rules, keeping values deterministic for reproducibility, and which attributes downstream tooling reads.
Standardize manifest identity attributes across modules in a convention plugin; govern which attributes are mandatory for published libraries.
## The manifest A Java archive carries a `META-INF/MANIFEST.MF` file: key/value attributes describing the jar. Gradle's `Jar` task models this through a `manifest {}` configuration block backed by a `Manifest` interface. ## Adding attributes ```kotlin tasks.named<Jar>("jar") { manifest { attributes(mapOf( "Implementation-Title" to project.name, "Implementation-Version" to project.version, "Implementation-Vendor" to "Acme Corp", "Main-Class" to "com.acme.Main" )) } } ``` `attributes(...)` adds to the **main** manifest section. You can also add named sections with `attributes(map, "sectionName")`. ## Sharing a manifest across jars A library that publishes a main jar plus a sources/javadoc jar often wants the same identity attributes everywhere. Define the manifest once and merge it: ```kotlin val sharedManifest = project.manifest { attributes(mapOf("Implementation-Vendor" to "Acme Corp")) } tasks.named<Jar>("jar") { manifest { from(sharedManifest) attributes(mapOf("Implementation-Title" to project.name)) } } ``` `from(...)` merges another `Manifest` (or a manifest file path) into this one. When the same key appears in both, the merged value wins unless you customize merging. ## Merge rules Gradle lets you reconcile conflicts when merging file-based manifests: ```kotlin manifest { from("src/config/base.mf") { eachEntry { if (key == "Implementation-Version" && baseValue != null) value = baseValue } } } ``` `eachEntry` runs a `ManifestMergeDetails` callback exposing `key`, `value`, `baseValue`, and `mergeValue`, so you can deterministically pick a winner. ## Reproducibility caution Manifest content is part of the jar bytes, so it affects byte-for-byte reproducibility. Avoid attributes that vary run-to-run — build timestamps, hostnames, random IDs — if you want identical published artifacts. Pair this with the archive task's `isPreserveFileTimestamps = false` and `isReproducibleFileOrder = true` settings. ## Why it matters for publishing Consumers and tooling read manifest attributes (e.g. `Implementation-Version`, `Automatic-Module-Name` for the JPMS module name) directly from your published jar, so getting them right is part of producing a high-quality publication.
- How would you set the JPMS automatic module name via the manifest?Add the `Automatic-Module-Name` attribute in the jar's manifest block; the JVM uses it as the module name when the jar is on the module path without a module-info.
- What problem can manifest attributes cause for reproducible builds?Volatile values like build timestamps or hostnames change the jar bytes between builds, breaking byte-for-byte reproducibility.
saying these in an interview costs you the question
- Claiming you must hand-write META-INF/MANIFEST.MF and add it as a resource.
- Saying manifest values can't reference project.version because of evaluation order (they're lazy).
- Forgetting that manifest content affects reproducible-build byte equality.