// Copyright (C) 2024 Gradle, Inc.
//
// Licensed under the Creative Commons Attribution-Noncommercial-ShareAlike 4.0 International License.;
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      https://creativecommons.org/licenses/by-nc-sa/4.0/
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

[[dependency-management-in-gradle]]
= Dependency Management

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 link:https://mvnrepository.com/artifact/com.google.guava/guava[Guava] which is a suite of Google Core libraries for Java.
The build file of the project includes the following:

====
include::sample[dir="snippets/dependencyManagement/introductionDependencies/kotlin",files="build.gradle.kts[tags=dependency-intro]"]
include::sample[dir="snippets/dependencyManagement/introductionDependencies/groovy",files="build.gradle[tags=dependency-intro]"]
====

Within the `dependencies` block, there are three things to notice when a dependency is declared:

1. The bucket:
** The configuration: `implementation` is the scope the dependency is applied to
2. The dependency:
** The module ID: `com.google.guava:guava` is made up of a `group` and an artifact `name` 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_basics.adoc#build_file_basics,Build File>>.

Let's expand our example:

====
include::sample[dir="snippets/dependencyManagement/introductionDependencies/kotlin",files="build.gradle.kts[tags=dependency-repo]"]
include::sample[dir="snippets/dependencyManagement/introductionDependencies/groovy",files="build.gradle[tags=dependency-repo]"]
====

In this example, Gradle fetches the `guava` and `juneau-marshall` _dependencies_ from the link:https://repo1.maven.org/maven2/[Maven Central] and link:https://maven.google.com/[Google] _repositories_.

== Learning the Basics

If you want to understand the basics of dependency management and you are new to Gradle, start <<declaring_dependencies.adoc#one-declaring-dependencies,here>>.

=== 1. Declaring Dependencies

You can add external libraries to your Java project, such as `Guava`.
These libraries are <<declaring_dependencies_basics.adoc#declaring-dependencies-basics,_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 <<dependency_configurations.adoc#two-dependency-configurations,_configurations_>>.
These _configurations_ are typically created by applying plugins or must be created directly using APIs.

=== 3. Declaring Repositories

You can <<declaring_repositories_basics.adoc#declaring-repositories-basics,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 <<platforms.adoc#platforms,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.adoc#using-resolution-rules,resolution rules>> or <<dependency_locking.adoc#locking-versions,dependency locking>>.

== Advanced Concepts

In order to influence how Gradle resolves dependencies, it's important to understand <<dependency_resolution.adoc#dependency-resolution-basics,how it works>>.

=== 1. Dependency Resolution

Gradle's <<dependency_resolution.adoc#dependency-resolution-basics,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.adoc#dependency-graph-resolution,graph resolution>>, Gradle constructs a _dependency graph_, resolving version conflicts and ensuring the intended dependencies are selected.

=== 3. Variant Selection

<<variant_aware_resolution.adoc#sec:understanding-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.adoc#artifact-resolution,Artifact resolution>> is how Gradle determines which files or _artifacts_ published by the selected variants to download and use during the build.
