Gradle Architecture — The arrangement to handle single and multiple projects

Project — This is the image provided by the gradle community which represents the architecture and internal working. Let us understand the components inside this.
First part, is the project. It is the software that can be built such as an application or a library. We can have single project or multiple projects depending on our architecture. Each project have its own build.gradle file along with the source code in their root path which has the dependencies and plugins information.
build.gradle — In the build file, two types of dependencies can be added:
- The libraries and/or plugins on which Gradle and the build script depend.
- The libraries on which the project sources (i.e., source code) depend.
//Adding a plugin to a build is called applying a plugin and makes additional functionality available.
plugins {
id 'application'
}
//The application plugin defines tasks that package and distribute an application, such as the run task.
// The Application plugin provides a way to declare the main class of a Java application, which is required to execute the code.
application {
mainClass = 'com.example.Main'
}
settings.gradle :The primary purpose of the settings file is to add subprojects to your build
For single project it is optional. But is required for the sub projects
//Setting the project name
rootProject.name = 'root-project'
//including the sub projects
include('sub-project-a')
include('sub-project-b')
include('sub-project-c')
Gradle — The wrapper is available as the gradlew and gradlew.bat which standardizes a project with same version.
.
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
└── gradlew.bat
gradle-wrapper.jar: This is a small JAR file that contains the Gradle Wrapper code. It is responsible for downloading and installing the correct version of Gradle for a project if it’s not already installed.
gradle-wrapper.properties: This file contains configuration properties for the Gradle Wrapper, such as the distribution URL (where to download Gradle from) and the distribution type (ZIP or TARBALL).
gradlew: This is a shell script (Unix-based systems) that acts as a wrapper around
gradle-wrapper.jar. It is used to execute Gradle tasks on Unix-based systems without needing to manually install Gradle.gradlew.bat: This is a batch script (Windows) that serves the same purpose as gradlew but is used on Windows systems.
Dependency Manager — Declares and resolves external resources required by a project.
To add dependency to the project, we specify the dependency in the dependencies block of build.gradle file
dependencies {
// Dependency on a remote binary to compile and run the code
implementation(libs.googleMaterial)
// Dependency on a remote binary to compile and run the test code
testImplementation(libs.mockitoCore)
}
To View the dependency tree of the project we can use the following command
./gradlew :app:dependencies
Task — Independent unit of work that the build performs. For Eg., compiling classes, creating a JAR, generating Javadoc, publishing to repository.
we can invoke the task using gradle commands. For Example, you want to build the app and it is considered as task.
./gradlew build
When we run this task, there are multiple tasks within the build task is run like compile classes task, start scripts, assemble etc.,
Plugins — As mentioned earlier, the plugins give extra capability to the gradle build task. There are 3 ways :
- Core Plugins(Gradle develops and maintains) — These are included in Gradle distribution and has unique name for example, java
plugins {
id("java")
}
- Community Plugins (Gradle community shares) — Additional functionalities tha may be specific to certain usecases or technologies but not included in core. For Example, spring boot
plugins {
id("org.springframework.boot") version "3.1.5"
}
- Local Plugins(Custom created) — These are created and used by the specific project or organization.Steps involves are as follows:
Define the plugin class: create a new class that implements the Plugin<Project> interface.
// Define a 'HelloPlugin' plugin
class HelloPlugin : Plugin<Project> {
override fun apply(project: Project) {
// Define the 'hello' task
val helloTask = project.tasks.register("hello") {
doLast {
println("Hello, Gradle!")
}
}
}
}
Build and optionally publish your plugin: This generates JAR file
// Publish the plugin
plugins {
`maven-publish`
}
publishing {
publications {
create<MavenPublication>("mavenJava") {
from(components["java"])
}
}
repositories {
mavenLocal()
}
}
Apply your plugin: use the plugin in the plugins block of build file.
// Apply the plugin
plugins {
id("com.example.hello") version "1.0"
}
Incremental Build — avoids running tasks if the files are not changed. The build cache stores previous builds results and restores them when needed.
./gradlew compileJava --build-cache
Build Scans — Captures build metadata and sends it to the build scan service. It then transforms the metadata to information you can analyze and share with others. To enable it we can run the following command
./gradlew build --scan