// 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.

[[dependencies_intro]]
= Declaring and Managing Dependencies

Gradle provides a rich and flexible model for declaring dependencies, managing versions, and resolving conflicts across builds.

image::gradle-basic-13.png[]

[[sec:declare_dependencies]]
== Declare Dependencies

The `dependencies{}` block is where you declare the external libraries, internal modules, or files your project needs to compile, run, or test:

====
include::sample[dir="snippets/fundamentals/authoring-builds/declaringDependencies-basic/kotlin/app",files="build.gradle.kts[tags=java-dependency-mgmt]"]
include::sample[dir="snippets/fundamentals/authoring-builds/declaringDependencies-basic/groovy/app",files="build.gradle[tags=java-dependency-mgmt]"]
====

Each dependency is added to a **bucket configuration**.
For example `implementation`, `runtimeOnly`, or `testImplementation`.
Bucket configurations defines **where** that dependency is used (compile classpath, runtime only, tests, etc.).
The **set of configurations available** depends on the plugins you apply (e.g., `java`/`java-library`, Android Gradle Plugin (AGP), Kotlin Multiplatform (KMP), etc.).

Gradle recommends the **single-string notation** for external modules.
The map notation is deprecated as of Gradle 9.1.0 and will fail your build in Gradle 10:

====
include::sample[dir="snippets/fundamentals/authoring-builds/dependenciesIntermediate/kotlin",files="build.gradle.kts[tags=string-notation]"]
include::sample[dir="snippets/fundamentals/authoring-builds/dependenciesIntermediate/groovy",files="build.gradle[tags=string-notation]"]
====

[[sec:centralize_versions]]
== Centralize Versions with Version Catalogs

Gradle recommends using version catalogs to declare dependency versions in a single, reusable location:

====
include::sample[dir="snippets/fundamentals/authoring-builds/generated/groovy",files="gradle/libs.versions.toml[]"]
====

You can then use these aliases in your build scripts:

====
include::sample[dir="snippets/fundamentals/authoring-builds/generated/kotlin",files="app/build.gradle.kts[tags=init-dep]"]
include::sample[dir="snippets/fundamentals/authoring-builds/generated/groovy",files="app/build.gradle[tags=init-dep]"]
====

[[sec:enforce_constrain_versions]]
== Enforce and Constrain Versions

Gradle allows you to constrain dependency versions to avoid unwanted upgrades or enforce known good versions:

====
include::sample[dir="snippets/fundamentals/authoring-builds/downgrade-transitives/kotlin",files="build.gradle.kts[tags=dependency-full]"]
include::sample[dir="snippets/fundamentals/authoring-builds/downgrade-transitives/groovy",files="build.gradle[tags=dependency-full]"]
====

You can also constrain a module globally:

====
include::sample[dir="snippets/fundamentals/authoring-builds/managingTransitiveDependencies-versionsWithConstraints/kotlin",files="build.gradle.kts[tags=dependency-constraints]"]
include::sample[dir="snippets/fundamentals/authoring-builds/managingTransitiveDependencies-versionsWithConstraints/groovy",files="build.gradle[tags=dependency-constraints]"]
====

[[sec:resolve_conflicts_capabilities]]
== Resolve Conflicts with Capabilities

Sometimes multiple libraries provide the same functionality under different coordinates. This can lead to classpath conflicts:

====
include::sample[dir="snippets/fundamentals/authoring-builds/dependenciesIntermediate/kotlin",files="build.gradle.kts[tags=conflict-deps]"]
include::sample[dir="snippets/fundamentals/authoring-builds/dependenciesIntermediate/groovy",files="build.gradle[tags=conflict-deps]"]
====

Gradle lets you model these cases using capabilities.
For example:

====
include::sample[dir="snippets/fundamentals/authoring-builds/dependenciesIntermediate/kotlin",files="build.gradle.kts[tags=capability-deps]"]
include::sample[dir="snippets/fundamentals/authoring-builds/dependenciesIntermediate/groovy",files="build.gradle[tags=capability-deps]"]
====

Then declare capabilities via a component metadata rule:

====
include::sample[dir="snippets/fundamentals/authoring-builds/dependenciesIntermediate/kotlin",files="build.gradle.kts[tags=metadata-rule]"]
include::sample[dir="snippets/fundamentals/authoring-builds/dependenciesIntermediate/groovy",files="build.gradle[tags=metadata-rule]"]
====

Gradle will now treat `jaxen` and `jdom2` as alternate implementations and select the one with a required capability.

There are many more ways to influence dependency resolution in Gradle.
Consult the <<getting_started_dep_man.adoc#dependency-management-in-gradle,Dependency Management>> chapter to learn more.

[.text-right]
**Next Step:** <<writing_tasks_intermediate.adoc#writing_tasks,Learn about Creating and Registering Tasks>> >>
