New to gradle. I am trying to implement gradle for an existing multi project (java)
build. And there exists circular dependencies between some of the sub projects.
Does gradle support this kind of a scenario? If so, whats the best strategy?
Thanks in advance.
It depends on the nature of your cycles. Dependencies are grouped into configurations. As long as the configurations are cycle-free, you’ll be fine. For instance, the following will work:
project(':a') {
apply plugin: 'java'
dependencies {
testCompile project(':b')
}
}
project(':b') {
apply plugin: 'java'
dependencies {
compile project(':a')
}
}
Still, removing those cycles is probably a good idea
Thanks for your response. I tried the method suggested, still having issue with the build.
I created a simple project to mimic the issue I am trying to resolve.
2 Java Projects:
GradleCycliecDependencyTest, and GradleCycliecDependencyTest are 2 simple Java projects with the cyclic dependency between them.
Class from the first project:
public class TestA1 {
private TestA2 a2;
}
class from the second project:
public class TestA2 {
private TestA1 a1;
}
So, they have circular dependency.
from the CyclicBuild directory:
contents of build.gradle:
project(‘:GradleCyclicDependencyTest’) {
apply plugin: ‘java’
sourceSets {
main {
java {
srcDir "../../$project.name/src"
}
resources {
}
}
}
dependencies {
compile project(‘:GradleCyclicDependencyTest2’)
}
}
project(‘:GradleCyclicDependencyTest2’) {
apply plugin: ‘java’
sourceSets {
main {
java {
srcDir "../../$project.name/src"
}
resources {
}
}
}
dependencies {
testCompile project(‘:GradleCyclicDependencyTest’)
}
}
contents of settings.gradle;
include ‘GradleCyclicDependencyTest’, ‘GradleCyclicDependencyTest2’
When I run the gradle java --info from the CyclicBuild folder, this is the output:
$ gradle java --info
Starting Build
Settings evaluated using settings file ‘C:\LocalSysWorkspaces\RFID\Test\CyclicBuild\settings.gradle’.
Projects loaded. Root project using build file ‘C:\LocalSysWorkspaces\RFID\Test\CyclicBuild\build.gradle’.
Included projects: [root project ‘CyclicBuild’, project ‘:GradleCyclicDependencyTest’, project ‘:GradleCyclicDependencyTest2’]
Evaluating root project ‘CyclicBuild’ using build file ‘C:\LocalSysWorkspaces\RFID\Test\CyclicBuild\build.gradle’.
Evaluating project ‘:GradleCyclicDependencyTest’ using build file ‘C:\LocalSysWorkspaces\RFID\Test\CyclicBuild\GradleCyclicDependencyTest\build.gradle’.
Evaluating project ‘:GradleCyclicDependencyTest2’ using build file ‘C:\LocalSysWorkspaces\RFID\Test\CyclicBuild\GradleCyclicDependencyTest2\build.gradle’.
All projects evaluated.
Selected primary task ‘javadoc’ from project :
Tasks to be executed: [task ‘:GradleCyclicDependencyTest2:compileJava’, task ‘:GradleCyclicDependencyTest2:processResources’, task ‘:GradleCyclicDependencyTest2:classes’, task ‘:GradleCyclicDependencyTest2:jar’, task ‘:GradleCyclicDependencyTest:compileJava’, task ‘:GradleCyclicDependencyTest:processResources’, task ‘:GradleCyclicDependencyTest:classes’, task ‘:GradleCyclicDependencyTest2:javadoc’, task ‘:GradleCyclicDependencyTest:javadoc’]
:GradleCyclicDependencyTest2:compileJava (Thread[main,5,main]) started.
:GradleCyclicDependencyTest2:compileJava
file or directory ‘C:\LocalSysWorkspaces\RFID\Test\CyclicBuild\GradleCyclicDependencyTest2\src\main\java’, not found
file or directory ‘C:\LocalSysWorkspaces\RFID\Test\CyclicBuild\GradleCyclicDependencyTest2\src\main\java’, not found
Executing task ‘:GradleCyclicDependencyTest2:compileJava’ (up-to-date check took 0.043 secs) due to:
No history is available.
All input files are considered out-of-date for incremental task ‘:GradleCyclicDependencyTest2:compileJava’.
file or directory ‘C:\LocalSysWorkspaces\RFID\Test\CyclicBuild\GradleCyclicDependencyTest2\src\main\java’, not found
Compiling with JDK Java compiler API.
C:\LocalSysWorkspaces\RFID\Test\GradleCyclicDependencyTest2\src\TestA2.java:4: error: cannot find symbol
private TestA1 a1;
^
symbol: class TestA1
location: class TestA2
1 error
:GradleCyclicDependencyTest2:compileJava FAILED
:GradleCyclicDependencyTest2:compileJava (Thread[main,5,main]) completed. Took 0.277 secs.
FAILURE: Build failed with an exception.
- What went wrong:
Execution failed for task ‘:GradleCyclicDependencyTest2:compileJava’.
Compilation failed; see the compiler error output for details.
- Try:
Run with --stacktrace option to get the stack trace. Run with --debug option to get more log output.
BUILD FAILED
Not sure if the method you suggested handles the circular dependency shown here, or if I am doing something wrong. Thanks for for your assistance.
What I posted was only meant as an example. It would work if A only needed B for testing.
The example you posted has the implementation of A depending on the implementation of B and vice versa. That won’t work. How do you build that project currently?
What could work (but I don’t know if that is your case):
- The implementation of A depends on the api of B
- The implementation of B depends on the api of A
- The apis of both are independent
In that case, you’ll need to model a seperate api jar for both projects, so they could reference each other through that.
We build it using eclipse currently. If implementation of A depends on implementation of B and viceversa, is there a way to do it in gradle? Not sure how eclipse does it.
No, there is not. Gradle builds based on source sets. You’ll have to break it up into parts that can be built independently.
Eclipse builds based on individual files, so it can in principle handle such cycles. But cycles are flagged as an error by Eclipse by default, for good reason. It’s a design smell that the projects should either be merged or refactored.