Skip to main content

How to use gradle to find dependency tree

A quick guide to creating an easy to read report of your dependency tree using Gradle. 

Inspecting Dependencies 

Gradle provides enough tools to navigate large dependency graphs and solve situations that can lead to dependency hell. You can choose to render the full graph of dependencies as well as identify the selection reason and origin for a dependency.

Listing dependencies in your project

Rendering the dependency tree is particularly useful if you'd like to identify which dependencies have been resolved at runtime and get valuable information in case any dependency conflict resolution occurred. The dependency report will contain declared and transitive dependencies.

Every Gradle project provides the task dependencies for rendering the so-called dependency report from the command line. By default, the dependency report presents dependencies for all configurations. To print information for a specific configuration, you need to provide the optional parameter        
--configuration

Available configuration in Android projects

  • debug
  • debugCompileClasspath - Dependencies for compilation
  • debugRuntimeClasspath - Dependencies for runtime/packaging
  • debugAndroidTest
  • debugAndroidTestCompileClasspath - Dependencies for compilation
  • debugAndroidTestRuntimeClasspath - Dependencies for runtime/packaging
  • debugUnitTest
  • debugUnitTestCompileClasspath - Dependencies for compilation
  • debugUnitTestRuntimeClasspath - Dependencies for runtime/packaging
  • release
  • releaseCompileClasspath - Dependencies for compilation
  • releaseRuntimeClasspath - Dependencies for runtime/packaging
  • releaseUnitTest
  • releaseUnitTestCompileClasspath - Dependencies for compilation
  • releaseUnitTestRuntimeClasspath - Dependencies for runtime/packaging

Example: Using Android Studio to render the dependency graph

Additionally, the Android Gradle plugin also provides a task to print the dependency tree for all configurations directly from Android Studio.




When working on large projects, is inevitably deal with an increased number of dependencies whether through direct or transitive dependencies. The dependency report provides us with the raw list of dependencies. Let's see how can we get more dependency insights.

Example: Rendering the dependency report for the dependencies for runtime/packaging using the console.

>gradlew app:dependencies --configuration debugRuntimeClasspath

> Task :app:dependencies 

------------------------------------------------------------
Project :app
------------------------------------------------------------

debugRuntimeClasspath - Resolved configuration for runtime for variant: debug
+--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.2.61
|    \--- org.jetbrains.kotlin:kotlin-stdlib:1.2.61
|         +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.2.61
|         \--- org.jetbrains:annotations:13.0
+--- com.android.support:appcompat-v7:28.0.0-rc02
|    +--- com.android.support:support-annotations:28.0.0-rc02
|    +--- com.android.support:support-compat:28.0.0-rc02
|    |    +--- com.android.support:support-annotations:28.0.0-rc02
...

- some dependencies have been omitted 

Now we can see identify dependency conflicts and the selection reason and track down the origin of the dependency. When resolving dependencies issues, we usually want to look for a particular dependency and to do that; we can use the Gradle task dependencyInsight to render the so-called dependency insight report from the command line. 

Example: Rendering the dependency insight report from the command line


>gradlew -q app:dependencyInsight --dependency runtime --configuration debugRuntimeClasspath


android.arch.core:runtime:1.1.1 (conflict resolution)
+--- android.arch.lifecycle:extensions:1.1.1
|    +--- debugRuntimeClasspath
|    \--- org.koin:koin-android-architecture:0.9.3
|         \--- debugRuntimeClasspath
+--- android.arch.lifecycle:livedata:1.1.1
|    \--- android.arch.lifecycle:extensions:1.1.1 (*)
+--- android.arch.lifecycle:livedata-core:1.1.1
|    +--- com.android.support:loader:28.0.0-rc02
|    |    +--- com.android.support:support-fragment:28.0.0-rc02
|    |    |    +--- com.android.support:design:28.0.0-rc02
|    |    |    |    \--- debugRuntimeClasspath
|    |    |    +--- com.android.support:appcompat-v7:28.0.0-rc02
|    |    |    |    +--- debugRuntimeClasspath
|    |    |    |    \--- com.android.support:design:28.0.0-rc02 (*)
|    |    |    +--- android.arch.lifecycle:extensions:1.1.1 (*)
....

android.arch.lifecycle:runtime:1.1.1 (conflict resolution)
+--- android.arch.lifecycle:extensions:1.1.1
|    +--- debugRuntimeClasspath
|    \--- org.koin:koin-android-architecture:0.9.3
|         \--- debugRuntimeClasspath
\--- com.android.support:support-compat:28.0.0-rc02
     +--- com.android.support:design:28.0.0-rc02
     |    \--- debugRuntimeClasspath
     +--- com.android.support:appcompat-v7:28.0.0-rc02
     |    +--- debugRuntimeClasspath
     |    \--- com.android.support:design:28.0.0-rc02 (*)
     +--- com.android.support:support-vector-drawable:28.0.0-rc02
     |    +--- com.android.support:appcompat-v7:28.0.0-rc02 (*)
     |    \--- com.android.support:animated-vector-drawable:28.0.0-rc02
     |         \--- com.android.support:appcompat-v7:28.0.0-rc02 (*)
     +--- com.android.support:transition:28.0.0-rc02
     |    \--- com.android.support:design:28.0.0-rc02 (*)
     +--- com.android.support:recyclerview-v7:28.0.0-rc02
     |    \--- com.android.support:design:28.0.0-rc02 (*)
     +--- com.android.support:support-v4:26.1.0
     |    \--- com.google.android.gms:play-services-basement:15.0.1
  ....

android.arch.persistence.room:runtime:1.1.1
+--- debugRuntimeClasspath
\--- android.arch.persistence.room:rxjava2:1.1.1
     \--- debugRuntimeClasspath
...

In the example, we can see that the origin fort he runtime dependency and identify conflicts and track down the dependency selection to resolve issues.

You can think of the dependency insight report as the inverse representation of the dependency report for a given dependency. 

Using the project report plugin

The project report plugin adds some tasks to generate dependency reports. These tasks create the same results than running the commands from the terminal. In contrast to the command line, the report plugin creates a file.

To use the project report plugin. Add the plugin to the app build.gradle

apply plugin: 'project-report' 

And generate the dependency and dependency insight report in HTML using the command line. 

>gradlew htmlDependencyReport

Conclusion

We've reviewed different ways to visualize and analyze the dependency tree and get insights about how Gradle resolves dependencies in your project for different configurations which can be very handy when resolving dependency issues.

What problems have you faced in your projects with conflicting dependencies? Leave your answer in a comment down below and remember to hit the subscribe button!


Comments