Version is root build.gradle buildscript is overriding subproject buildscript dependency versions

I’m not sure if this is a bug or working as intended (but I’d like to confirm), but it is affecting my plugin’s ability to interact with the android plugin.

I’m using gradle 3.2

This is occurring for me because of transitive dependencies, but I’ve isolated it with the following code

consider the project

<root>
 |_ build.gradle (1)
 \_ module
    |_ build.gradle (2)

build.gradle (1)

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'com.google.guava:guava:18.0'
  }
} 

and

build.gradle (2)

buildscript {
  repositories {
    mavenCentral()
  }
  dependencies {
    classpath 'com.google.guava:guava:19.0'
  }
} 

// this is only available in guava 19
def x = com.google.common.collect.Maps.newLinkedHashMapWithExpectedSize(5);

running ./gradlew or whatever

* Where:
Build file 'test/gradle-issue/module/build.gradle' line: 10

* What went wrong:
A problem occurred evaluating project ':module'.
> No signature of method: static com.google.common.collect.Maps.newLinkedHashMapWithExpectedSize() is applicable for argument types: (java.lang.Integer) values: [5]

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.

As expected if both build.gradle files include guava:19.0 things work just fine.

Trying to figure this out on my own :
If you actually inspect the dependencies by doing this thing I found on the internet in module/build.gradle (2)

// comment this out so we don't die
// def x = com.google.common.collect.Maps.newLinkedHashMapWithExpectedSize(5);

task buildScriptDependencies(type: org.gradle.api.tasks.diagnostics.DependencyReportTask) {
      configurations = project.buildscript.configurations
}

running ./gradlew :module:buildscriptDependencies

:module:buildScriptDependencies

------------------------------------------------------------
Project :module
------------------------------------------------------------

classpath
\--- com.google.guava:guava:19.0

BUILD SUCCESSFUL

Total time: 2.391 secs

^^^^^^^ this is a lie, because the classpath appears to actually be linking to guava 18

What exactly is happening under the hood here that is overriding the sub-module buildscript classpaths?

1 Like

There is a classloader hierarchy from root to child projects. If a root project has loaded a dependency, that version will be used in all subprojects, no matter what they do in their buildscript block. This is something we want to change in the long run, but not easy for backwards compatibility reasons.

I recommend specifying all your buildscript dependencies in the root project.

1 Like

The inability of using the desired version of an external dependency in the build script of a subproject in case another version of that dependency is loaded by the build script of the parent project causes subtle bugs that are very hard to track down. The issue is even less obvious if the parent project just transitively loads that dependency.

Would it be possible to detect such situations and display a warning?

The deceptive information shown by the buildEnvironment task is also problematic.

In any case it would be nice to at least document this behavior in the User Guide.

1 Like