I have been using Gradle for some time now but have never delved deeper into it's many features and functionalities, but the other day I decided to split my Java project into two modules for easier testing and maintenance. After I was done I started reading about Authoring Multi-projects and one of the newer Gradle concepts called Composite builds. Then I proceeded to spend the better part of the day trying to apply (what I thought I understood) this knowledge on making my project modular. It's safe to assume that I was not successful and now here I am asking for help in understanding these concepts and their application.
Theoretical Workspace
Let us imagine that we have the following directory structure:
toolbox
|
├── first-tool
| └── build.gradle
|
├── second-tool
| └── build.gradle
|
├── build.gradle
└── settings.gradle
And these are the projects inside the root directory:
Root project 'toolbox'
+--- Project ':first-tool'
\--- Project ':second-tool'
Let's make project first-tool
introduce an external dependency org.master-toolbox:some.other.tool
on which the second toolbox is dependent on but does not implement itself:
default - Configuration for default artifacts.
+--- org.master-toolbox:some.other.tool:1.0
| +--- ...
\--- io.toolbox:first-tool
These are the relevant Gradle files:
settings.gradle
rootProject.name = 'toolbox'
include 'first-tool', 'second-tool'
toolbox.build.gradle
allprojects {
apply plugin: 'java-library'
group = "io.toolbox"
repositories {
jcenter()
}
}
first-tool.build.gradle
dependencies {
// This is an external dependency that is resolved through jcentral
implements 'org.master-toolbox:some.other.tool:1.0'
}
second-tool.build.gradle
dependencies {
// Try to implement first-tool build to inherit dependencies
implementation 'io.toolbox:first-tool'
}
The above produces a nice project structure as shown above but would not fully work because second-tool
would not find first-tool
and something similar to the following error would appear in our console:
> Could not resolve all files for configuration ':second-tool:compileClasspath'.
> Could not find io.toolbox:first-tool:.
Required by:
project :second-tool
Now as far as I understand it this is where composite builds are suppose to swoop-in and save the day by allowing us to include entire builds. Well that sounds great, let us just update out settings.gradle
:
rootProject.name = 'toolbox'
includeBuild `first-tool`
include 'second-tool'
Now the project builds and compiles properly, everything is good right? Well not exactly, as by using the includeBuild
keyword in our settings.gradle
first-tool
is no longer inheriting properties from toolbox
and has essentially stopped being a sub-project of toolbox
.
Project Goal
I am most probably misunderstanding the whole concept of composite builds or just making silly mistakes. Either way what I would like to know is if there is any way to have a hierarchical multi-project structure with sub-projects that are interdependent upon each-other?
As it stands I have to choose between the following:
- a regular multi-project build where everything is neat and organized and all my sub-projects share the same definitions from the top project.
- a composite build where I am free to create inter-project dependencies.
It would be great if it was possible to have a main build.gradle
that resides at the top project's root directory and defines the common plugins, repositories, group etc. for the whole hierarchy. Other projects would then have their own build.gradle
files that would give them unique properties but would execute their tasks from the top project.
I have already read the official documentation on this subject so I am looking for more concrete explanations and directions on how to accomplish this specific goal.