Problem with cross-project dependencies

I have a multi-project build and I am trying to set up cross-project lib dependencies as described in http://gradle.org/docs/current/userguide/multi_project_builds.html in section 49.25.

In the build.gradle of the root project I have this:

project(':Content') {
 dependencies {
  compile project(':Core')
 }
}

In settings.gradle both the Content & the Core projects are declared.

When I try and run the build I get this error:

FAILURE: Build failed with an exception.
  * Where:
Script 'C:\Projects1\master\build.gradle' line: 1
  * What went wrong:
A problem occurred evaluating script.
> No signature of method: org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler.compile() is applicable for argument types: (org.gradle.api.internal.project.DefaultProject_Decorated) values: [project ':Core']
Possible solutions: module(java.lang.Object)
  * Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
  BUILD FAILED
  Total time: 2.902 secs

One thing to note - If I go into the build.gradle of the Content project and put in

dependencies {
  compile project(':Core')
 }

it does work. I don’t want to do it that way - I want all of my cross-project dependencies declared at the root project level.

Before you can add dependencies to the ‘compile’ configuration, you have to introduce it. In other words, you have to make sure that the ‘java’ plugin gets applied to a particular project before its dependencies are declared.

I did that as well to no avail. In the build.gradle in the root project I had

apply plugin: 'tiaa-java'

which is a custom-build plugin, loaded beforehand in the same build.gradle using a buildscript {} block.

And actually it doesn’t seem to matter if I just apply the default gradle plugin. This is my root project’s build.gradle:

apply plugin: 'java'
  project(':Content') {
 dependencies {
  compile project(':Core')
 }
}

and my settings.gradle

includeFlat 'Core', 'Content', 'Preferences'
rootProject.name = 'Atom Framework'

It still produces the same result.

Have you applied the ‘java’ plugin to the child project anywhere? I think you want…

project(':Content') {
    apply plugin: 'java'
     dependencies {
        compile project(':Core')
    }
}

To get a ‘compile’ configuration for the ‘:Content’ project, you have to apply the ‘java’ plugin to the ‘:Content’ project (not the root project). You could also apply the ‘java’ plugin to ‘allprojects {}’ or ‘subprojects {}’.

Each subproject already has the java plugin applied (via using a custom tiaa-java plugin).

Here is Content’s build.gradle (& actually it is identical for the Core project):

buildscript {
 dependencies {
  classpath files(fileTree(dir: "${rootProject.projectDir}/lib/build", includes: ['*.jar']))
 }
}
  apply plugin: 'tiaa-java'

That’s too late as the root project’s build script gets evaluated before the subprojects’ build scripts (at least by default). What’s the intention behind specifying some things (e.g. dependencies) in the root build script and others (e.g. plugins) in the per-project build scripts? Understanding the intention will help us to suggest a solution.

Right, so it’s an ordering issue.

See http://gradle.org/docs/current/userguide/userguide_single.html#sub:configuration_time_dependencies.

Configuration is in top down, breadth-first, alpha numeric order.

I think it is cleaner to be able to define cross-project dependencies in the root project’s buildscript. Thats one place to look to see which projects depend on what, rather than having to specify the dependencies as part of each project.

For example, in this particular project I am going to have upwards of 10 or so sub-projects. All of them will depend on 1 particular other sub-project (Core). Some of the other projects might depend on others. I just thought it would be cleaner to set up all of the dependencies inside the root project. Otherwise to figure out all of the cross-project dependencies you would have to go through each sub-project’s buildscript and take notes :slight_smile:

Have a read of that section of the user guide. It explains the constructs you can use to do what you want.

Perfect - adding

evaluationDependsOnChildren()

in my root project’s build.gradle allows me to now do things like

project(':Content') {
  dependencies {
  compile project(':Core')
 }
}

inside my root project.

Thanks for the help!

If I wanted to set it up automatically that every sub-project (except the Core project itself) depended on Core without having to explicitly list out each project, could I do something like this in the root project’s build file?

configure(subprojects.findAll { it.name != 'Core' }) {
 logger.lifecycle "Configuring project $name"
    dependencies {
  compile project(':Core')
 }
}

This doesn’t seem to work. It doesn’t give any errors but it doesn’t add the dependency either - when I run a build the Core project doesn’t seem to be built before the others like I would expect.

‘subprojects {}’ is not recursive, it only applies to the immediate children. Could that be it?

I don’t have nested subprojects - only 1 level of depth.

That should work then. Can you create a reproducible sample?

It’s supposed to be recursive.