Use only direct dependencies during compilation

I recently checked a bunch of Gradle files in our multi modules project. It appeared people quite often just relies on transitive dependencies. Let me explain with an example:

Let’s say I’m working on project A which depends on project B. Project B at the same time depends on Guava. So in my case most likely I won’t specify a dependency on Guava in my build file for project A once I’ll start using it. I can just forget, in any case my project compiles just fine!

What I would like is to have a flag in Java plugin to only include direct dependencies during compilation. It will enforce users to specify all necessary dependencies. Also the classpath will be smaller and as a result compilation should be faster for big projects.

Does it make any sense? Maybe there is already a way to do it in Gradle? I know Blaze alike build systems like Bazel/Buck and Pants are already supporting it.

Sometimes the situation is much more complicated. Transitive dependencies might “leak in” to the main project via different paths. Out of my head I can think of two: being inherited from in the class you directly depend on, and being returned by one of your direct dependencies’ method (even if you don’t use that value).

Things can go even more complicated with Java 8 lambdas and default methods (see e.g. https://bugs.openjdk.java.net/browse/JDK-8055048)

You can try excluding transitive dependencies, as described by https://docs.gradle.org/current/userguide/dependency_management.html#sub:exclude_transitive_dependencies.

For more compilation (and runtime) regime, on a package level, you may consider OSGi budles. But often this is not a simple “drag-and-drop” approach, but requires rethinking your project architecture.

I’m not saying about excluding them completely. Maybe I just explained myself not very clear.

I’m just looking for a way to have a different classpath on the compilation phase. You definitely need to all the deps in runtime but you can compile java with fewer classpath entries. Not including transitive deps in compilation classpath will just force people specify them explicitly. In my example I just want users also specify Guava dependency for project A even though project A pulls it transitively via a dependency on Project B.