Both platforms and version catalogs help manage dependency versions in a project, but they serve different purposes and have different effects on dependency resolution:

Version Catalogs

  • Purpose: A version catalog centralizes and standardizes dependency coordinates (group, name, version) and provides type-safe accessors in the build script, making dependencies easier to manage.

  • Effect on Dependency Graph: Version catalogs do not directly affect dependency resolution. The versions defined in the catalog must be explicitly referenced in a dependencies block, and once referenced, they behave the same as any locally declared dependency. Additionally, the catalog’s contents are transparent to downstream consumers, meaning that consumers cannot identify whether a dependency was declared locally or sourced from a catalog.

libs.versions.toml
[libraries]
mylib = { group = "com.example", name = "mylib", version = "1.0.0" }

Platforms

  • Purpose: A platform is a module in the dependency graph that enforces or aligns versions of dependencies (including transitive dependencies). It influences dependency resolution and ensures version consistency across different modules.

  • Effect on Dependency Graph: Platforms apply or enforce versions to dependencies that are declarated locally without versions. These versions in a platform are propagated through the dependency graph, affecting transitive dependencies and downstream consumers. They are a formal part of the dependency graph and can dictate the version chosen during resolution.

build.gradle.kts
plugins {
    `java-platform`
}

dependencies {
    constraints {
        api("com.example:mylib:2.0.0")
    }
}

Using a catalog with a platform

Even if a version catalog defines a version for a dependency, Gradle might pick a different version during resolution if another component (e.g., a platform or a transitive dependency) suggests a different version (unless enforcedPlatform is used).

For example, a version catalog may define mylib as version 1.0.0, but if a platform enforces 2.0.0, Gradle will select version 2.0.0.

To ensure consistent version alignment, a good approach is to use a version catalog to define dependency versions alongside a platform to enforce them.

Version Catalog:

gradle/libs.versions.toml
[versions]
junit-jupiter = "5.10.3"

[libraries]
guava = { module = "com.google.guava:guava"}
junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
junit-jupiter-launcher = { module = "org.junit.platform:junit-platform-launcher" }

Platform:

platform/build.gradle.kts
plugins {
    `java-platform`
}

javaPlatform {
    allowDependencies()
}

dependencies {
    constraints {
        api("org.junit.jupiter:junit-jupiter:5.11.1") // Enforcing version range
        api("com.google.guava:guava:[33.1.0-jre,)") // Enforcing specific version
    }
}
platform/build.gradle
plugins {
    id 'java-platform'
}

javaPlatform {
    allowDependencies()
}

dependencies {
    constraints {
        api 'org.junit.jupiter:junit-jupiter:5.11.1' // Enforcing specific version
        api 'com.google.guava:guava:[33.1.0-jre,)' // Enforcing version range
    }
}

Consumer:

consumer/build.gradle.kts
dependencies {
    // Platform
    implementation(platform(project(":platform")))
    // Catalog
    testImplementation(libs.junit.jupiter)
    testRuntimeOnly(libs.junit.jupiter.launcher)
    implementation(libs.guava)
}
consumer/build.gradle
dependencies {
    // Platform
    implementation platform(project(":platform"))
    // Catalog
    testImplementation libs.junit.jupiter
    testRuntimeOnly libs.junit.jupiter.launcher
    implementation libs.guava
}

Best Practices for using both a catalog and a platform:

  1. Use version catalogs for defining and sharing dependency coordinates across projects. They make dependency declarations consistent and easier to manage but do not guarantee version alignment.

  2. Use platforms when you need to influence or enforce version alignment across modules. Platforms ensure that dependencies resolve to the desired version, particularly in large or multi-module projects.