Software projects typically depend on other libraries to function. These libraries can either be sourced from other projects in the same build or from external repositories.
Gradle’s dependency management infrastructure provides APIs to declare, resolve, and expose binaries required by and provided by a project.
Understanding dependency management in Gradle is important for structuring projects into components. It is also important when you want to reuse existing libraries, or you need to upgrade those libraries while managing their versions.
Let’s look at a Java project where the code relies on Guava which is a suite of Google Core libraries for Java. The build file of the project includes the following:
dependencies {
implementation("com.google.guava:guava:32.1.2-jre") (2)
api("org.apache.juneau:juneau-marshall:8.2.0") (3)
}
dependencies {
implementation("com.google.guava:guava:32.1.2-jre") (2)
api("org.apache.juneau:juneau-marshall:8.2.0") (3)
}
Within the dependencies
block, there are three things to notice when a dependency is declared:
-
The configuration:
implementation
also known as the scope the dependency is applied to -
The module ID:
com.google.guava:guava
is made up of agroup
and an artifactname
which are uniquely identifiable -
The version:
32.1.2-jre
which is not always required
Dependencies can be local or external.
To let Gradle know where to find external dependencies, use the repositories{}
block in the Build File.
Let’s expand our example:
repositories {
google()
mavenCentral()
}
dependencies {
implementation("com.google.guava:guava:32.1.2-jre") (2)
api("org.apache.juneau:juneau-marshall:8.2.0") (3)
}
repositories {
google()
mavenCentral()
}
dependencies {
implementation("com.google.guava:guava:32.1.2-jre") (2)
api("org.apache.juneau:juneau-marshall:8.2.0") (3)
}
In this example, Gradle fetches the guava
and juneau-marshall
dependencies from the Maven Central and Google repositories.
Learning the Basics
If you want to understand the basics of dependency management and you are new to Gradle, start here.
1. Declaring Dependencies
You can add external libraries to your Java project, such as Guava
.
These libraries are dependencies of your project.
They are added using the dependencies{}
block in your build file.
2. Dependency Configurations
Every dependency declared for a Gradle project applies to a specific scope, known as a configurations. These configurations are typically created by applying plugins or must be created directly using APIs.
3. Declaring Repositories
You can declare repositories to tell Gradle where to fetch external dependencies. During a build, Gradle locates and downloads the dependencies, a process called dependency resolution.
4. Centralizing Dependencies
To keep dependencies and their versions declared in a single, manageable location (i.e., centralized), you can use platforms and version catalogs.
A platform is a set of modules intended to be used together. A version catalog is a centralized list of dependency coordinates that can be referenced in multiple projects.
5. Managing Constraints and Conflicts
Conflicts can arise when the same library is declared multiple times or when different libraries provide the same functionality. This usually leads to failing builds.
You can manage conflicts using resolution rules or dependency locking.
Advanced Concepts
In order to influence how Gradle resolves dependencies, it’s important to understand how it works.
1. Dependency Resolution
Gradle’s dependency resolution process determines which modules and versions are required to fulfill a build’s declared dependencies. It is done in two steps, graph resolution and artifact resolution.
2. Graph Resolution
During graph resolution, Gradle constructs a dependency graph, resolving version conflicts and ensuring the intended dependencies are selected.
3. Variant Selection
Variant selection traverses the resolved dependency graph by choosing the most compatible variant of each module based on attributes and capabilities.
4. Artifact Resolution
Finally, Artifact resolution is how Gradle determines which files or artifacts published by the selected variants to download and use during the build.