Gradle
Build Tool & Package Manager
Gradle
Overview
Gradle is a modern build automation tool that supports multiple languages including Java, Kotlin, Scala, and Android. Using Groovy or Kotlin-based DSL (Domain Specific Language), it provides high flexibility and performance. With advanced features like incremental builds, build caching, and parallel execution, Gradle achieves 2-10x faster builds compared to Maven. As the official build tool for Android chosen by Google, Gradle has become increasingly popular for projects requiring high performance and customization flexibility.
Details
Architecture
Gradle's build scripts are modeled as a directed acyclic graph (DAG) of tasks, enabling sophisticated dependency management and flexible build logic. This task-based approach allows for fine-grained control over the build process.
Key Features
- High Performance: Incremental builds, build cache, and daemon process
- Flexible DSL: Script description in Groovy or Kotlin
- Multi-language Support: Java, Kotlin, Scala, Groovy, Android, and more
- Rich Plugin Ecosystem: Extensible ecosystem with powerful plugins
- Multi-project Builds: Efficient management of large-scale projects
- Advanced Dependency Management: Feature variants, version catalogs
Performance Optimizations
- Incrementality: Avoids unnecessary work by tracking input/output changes
- Build Cache: Reuses build outputs with the same inputs
- Gradle Daemon: Keeps build information "hot" in memory for faster execution
- Parallel Execution: Simultaneous execution of independent tasks
- Compile Avoidance: Avoids recompilation when only implementation changes
Build Lifecycle
- Initialization Phase: Determines project settings and participation scope
- Configuration Phase: Configures tasks and builds dependency relationships
- Execution Phase: Executes the task graph
Task System
Gradle organizes builds as tasks that can be customized and combined in various ways. Tasks are the basic unit of work in Gradle, and they can depend on other tasks, have inputs and outputs, and be incremental.
Dependency Management
Gradle's dependency management is more flexible than Maven's, distinguishing between dependencies required to build a module and those required to build a module that depends on it. It supports rich dependency management features like feature variants and version catalogs.
Advantages & Disadvantages
Advantages
- Superior Performance: 2-10x faster than Maven on average
- High Flexibility: Custom build logic is straightforward to implement
- Modern DSL: Intuitive description with Groovy/Kotlin syntax
- Incremental Builds: Rebuilds only changed parts, saving significant time
- Build Cache: Local and remote cache support for even faster builds
- Multi-language Support: Comprehensive support for various programming languages
- Android Official Support: Google's official build tool for Android development
- Advanced Dependency Management: Rich features like feature variants and dependency constraints
- Powerful Plugin System: Extensible architecture with rich plugin ecosystem
- Better IDE Integration: Excellent support in IntelliJ IDEA and Android Studio
- Composite Builds: Ability to include builds from other projects
Disadvantages
- Learning Curve: More complex to learn compared to Maven
- Complexity: Flexibility can introduce complexity, especially for new developers
- Fewer Plugins: Less extensive plugin library compared to Maven
- Relatively New Tool: Fewer developers proficient with Gradle compared to Maven
- Debugging Difficulty: Complex build scripts can be challenging to debug
- Memory Usage: Daemon process consumes additional memory
- Documentation: Sometimes less comprehensive than Maven's extensive documentation
- Migration Complexity: Converting existing Maven projects can be challenging
References
- Gradle Official Site
- Gradle User Manual
- Gradle vs Maven Comparison
- Gradle Plugin Portal
- Gradle Build Cache
- Gradle Performance Guide
Code Examples
Project Creation
# Create new Gradle project
gradle init --type java-application
# Create Spring Boot project
gradle init --type java-application --dsl kotlin
# Create Kotlin project
gradle init --type kotlin-application
# Create Android project
gradle init --type android-application
# Interactive project creation
gradle init
build.gradle Configuration (Groovy DSL)
plugins {
id 'java'
id 'org.springframework.boot' version '3.2.0'
id 'io.spring.dependency-management' version '1.1.4'
}
group = 'com.example'
version = '1.0.0'
sourceCompatibility = '17'
repositories {
mavenCentral()
gradlePluginPortal()
maven {
url 'https://repo.spring.io/milestone'
}
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'com.h2database:h2'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'junit:junit:4.13.2'
// Logging libraries
implementation 'ch.qos.logback:logback-classic'
}
tasks.named('test') {
useJUnitPlatform()
maxHeapSize = '1G'
testLogging {
events 'passed', 'skipped', 'failed'
}
}
// Custom task
task hello {
doLast {
println 'Hello, Gradle!'
}
}
// Performance optimization
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << '-Xlint:unchecked'
options.deprecation = true
}
}
build.gradle.kts Configuration (Kotlin DSL)
plugins {
java
id("org.springframework.boot") version "3.2.0"
id("io.spring.dependency-management") version "1.1.4"
}
group = "com.example"
version = "1.0.0"
java.sourceCompatibility = JavaVersion.VERSION_17
repositories {
mavenCentral()
gradlePluginPortal()
maven {
url = uri("https://repo.spring.io/milestone")
}
}
dependencies {
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
implementation("com.h2database:h2")
testImplementation("org.springframework.boot:spring-boot-starter-test")
testImplementation("junit:junit:4.13.2")
// Development tools
developmentOnly("org.springframework.boot:spring-boot-devtools")
}
tasks.withType<Test> {
useJUnitPlatform()
maxHeapSize = "1G"
testLogging {
events("passed", "skipped", "failed")
}
}
// Custom task
tasks.register("hello") {
doLast {
println("Hello, Gradle!")
}
}
// Compiler configuration
tasks.withType<JavaCompile> {
options.compilerArgs.addAll(listOf("-Xlint:unchecked", "-Xlint:deprecation"))
}
Dependency Management
dependencies {
// Compile and runtime dependencies
implementation 'org.apache.commons:commons-lang3:3.12.0'
// Compile-only dependencies
compileOnly 'org.projectlombok:lombok:1.18.30'
annotationProcessor 'org.projectlombok:lombok:1.18.30'
// Runtime-only dependencies
runtimeOnly 'mysql:mysql-connector-java:8.0.33'
// Test dependencies
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
// Exclude specific dependencies
implementation('org.springframework.boot:spring-boot-starter-web') {
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
}
// Version range specification
implementation 'com.google.guava:guava:30.0+'
// Platform dependencies (BOM)
implementation platform('org.springframework.boot:spring-boot-dependencies:3.2.0')
// Feature variants
implementation 'com.example:my-library:1.0.0' {
capabilities {
requireCapability 'com.example:my-library-json-support'
}
}
}
// Dependency constraints
dependencies {
constraints {
implementation 'commons-codec:commons-codec:1.15'
}
}
// Version catalog (gradle/libs.versions.toml)
// dependencies {
// implementation libs.spring.boot.starter.web
// testImplementation libs.junit.jupiter
// }
Task Execution
# Clean project
./gradlew clean
# Compile source code
./gradlew compileJava
# Run tests
./gradlew test
# Build project (compile, test, package)
./gradlew build
# Build skipping tests
./gradlew build -x test
# Run application
./gradlew run
# Create JAR file
./gradlew jar
# Show available tasks
./gradlew tasks
# Show dependency tree
./gradlew dependencies
# Enable build cache
./gradlew build --build-cache
# Parallel execution
./gradlew build --parallel
# Continuous build
./gradlew build --continuous
# Profile build performance
./gradlew build --profile
# Debug mode
./gradlew build --debug
# Dry run (show what would be executed)
./gradlew build --dry-run
Custom Tasks
// Simple task
task hello {
doLast {
println 'Hello, World!'
}
}
// File copy task
task copyFiles(type: Copy) {
from 'src/main/resources'
into 'build/resources'
include '**/*.properties'
exclude '**/*.tmp'
}
// Task with dependencies
task buildAndCopy(dependsOn: [build, copyFiles]) {
doLast {
println 'Build and copy completed!'
}
}
// Task with inputs and outputs (for incrementality)
task generateDocs {
inputs.files fileTree('src/main/java')
outputs.file 'build/docs/api.html'
doLast {
// Javadoc generation logic
exec {
commandLine 'javadoc', '-d', 'build/docs',
'-sourcepath', 'src/main/java',
'-subpackages', 'com.example'
}
}
}
// Typed task
task zipSources(type: Zip) {
from 'src'
include '**/*.java'
archiveFileName = 'sources.zip'
destinationDirectory = file('build/distributions')
}
// Task with configuration
task integrationTest(type: Test) {
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
shouldRunAfter test
}
Multi-Project Build
// settings.gradle
rootProject.name = 'my-multi-project'
include 'core', 'web', 'api', 'common'
// Optional: custom project locations
// project(':web').projectDir = file('web-module')
// Root project build.gradle
allprojects {
group = 'com.example'
version = '1.0.0'
repositories {
mavenCentral()
}
}
subprojects {
apply plugin: 'java'
apply plugin: 'java-library'
sourceCompatibility = '17'
targetCompatibility = '17'
dependencies {
testImplementation 'junit:junit:4.13.2'
}
// Common test configuration
test {
useJUnitPlatform()
testLogging {
events 'passed', 'skipped', 'failed'
}
}
}
// Configure specific subprojects
configure(subprojects.findAll { it.name != 'common' }) {
dependencies {
implementation project(':common')
}
}
// Subproject build.gradle (web module)
dependencies {
api project(':core') // Exposes core to consumers
implementation project(':common')
implementation 'org.springframework.boot:spring-boot-starter-web'
testImplementation project(':core').sourceSets.test.output
}
// Project dependency commands
./gradlew :web:build // Build web module
./gradlew build // Build all modules
./gradlew :core:test // Test core module only
./gradlew test // Test all modules
Advanced Features
// Version catalogs (gradle/libs.versions.toml)
// [versions]
// spring-boot = "3.2.0"
// junit = "5.9.2"
//
// [libraries]
// spring-boot-starter-web = { module = "org.springframework.boot:spring-boot-starter-web", version.ref = "spring-boot" }
// junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit" }
// Build cache configuration
buildCache {
local {
enabled = true
directory = file('build-cache')
}
remote(HttpBuildCache) {
url = 'https://example.com/build-cache/'
push = true
credentials {
username = System.getenv('CACHE_USERNAME')
password = System.getenv('CACHE_PASSWORD')
}
}
}
// Composite builds (settings.gradle)
includeBuild '../shared-library'
includeBuild '../plugins' {
dependencySubstitution {
substitute module('com.example:plugin') with project(':')
}
}
// Performance configuration (gradle.properties)
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configureondemand=true