Skip to content

Gradle Build Tool Guide — Complete Modern Java and Kotlin Automation

DodaTech Updated 2026-06-23 5 min read

In this tutorial, you'll learn about Gradle Build Tool Guide. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

Gradle is a build automation tool that combines the power of Apache Ant and Maven with a flexible Groovy or Kotlin DSL, incremental build support, and a task-based execution model optimized for multi-project builds.

What You'll Learn

You'll learn how to write Gradle build scripts using Groovy and Kotlin DSL, configure dependencies with rich resolution strategies, create custom tasks, build multi-project applications, and optimize build performance with Caching and parallel execution.

Why Gradle Matters

Gradle is the default build system for Android and is widely adopted in enterprise Java and Kotlin projects. Its incremental build model means only changed inputs are re-processed, making builds significantly faster than Maven for large codebases.

Real-World Use

Gradle builds the Android client for Doda Browser, compiling hundreds of modules with parallel execution and build Caching to reduce CI pipeline time from 45 minutes to under 12.

Prerequisites

  • Java 11+ installed
  • Familiarity with Maven concepts (optional but helpful)
  • Gradle 8.5+ installed

Step 1: Project Setup and Build Script Basics

A Gradle build starts with build.gradle (Groovy DSL) or build.gradle.kts (Kotlin DSL). The file declares plugins, dependencies, and task configurations.

// build.gradle (Groovy DSL)
plugins {
    id 'java'
    id 'application'
}

group = 'com.dodatech'
version = '1.0.0'

java {
    sourceCompatibility = JavaVersion.VERSION_17
    targetCompatibility = JavaVersion.VERSION_17
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'com.google.code.gson:gson:2.10.1'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}

application {
    mainClass = 'com.dodatech.App'
}

Expected output: Running gradle build compiles the source, runs tests, and produces a JAR in build/libs/.

Step 2: Kotlin DSL Version

Kotlin DSL provides type-safe accessors and better IDE support with auto-completion.

// build.gradle.kts
plugins {
    java
    application
    id("com.github.johnrengelman.shadow") version "8.1.1"
}

group = "com.dodatech"
version = "1.0.0"

java {
    sourceCompatibility = JavaVersion.VERSION_17
}

repositories {
    mavenCentral()
}

dependencies {
    implementation("com.google.code.gson:gson:2.10.1")
    testImplementation(platform("org.junit:junit-bom:5.10.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")
}

application {
    mainClass.set("com.dodatech.App")
}

tasks.withType<Test> {
    useJUnitPlatform()
}

Expected output: The Kotlin DSL produces identical build output to the Groovy version, with the added benefit of compile-time error checking for configuration keys.

Step 3: Custom Tasks and Task Graph

Gradle builds are directed acyclic graphs of tasks. You can create custom tasks that depend on other tasks, run conditionally, or Process files.

// Custom task that counts lines of source code
abstract class LineCounter extends DefaultTask {
    @InputDirectory
    abstract DirectoryProperty getSourceDir()

    @OutputFile
    abstract RegularFileProperty getOutputFile()

    @TaskAction
    void countLines() {
        def total = 0
        sourceDir.asFileTree.each { file ->
            total += file.text.readLines().size()
        }
        outputFile.get().asFile.text = "Total lines: $total"
    }
}

tasks.register('countSourceLines', LineCounter) {
    sourceDir = layout.projectDirectory.dir('src')
    outputFile = layout.buildDirectory.file('line-count.txt')
    dependsOn 'compileJava'
}

Expected behavior: Running gradle countSourceLines first compiles Java (due to dependsOn), then counts lines across all source files and writes the total to build/line-count.txt.

Step 4: Multi-Project Builds

Gradle excels at multi-project builds. A settings.gradle file defines the project hierarchy, and subprojects inherit common configuration.

// settings.gradle
rootProject.name = 'myapp'
include 'core', 'api', 'webapp'
// build.gradle — shared configuration for all subprojects
subprojects {
    apply plugin: 'java'

    repositories {
        mavenCentral()
    }

    dependencies {
        testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
    }
}
// api/build.gradle — module-specific configuration
dependencies {
    implementation project(':core')
    implementation 'org.springframework.boot:spring-boot-starter-web:3.2.0'
}

Expected behavior: gradle build from the root compiles all subprojects in dependency order. Changes to core automatically trigger recompilation of api and webapp.

Architecture

flowchart LR
    subgraph "Gradle Build"
        SETTINGS[settings.gradle]
        BUILD[build.gradle]
        SRC[src/]
        CACHE[Build Cache]
    end
    subgraph "Execution"
        TASKS[Task Graph
DAG] DAEMON[Gradle Daemon] WORKERS[Parallel Workers] end subgraph "Outputs" CLASSES[Compiled Classes] REPORTS[Test Reports] ARTIFACT[JAR / AAR] end SETTINGS --> TASKS BUILD --> TASKS SRC --> TASKS DAEMON --> TASKS TASKS -->|incremental| CACHE TASKS --> WORKERS WORKERS --> CLASSES WORKERS --> REPORTS WORKERS --> ARTIFACT

Common Errors

1. Could not find method implementation() for arguments This occurs when the java plugin is not applied before the dependencies block. Plugins must be declared before you use their DSL extensions.

2. Task with name 'build' not found in root project The root project may lack the java plugin. Apply it in subprojects or allprojects if you want the build task available at the root level.

3. Dependency resolution fails with version conflict Different modules may require incompatible versions of the same library. Use gradle dependencyInsight --dependency <name> to trace the conflict and force or constraints to resolve it.

4. Build is not incremental Custom tasks that don't declare proper input/output annotations disable incremental build support. Always annotate task properties with @Input, @InputFiles, @OutputFile, etc.

5. Daemon consumes too much memory The Gradle daemon can be configured with org.gradle.jvmargs=-Xmx2g in gradle.properties. Reduce the heap if memory is constrained on your CI runner.

Practice Questions

1. What is the Gradle daemon and why is it beneficial? The daemon is a long-running JVM Process that keeps project data cached between builds. It eliminates JVM startup time and caches classloaders and task configuration, making subsequent builds significantly faster.

2. How does Gradle's incremental build work? Gradle compares the current inputs and outputs of each task against snapshots from the previous run. If nothing changed, the task is marked UP-TO-DATE and skipped, reducing build time.

3. What is the difference between implementation and api dependencies? implementation keeps the dependency hidden from consumers, while api exposes it transitively. Use api only when consumers must have the dependency on their compile classpath.

4. Challenge: Parallel task execution Configure gradle.properties to enable parallel execution and configure a build cache. Measure the build time difference for a multi-project build with and without parallel mode.

5. Challenge: Custom plugin Write a custom Gradle plugin that generates a version properties file during the build and publishes it as a build artifact.

FAQ

Can Gradle build Android projects?

Yes. Gradle is the official build system for Android. Android projects use the Android Gradle Plugin (AGP) with variants, build types, and product flavors.

How does Gradle compare to Bazel?

Gradle focuses on JVM and Android ecosystems with a flexible DSL. Bazel targets polyglot repositories (C++, Go, Java, Python) with strict hermetic builds and remote execution.

What is the build cache?

The build cache stores task outputs keyed by their inputs. If the same inputs appear on another machine or branch, outputs are pulled from the cache instead of recomputing them.

Next Steps

  • Compare Gradle with Maven to understand when each tool is preferable
  • Learn how CI/CD pipelines use Gradle with build Caching for faster deployments
  • Explore Gradle's Kotlin DSL for type-safe build configuration
  • Review the Docker image build tutorial for containerizing Gradle artifacts

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro