# Understanding Gradle Module Metadata

version 7.6.4

Gradle Module Metadata is a format used to serialize the Gradle component model. It is similar to Apache Maven™'s POM file or Apache Ivy™ ivy.xml files. The goal of metadata files is to provide to consumers a reasonable model of what is published on a repository.

Gradle Module Metadata is a unique format aimed at improving dependency resolution by making it multi-platform and variant-aware.

In particular, Gradle Module Metadata supports:

- rich version constraints

- dependency constraints

- component capabilities

- variant-aware resolution

Publication of Gradle Module Metadata will enable better dependency management for your consumers:

- early discovery of problems by detecting incompatible modules

- consistent selection of platform-specific dependencies

- native dependency version alignment

- automatically getting dependencies for specific features of your library

Gradle Module Metadata is automatically published when using the Maven Publish plugin or the Ivy Publish plugin.

The specification for Gradle Module Metadata can be found here.

## Mapping with other formats

Gradle Module Metadata is automatically published on Maven or Ivy repositories. However, it doesn’t replace the pom.xml or ivy.xml files: it is published alongside those files. This is done to maximize compatibility with third-party build tools.

Gradle does its best to map Gradle-specific concepts to Maven or Ivy. When a build file uses features that can only be represented in Gradle Module Metadata, Gradle will warn you at publication time. The table below summarizes how some Gradle specific features are mapped to Maven and Ivy:

Table 1. Mapping of Gradle specific concepts to Maven and Ivy
Gradle | Maven | Ivy | Description
--- | --- | --- | ---
dependency constraints | `<dependencyManagement>` dependencies | Not published | Gradle dependency constraints are transitive, while Maven’s dependency management block isn’t
rich version constraints | Publishes the requires version | Published the requires version |
component capabilities | Not published | Not published | Component capabilities are unique to Gradle
Feature variants | Variant artifacts are uploaded, dependencies are published as optional dependencies | Variant artifacts are uploaded, dependencies are not published | Feature variants are a good replacement for optional dependencies
Custom component types | Artifacts are uploaded, dependencies are those described by the mapping | Artifacts are uploaded, dependencies are ignored | Custom component types are probably not consumable from Maven or Ivy in any case. They usually exist in the context of a custom ecosystem.

### Disabling metadata compatibility publication warnings

If you want to suppress warnings, you can use the following APIs to do so:

- For Maven, see the `suppress*` methods in MavenPublication

- For Ivy, see the `suppress*` methods in IvyPublication

Example 1. Disabling publication warnings
build.gradle

        publications {
            maven(MavenPublication) {
                from components.java
                suppressPomMetadataWarningsFor('runtimeElements')
            }
        }

build.gradle.kts

        publications {
            register<MavenPublication>("maven") {
                from(components["java"])
                suppressPomMetadataWarningsFor("runtimeElements")
            }
        }

## Interactions with other build tools

Because Gradle Module Metadata is not widely spread and because it aims at maximizing compatibility with other tools, Gradle does a couple of things:

- Gradle Module Metadata is systematically published alongside the normal descriptor for a given repository (Maven or Ivy)

- the `pom.xml` or `ivy.xml` file will contain a marker comment which tells Gradle that Gradle Module Metadata exists for this module

The goal of the marker is not for other tools to parse module metadata: it’s for Gradle users only. It explains to Gradle that a better module metadata file exists and that it should use it instead. It doesn’t mean that consumption from Maven or Ivy would be broken either, only that it works in degraded mode.

| This must be seen as a performance optimization: instead of having to do 2 network requests, one to get Gradle Module Metadata, then one to get the POM/Ivy file in case of a miss, Gradle will first look at the file which is most likely to be present, then only perform a 2nd request if the module was actually published with Gradle Module Metadata.

If you know that the modules you depend on are always published with Gradle Module Metadata, you can optimize the network calls by configuring the metadata sources for a repository:

Example 2. Resolving Gradle Module Metadata only
build.gradle

        repositories {
            maven {
                url "http://repo.mycompany.com/repo"
                metadataSources {
                    gradleMetadata()
                }
            }
        }

build.gradle.kts

        repositories {
            maven {
                setUrl("http://repo.mycompany.com/repo")
                metadataSources {
                    gradleMetadata()
                }
            }
        }

## Gradle Module Metadata validation

Gradle Module Metadata is validated before being published.

The following rules are enforced:

- Variant names must be unique,

- Each variant must have at least one attribute,

- Two variants cannot have the exact same attributes and capabilities,

- If there are dependencies, at least one, across all variants, must carry version information.

These rules ensure the quality of the metadata produced, and help confirm that consumption will not be problematic.

## Gradle Module Metadata reproducibility

The task generating the module metadata files is currently never marked `UP-TO-DATE` by Gradle due to the way it is implemented. However, if neither build inputs nor build scripts changed, the task result is effectively up-to-date: it always produces the same output.

If users desire to have a unique `module` file per build invocation, it is possible to link an identifier in the produced metadata to the build that created it. Users can choose to enable this unique identifier in their `publication`:

Example 3. Configuring the build identifier of a publication
build.gradle

    publishing {
        publications {
            myLibrary(MavenPublication) {
                from components.java
                withBuildIdentifier()
            }
        }
    }

build.gradle.kts

    publishing {
        publications {
            create<MavenPublication>("myLibrary") {
                from(components["java"])
                withBuildIdentifier()
            }
        }
    }

With the changes above, the generated Gradle Module Metadata file will always be different, forcing downstream tasks to consider it out-of-date.

## Disabling Gradle Module Metadata publication

There are situations where you might want to disable publication of Gradle Module Metadata:

- the repository you are uploading to rejects the metadata file (unknown format)

- you are using Maven or Ivy specific concepts which are not properly mapped to Gradle Module Metadata

In this case, disabling the publication of Gradle Module Metadata is done simply by disabling the task which generates the metadata file:

Example 4. Disabling publication of Gradle Module Metadata
build.gradle

        tasks.withType(GenerateModuleMetadata) {
            enabled = false
        }

build.gradle.kts

        tasks.withType<GenerateModuleMetadata> {
            enabled = false
        }