# Platforms

version 9.0.0

Platforms are used to ensure that all dependencies in a project align with a consistent set of versions.

Platforms help you manage and enforce version consistency across different modules or libraries, especially when you are working with a set of related dependencies that need to be kept in sync.

## Using a platform

A platform is a specialized software component used to control transitive dependency versions. Typically, it consists of dependency constraints that either recommend or enforce specific versions. Platforms are particularly useful when you need to share consistent dependency versions across multiple projects.

In a typical setup you have:

- A Platform Project: Which defines constraints for dependencies used across different subprojects.

- A Number of Subprojects: Which depend on the platform and declare dependencies without specifying versions.

The `java-platform plugin` supports creating platforms in the Java ecosystem. Platforms are also commonly published as Maven BOMs (Bill of Materials), which Gradle natively supports.

To use a platform, declare a dependency with the `platform` keyword:

build.gradle.kts

    dependencies {
        // get recommended versions from the platform project
        api(platform(project(":platform")))
        // no version required
        api("commons-httpclient:commons-httpclient")
    }

build.gradle

    dependencies {
        // get recommended versions from the platform project
        api platform(project(':platform'))
        // no version required
        api 'commons-httpclient:commons-httpclient'
    }

This notation automatically performs several actions:

- Sets the `org.gradle.category` attribute to platform, ensuring Gradle selects the platform component.

- Enables the `endorseStrictVersions` behavior by default, enforcing strict versions defined in the platform.

If strict version enforcement isn’t needed, you can disable it using the `doNotEndorseStrictVersions` method.

## Creating a platform

In Java projects, the `java-platform` plugin combined with dependency constraints can be used to create a platform:

    plugins {
        id("java-platform")
    }

    dependencies {
        constraints {
            api("com.google.guava:guava:30.1-jre")
            api("org.apache.commons:commons-lang3:3.12.0")
        }
    }

This defines a custom platform with specific versions of `guava` and `commons-lang3` that can be applied in other projects.

## Importing a platform

Gradle supports importing BOMs, which are POM files containing `<dependencyManagement>` sections that manage dependency versions.

In order to qualify as a BOM, a `.pom` file needs to have pom set. This means that the POM file should explicitly specify <packaging>pom</packaging> in its metadata.

Gradle treats all entries in the block of a BOM similar to Adding Constraints On Dependencies.

### Regular Platform

To import a BOM, declare a dependency on it using the `platform` dependency modifier method:

build.gradle.kts

    dependencies {
        // import a BOM
        implementation(platform("org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE"))
        // define dependencies without versions
        implementation("com.google.code.gson:gson")
        implementation("dom4j:dom4j")
    }

build.gradle

    dependencies {
        // import a BOM
        implementation platform('org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE')
        // define dependencies without versions
        implementation 'com.google.code.gson:gson'
        implementation 'dom4j:dom4j'
    }

In this example, the Spring Boot BOM provides the versions for `gson` and `dom4j`, so no explicit versions are needed.

### Enforced Platform

The `enforcedPlatform` keyword can be used to override any versions found in the dependency graph, but should be used with caution as it is effectively transitive and exports forced versions to all consumers of your project:

build.gradle.kts

    dependencies {
        // import a BOM. The versions used in this file will override any other version found in the graph
        implementation(enforcedPlatform("org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE"))

        // define dependencies without versions
        implementation("com.google.code.gson:gson")
        implementation("dom4j:dom4j")

        // this version will be overridden by the one found in the BOM
        implementation("org.codehaus.groovy:groovy:1.8.6")
    }

build.gradle

    dependencies {
        // import a BOM. The versions used in this file will override any other version found in the graph
        implementation enforcedPlatform('org.springframework.boot:spring-boot-dependencies:1.5.8.RELEASE')

        // define dependencies without versions
        implementation 'com.google.code.gson:gson'
        implementation 'dom4j:dom4j'

        // this version will be overridden by the one found in the BOM
        implementation 'org.codehaus.groovy:groovy:1.8.6'
    }

When using `enforcedPlatform`, exercise caution if your software component is intended for consumption by others. This declaration is transitive and affects the dependency graph of your consumers. If they disagree with any enforced versions, they’ll need to use `exclude`. Instead, if your reusable component strongly favors specific third-party dependency versions, consider using a rich version declaration with `strictly`.