What does `withSourcesJar()` do beyond just creating a Jar task — how does it integrate with the java component and publishing?
answer
- registers Jar task + sourcesElements configuration
- consumable, attributes Category=documentation DocsType=sources
- secondary variant on AdhocComponentWithVariants
- publishing + module metadata pick it up
- manual artifact() misses the variant
basics
~10 sIt registers the sourcesJar task and attaches the jar as a secondary variant on the java SoftwareComponent. So from(components["java"]) publishes it automatically and Gradle Module Metadata describes it as a documentation variant.
solid answer
~40 s`withSourcesJar()` isn't just task creation — its value is *component integration*. It registers a `Jar` task (`sourcesJar`, classifier `sources`) and then adds it to the `java` component as a **secondary variant** carrying attributes like `Category=documentation`, `DocsType=sources`, `Bundling=external`. Two payoffs: (1) any `maven-publish`/`ivy-publish` publication built with `from(components["java"])` includes the jar and emits correct Gradle Module Metadata describing the variant, so attribute-aware consumers can resolve sources separately; (2) you don't touch the `archives` configuration or the `artifacts {}` block. Without the method you'd register the `Jar` task yourself AND attach it (e.g. via `AdhocComponentWithVariants.addVariantsFromConfiguration` or a publication `artifact(...)`), which is more error-prone and may omit metadata.
code
kotlin · 9 linesjava {
withSourcesJar() // -> sourcesJar task + sourcesElements consumable config
}
// equivalent secondary-variant attributes Gradle sets:
// org.gradle.category = documentation
// org.gradle.docstype = sources
// org.gradle.usage = (none / docs)
// org.gradle.dependency.bundling = externalgo deeper
Know it both creates the task and makes publishing include the sources jar automatically.
Explain the secondary-variant attachment and the consumable sourcesElements configuration with documentation attributes.
Detail the attributes, AdhocComponentWithVariants, and how module metadata enables attribute-based consumption of sources.
Reason about variant governance across a multi-module platform and consumer tooling (IDE sources resolution) implications.
## Component vs. task A *task* produces a file. A **SoftwareComponent** is Gradle's abstraction of "what gets published" — it groups variants (usages) such as `apiElements`, `runtimeElements`, plus optional documentation variants. The `java` component is the standard one for libraries. ## What `withSourcesJar()` actually does 1. Registers a `Jar` task named `sourcesJar` packaging the `main` source set, classifier `sources`. 2. Creates (or reuses) a *consumable* configuration for the sources, e.g. `sourcesElements`, marked `canBeConsumed = true`, `canBeResolved = false`, with attributes: - `Category` = `documentation` - `DocsType` = `sources` - `Bundling` = `external` 3. Adds that configuration to the `java` component as a **secondary variant** (the component is an `AdhocComponentWithVariants` under the hood). `withJavadocJar()` does the same with `DocsType=javadoc` and a `javadocElements` configuration. ## Why secondary variant matters Because the variant lives on the component, two systems pick it up for free: - **Publishing**: `from(components["java"])` enumerates the component's variants, so all attached jars are published and written into Gradle Module Metadata (`module.json`). The metadata declares `available-at`/variant entries with the attributes above. - **Consumption**: a consumer can request `DocsType=sources` via attribute-based resolution (e.g. an IDE pulling sources) and Gradle matches the right variant. ## Contrast with manual wiring ```kotlin // manual equivalent — fragile val sourcesJar by tasks.registering(Jar::class) { archiveClassifier.set("sources") from(sourceSets.main.get().allSource) } // you'd still need to attach it as a variant or add it to the publication publishing.publications.withType<MavenPublication> { artifact(sourcesJar) // publishes the file but NOT as a proper documentation variant in module metadata } ``` The manual `artifact(sourcesJar)` route publishes the file but does not create the documentation variant in module metadata. `withSourcesJar()` does both, which is why it's the recommended path.
- Is the sources configuration resolvable or consumable?Consumable (`canBeConsumed = true`, `canBeResolved = false`). It exposes the artifact to consumers/publishing; it is not used to resolve a dependency graph.
- Why does `artifact(sourcesJar)` on a publication behave differently?It attaches the file to the Maven publication but does not register a documentation variant on the component, so Gradle Module Metadata won't describe it as a sources variant for attribute-aware consumers.
saying these in an interview costs you the question
- Saying `withSourcesJar()` only creates a task — missing the component/variant integration is the key point.
- Confusing consumable and resolvable: the sources configuration is consumable, not resolvable.