How can the compile configuration have more dependencies than compileClasspath?

I was reviewing configurations for a large, multi-module project and noticed something strange - the compile configuration often has more dependencies than compileClasspath. These are not direct dependencies - they are transitive. The code in the projects makes no direct reference to the missing dependencies, but some are definitely needed because intermediate classes use them.

I’m confused how this could happen in a “normal” project. Looking at JavaBasePlugin.defineConfigurationsForSourceSet in gradle 5.6.x for how the default configurations for a java project are hooked together I see:

compileClasspath <- implementation <- compile

(compileClasspath also extends from compileOnly, but I don’t care about that right now)

Given this, how is it possible that compile has things that compileClasspath does not? Does it have something to do with the various attributes that are set on compileClasspath?

Hi @esword,

First, please avoid using compile in build scripts for both declaring and resolving dependencies. It is deprecated in Gradle 6. And in Gradle 4/5 you also do not need it anymore for Java development.

To answer the question: For backwards compatibility, compile behaves as before so the name is basically incorrect now. It has no attributes which causes the Java Library plugin to fall back to the default behavior which corresponds to the behavior of older Gradle versions. That default behavior is “use the runtime variants”. So what compile gives you should correspond to runtimeClasspath.
compileClasspath can be smaller because implementation/api separation is respected. It will not include downstream implementation dependencies (scope=runtime dependencies in POMs).