Breaking the build 😝 : Demystifying Gradle

bansalayush

Ayush Bansal

Posted on October 30, 2024

Breaking the build 😝 : Demystifying Gradle

As an Android developer, I've always been deep into coding and app design, but kind of skimmed over the whole Gradle thing—even though it's such a key part of our workflow. Recently, I decided to really get to know Gradle, and I want to share what I've learned.
Let's break down some of its complexities and actually understand Gradle.

Understanding Settings file

Let's get started by creating an empty project in Jetbrain's IntelliJ IDEA (Community Edition)

The settings file, either settings.gradle or settings.gradle.kts, is the entry point of any Gradle project. Create a new file setting.gradle.kts. Your project structure should appear as follows


Ignore other files for now

Key Components of the Settings File

The settings file serves several purposes, but here are the three primary aspects to keep in mind:

  • Naming Your Project: Give your project a stable identifier using the rootProject.name property.
rootProject.name = "demo-project"
Enter fullscreen mode Exit fullscreen mode
  • Dependency and Plugins: Specify where Gradle should look for other components your build may depend upon. There are two fundamentally different things:
    • The first thing are libraries your production code might need. e.g., an Apache Commons library.
    • The second thing are plugins that extend Gradle itself.

These are usually located in the Gradle plugin portal, google and mavenCentral but may also be provided through other binary repositories. Or, you may also define plugins locally in other builds.

dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
    }
}
pluginManagement{
    repositories {
        gradlePluginPortal()
        google()
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Structuring Your Project: Organize your project into subprojects using the include() function. This helps in managing separate components of your application. e.g., we are defining 3 sub-projects "business-logic", "data-model", and "app".
include(":business-logic")
include(":data-model")
include(":app")
Enter fullscreen mode Exit fullscreen mode

Based on the three points discussed, your settings.gradle.kts file should be structured like this

rootProject.name = "demo-project"
dependencyResolutionManagement {
    repositories {
        google()
        mavenCentral()
    }
}
pluginManagement{
    repositories {
        gradlePluginPortal()
        google()
    }
}
include(":business-logic")
include(":data-model")
include(":app")
Enter fullscreen mode Exit fullscreen mode

The project structure, once the components are configured in the settings file, should appear as follows


Understanding Build Files

We have created a project with three subprojects namely

  • business-login
  • data-model
  • app

So far, these subprojects are empty and thus have no real meaning to Gradle. We can add a build file to each of them to change this.

The build file, either build.gradle or build.gradle.kts, is the heart of Gradle projects.
These files are crucial as they dictate how your project is built, what plugins and dependencies are included, and how your source code is organized.

Key Components of the Build File

Let's take a closer look at the build file for our business-logic project. There are three things to configure in your build files.

  • Configuring Plugins: This is the first component in any build file. The plugins section provides structure by specifying the type of project you are building, enabling Gradle and your IDE to understand your project’s layout, compile options, and packaging details. Let’s clarify with an example. In this example, we’ll apply the Java Library Plugin.
plugins {
    id("java-library")
  }
Enter fullscreen mode Exit fullscreen mode

Applying this plugin turns the subproject into a Java Library project, so Gradle and the IDE know where the source code is located, how the code is compiled, and how it’s packaged into a JAR file.

  • Setting Extension: Plugins often come with extensions that enable further customization. For the Java Library plugin, you can access the Java extension to configure compilation specifics, such as targeting a certain Java version.
   java {
       sourceCompatibility = JavaVersion.VERSION_11
       targetCompatibility = JavaVersion.VERSION_11
   }
Enter fullscreen mode Exit fullscreen mode
  • Defining Dependencies: Dependencies are what your subproject relies on for building and running. They can include other subprojects or external components housed in repositories. Here’s how you can define them:
   dependencies {
       // Dependency on internal subproject
       implementation(project(":data-model"))
       // External library dependency
       implementation("org.apache.commons:commons-lang3:3.12.0")
   }
Enter fullscreen mode Exit fullscreen mode

Here, implementation is used to denote compile-time dependencies. The project keyword assists in referring to subprojects, while the external component is specified through its group, name, and version.

Based on the three points discussed, your business-logic/build.gradle.kts file should be structured like this

plugins {
   id("java-library")
}

java {
   sourceCompatibility = org.gradle.api.JavaVersion.VERSION_11
   targetCompatibility = org.gradle.api.JavaVersion.VERSION_11
}

dependencies {
   implementation(project(":data-model"))
   implementation("org.apache.commons:commons-lang3:3.12.0")
}
Enter fullscreen mode Exit fullscreen mode

And Project structure should appear as follows

Sharing my notes/project(which form the base of this and upcoming article/s) as github project .

In our future discussions, we'll delve deeper into advanced Gradle features and plugins, further expanding development toolkit. Till then Keep exploring and building :🚀🚀!

💖 💪 🙅 🚩
bansalayush
Ayush Bansal

Posted on October 30, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related