gradle dependencies
allows to display dependencies in your project printed as pretty ascii tree. Unfortunately it does not work well for submodules in multi-project build. I was not able to find satisfactory solution on the web, so after worked out my own that blog post arose.
Multiple subprojects
For multi-project builds gradle dependencies
called in the root directory unexpectedly displays no dependencies:
In fact Gradle is right. Root project usually has no code and no compile or runtime dependencies. Only in case of using plugins there could be some additional configurations created by them.
You could think about --recursive
or --with-submodules
flags, but they do not exist. It is possible to display dependencies for subprojects with “gradle sub1:dependencies
” and “gradle sub2:dependencies
“, but this is very manual and unpractical for more than a few modules. We could write a shell script, but having regard to (potential) recursive folders traversal there are some catches. Gradle claims to be very extensible with its Groovy based DSL, so why not take advantage of that. Iteration over subprojects can give some effects, but after testing a few conception I ended with pure and simple:
subprojects { task allDeps(type: DependencyReportTask) {} }
When called gradle allDeps
it executes dependencies
task on all subprojects.
Remove duplication
All dependencies belong to us, but some parts of the tree looks similar (and duplication is a bad thing). Especially configurations default
, compile
and runtime
and the second group testCompile
and testRuntime
in most cases contain (almost) the same set of dependencies. To make the output shorter we could limit it to runtime
(or in case of test dependencies testRuntime
). dependencies
task provides convenient parameter --configuration
and to focus on test dependencies “gradle allDeps --configuration testRuntime
” can be used.
Summary
Where it could be useful? Recently I was pair programming with my old-new colleague in a new project (with dozens submodules) where SLF4J in addition to expected slf4j-logback
provider discovered on a classpath also slf4j-simple
. We wanted to figure out which library depends on it. Logging dependencies tree to file with a help of grep gave us the answer.
As a bonus during my fights with DependencyReportTask
I found an easier way how get know who requires given library. I will write about it in my next post.
Tested with Gradle 2.2.
Very nice (big) gradle banner, do you work for gradle?
Not yet, but it can be possibly changed soon.
[…] Gradle tricks – display dependencies for all subprojects in multi-project build […]
For a multiproject setup, i had to use following script:
Maybe it would cleaner to create that task only in the subproject with source code?
[…] Gradle tricks – display dependencies for all subprojects in multi-project build […]
If you would like to analyze result ascii tree dependencies, you can try to use this tool:
https://github.com/avast/gradle-dependencies-viewer
Looks interesting. Thanks for sharing.
Wonderful, what a web site it is! This weblog provides valuable facts to us, keep it up.
Thanks for sharing!
If gradle is configured to run tasks in parallel, this wil make the output useless, because it interweaves output from the different subprojects.
I added this to solve it:
“`
// Create a chain of dependencies between all sub project’s “allDeps” tasks, so that the output is linear
// even when we run gradle in default “–parallel” mode.
def allSubProjects = subprojects as List
for (def index = 1; index < allSubProjects.size; ++index) {
allSubProjects[index].tasks.allDeps.dependsOn allSubProjects[index – 1].tasks.allDeps
}
“`
Thanks for sharing. That in fact could be some problem, but for most of the projects I worked with it was doable to just wait a little bit longer executing just that one task. However then, you need to remember to disable the parallel mode :).
Btw, what Gradle version do you use? I believe in one of the Gradle versions released this year I have seen an improvement which was sorting out the console output in the parallel mode. Therefore, maybe it is already fixed out-of-box in 4.10?