Creating and Managing Multi-Build Projects
Estimated time to read: 3 minutes
Overview¶
Applications that consist of multiple projects, each project will have it's own build file Specify a top level build file to configure projects and set dependencies Specify a top level settings file to specify projects Project level build files, these set project level properties and tasks
Multi-Project Builds¶
Demo File Structure¶
Example file structure for the demo throughout this module.
- jacket
- build.gradle
- settings.gradle
- Repository
- src
- build.gradle
- JacketService //Depends on Repository
- src
- build.gradle
settings.gradle¶
include 'Repository', 'JacketService' //Include both sub-project folders into our multi-build project
build.gradle¶
Here, we can add properties to the file that affect all of the projects and we can add project specific settings to the file.
allprojects { //Applies to all projects within the build file
plugins {
id 'java'
}
}
version = '1.0-SNAPSHOT' //Set the version string for all of the projects
project(':Repository') { //Project specific settings syntax
}
project(':JacketService') {
dependencies {
implementation project(':Repository') // JacketService is dependent on the Repository project
}
}
build.gradle.kts¶
allprojects { //Applies to all projects within the build file
apply(plugin="java")
version = '1.0-SNAPSHOT' //Set the version string for all of the projects
}
project(':Repository') { //Project specific settings syntax
}
project(':JacketService') {
dependencies {
implementation project(':Repository') // JacketService is dependent on the Repository project
}
}
The above build files will first build the Repository project, as JacketService is dependant on it, then build the JacketService.
Top-level variable inheritance¶
Version variables can be defined in the top-level build file. These variables are then also accessible from any sub-project build files that are called by the top-level build file.
allprojects¶
The allprojects
element affects all projects within the build file including the top-level.
allprojects { //Applies to all projects within the build file
plugins {
id 'java'
}
version = '1.0-SNAPSHOT' //Set the version string for all of the projects
}
subprojects¶
The subprojects
element, conversely to the allprojects
element, only affects sub-projects, it does not affect the top-level.
Kotlin quirks¶
When using a build file based on the Kotlin DSL, it is worth noting that any variables that have been specified at the top of the file, or in settings.gradle, have to be redeclared when used within an allprojects
or subprojects
block.
val h2_version: String by project
allprojects { //Applies to all projects within the build file
apply(plugin="java")
version = '1.0-SNAPSHOT' //Set the version string for all of the projects
}
subproject {
dependencies {
val h2_version: String by project
classpath("com.h2database:h2:$h2_version")
}
}
project(':Repository') { //Project specific settings syntax
}
Using the java-library plugin¶
Example Top-level build.gradle¶
plugins {
id 'java'
}
subprojects {
repositories {
jcenter()
}
}
version = '0.1-SNAPSHOT'
project(':jCurlLib'){
dependencies {
}
}
project(':TerminalClient') {
apply plugin: 'java'
dependencies {
implementation project(':jCurlLib')
}
}
Example jCurlLib build.gradle¶
apply plugin: 'java-library'
dependencies {
implementation 'org.apache.httpcomponentsLhttpcore:4.4.13'
}
Example TerminalClient build.gradle¶
Explanation¶
In the example above, jCurlLib
is using the java-library
plugin.
There is a client class within jCurlLib
's code. The important part of this class is its' return value. It returns type StatusLine
. which is a part of the Apache HttpCore library.
StatusLine
is called within TerminalClient's code through the use of a instantiated object, however, TerminalClient's code is unaware of StatusLine
as a type.
This can be fixed by adding a dependency section within the TerminalClient build file. However, this is not good practise. Instead, we edit the jCurlLib
build.gradle file and change implementation
to api
. This tells Gradle to do everything that implementation
does, plus expose this to everything that jCurlLib interacts with; in this instance, TerminalClient
.