Viewing Dependencies
Gradle offers tools to navigate the results of dependency management, allowing you to more precisely understand how and why Gradle resolves dependencies. You can render a full dependency graph, identify the origin of a given dependency, and see why specific versions were selected. Dependencies can come from build script declarations or transitive relationships.
To visualize dependencies, you can use:
-
The
dependencies
task -
The
dependencyInsight
task
List project dependencies using the dependencies
task
Gradle provides the built-in dependencies
task to render a dependency tree from the command line.
By default, the task shows dependencies for all configurations within a single project.
The dependency tree shows the selected version of each dependency and provides information on conflict resolution.
The dependencies
task is particularly useful for analyzing transitive dependencies.
While your build file lists direct dependencies, the task helps you understand which transitive dependencies are resolved during the build.
$ ./gradlew dependencies
To render the graph of dependencies declared in the buildscript classpath configuration, use the buildEnvironment task.
|
Understanding output annotations
$ ./gradlew :app:dependencies
> Task :app:dependencies
------------------------------------------------------------
Project ':app'
------------------------------------------------------------
annotationProcessor - Annotation processors and their dependencies for source set 'main'.
No dependencies
compileClasspath - Compile classpath for source set 'main'.
\--- com.fasterxml.jackson.core:jackson-databind:2.17.2
+--- com.fasterxml.jackson.core:jackson-annotations:2.17.2
| \--- com.fasterxml.jackson:jackson-bom:2.17.2
| +--- com.fasterxml.jackson.core:jackson-annotations:2.17.2 (c)
| +--- com.fasterxml.jackson.core:jackson-core:2.17.2 (c)
| \--- com.fasterxml.jackson.core:jackson-databind:2.17.2 (c)
+--- com.fasterxml.jackson.core:jackson-core:2.17.2
| \--- com.fasterxml.jackson:jackson-bom:2.17.2 (*)
\--- com.fasterxml.jackson:jackson-bom:2.17.2 (*)
...
The dependencies
task marks dependency trees with the following annotations:
-
(*)
: Indicates repeated occurrences of a transitive dependency subtree. Gradle expands transitive dependency subtrees only once per project; repeat occurrences only display the root of the subtree, followed by this annotation. -
(c)
: This element is a dependency constraint, not a dependency. Look for the matching dependency elsewhere in the tree. -
(n)
: A dependency or dependency configuration that cannot be resolved.
Specifying a dependency configuration
To focus on a specific dependency configuration, use the optional --configuration
parameter.
Like project and task names, Gradle allows abbreviated names for dependency configurations.
For example, you can use tRC
instead of testRuntimeClasspath
, as long as it matches a unique configuration.
The following examples display dependencies for the testRuntimeClasspath
configuration in a Java project:
$ gradle -q dependencies --configuration testRuntimeClasspath
$ gradle -q dependencies --configuration tRC
To view a list of all configurations in a project, including those provided by plugins, run the resolvableConfigurations
report.
For more details, refer to the plugin’s documentation, such as the Java Plugin here.
Looking at an example
Consider a project that uses the JGit library to execute Source Control Management (SCM) operations for a release process. You can declare dependencies for external tooling with the help of a custom dependency configuration. This avoids polluting other contexts, such as the compilation classpath for your production source code.
The following example declares a custom dependency configuration named scm
that contains the JGit dependency:
configurations {
create("scm")
}
dependencies {
"scm"("org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r")
}
configurations {
scm
}
dependencies {
scm 'org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r'
}
Use the following command to view a dependency tree for the scm
dependency configuration:
$ gradle -q dependencies --configuration scm ------------------------------------------------------------ Root project 'dependencies-report' ------------------------------------------------------------ scm \--- org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r +--- com.jcraft:jsch:0.1.54 +--- com.googlecode.javaewah:JavaEWAH:1.1.6 +--- org.apache.httpcomponents:httpclient:4.3.6 | +--- org.apache.httpcomponents:httpcore:4.3.3 | +--- commons-logging:commons-logging:1.1.3 | \--- commons-codec:commons-codec:1.6 \--- org.slf4j:slf4j-api:1.7.2 A web-based, searchable dependency report is available by adding the --scan option.
Identify the selected version using the dependencyInsight
task
A project may request two different versions of the same dependency either directly or transitively that may result in a version conflict.
The following example introduces a conflict with commons-codec:commons-codec
, added both as a direct dependency and a transitive dependency of JGit:
repositories {
mavenCentral()
}
configurations {
create("scm")
}
dependencies {
"scm"("org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r")
"scm"("commons-codec:commons-codec:1.7")
}
repositories {
mavenCentral()
}
configurations {
scm
}
dependencies {
scm 'org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r'
scm 'commons-codec:commons-codec:1.7'
}
Gradle provides the built-in dependencyInsight
task to render a dependency insight report from the command line.
Dependency insights provide information about a single dependency within a single configuration. Given a dependency, you can identify the reason and origin for its version selection.
dependencyInsight
accepts the following parameters:
--dependency <dependency>
(mandatory)-
The dependency to investigate. You can supply a complete
group:name
, or part of it. If multiple dependencies match, Gradle generates a report covering all matching dependencies. --configuration <name>
(mandatory)-
The dependency configuration which resolves the given dependency. This parameter is optional for projects that use the Java plugin, since the plugin provides a default value of
compileClasspath
. --single-path
(optional)-
Render only a single path to the dependency.
--all-variants
(optional)-
Render information about all variants, not only the selected variant.
The following code snippet demonstrates how to run a dependency insight report for all paths to a dependency named commons-codec
within the scm
configuration:
$ gradle -q dependencyInsight --dependency commons-codec --configuration scm commons-codec:commons-codec:1.7 Variant default: | Attribute Name | Provided | Requested | |-------------------|----------|-----------| | org.gradle.status | release | | Selection reasons: - By conflict resolution: between versions 1.7 and 1.6 commons-codec:commons-codec:1.7 \--- scm commons-codec:commons-codec:1.6 -> 1.7 \--- org.apache.httpcomponents:httpclient:4.3.6 \--- org.eclipse.jgit:org.eclipse.jgit:4.9.2.201712150930-r \--- scm A web-based, searchable dependency report is available by adding the --scan option.
Understanding the selection reasons
The "Selection reasons" section of the dependency insight report lists the reasons why a dependency was selected.
Reason | Meaning |
---|---|
(Absent) |
No reason other than a reference, direct or transitive, was present. |
Was requested : <text> |
The dependency appears in the graph, and the inclusion came with a |
Was requested : didn’t match versions <versions> |
The dependency appears with a dynamic version which did not include the listed versions.
May be followed by a |
Was requested : reject version <versions> |
The dependency appears with a rich version containing one or more |
By conflict resolution : between versions <version> |
The dependency appeared multiple times, with different version requests. This resulted in conflict resolution to select the most appropriate version. |
By constraint |
A dependency constraint participated in the version selection.
May be followed by a |
By ancestor |
There is a rich version with a |
Selected by rule |
A dependency resolution rule overruled the default selection process.
May be followed by a |
Rejection : <version> by rule because <text> |
A |
Rejection: version <version>: <attributes information> |
The dependency has a dynamic version and some versions did not match the requested attributes. |
Forced |
The build enforces the version of the dependency through an enforced platform or resolution strategy. |
If multiple selection reasons exist, the insight report lists all of them.
Get a holistic view using Build Scans
The dependency tree in a Build Scan shows information about conflicts.
A Build Scan was created for the commons-codec
example above and a URL was provided with the results.
Head over to the Dependencies
tab and navigate to your desired dependency.
Select the Required By
tab to see the selection reason and origin of the dependency:
Resolving unsafe configuration resolution errors
Resolving a configuration can have side effects on Gradle’s project model, so Gradle needs manage access to each project’s configurations. There are a number of ways a configuration might be resolved unsafely. Gradle will produce a deprecation warning for each unsafe access. Each of these are bad practices and can cause strange and indeterminate errors.
If your build has an unsafe access deprecation warning, it needs to be fixed.
For example:
-
A task from one project directly resolves a configuration in another project in the task’s action.
-
A task specifies a configuration from another project as an input file collection.
-
A build script for one project resolves a configuration in another project during evaluation.
-
Project configurations are resolved in the settings file.
In most cases, this issue can be resolved by creating a cross-project dependency on the other project. See the documentation for sharing outputs between projects for more information.
If you find a use case that can’t be resolved using these techniques, please let us know by filing a GitHub Issue adhering to our issue guidelines.