What it is
Gradle is a powerful build automation tool that uses a Groovy or Kotlin-based DSL for configuring builds, commonly used for Java, Kotlin, Android, and other JVM-based projects.
Installation
Linux
# Using SDKMAN! (recommended)
sdk install gradle 8.5
# Manual download and setup
wget https://services.gradle.org/distributions/gradle-8.5-bin.zip
unzip gradle-8.5-bin.zip
export GRADLE_HOME=/path/to/your/unzipped/gradle-8.5
export PATH=$GRADLE_HOME/bin:$PATH
macOS
# Using Homebrew
brew install gradle
# Manual download and setup (same as Linux)
wget https://services.gradle.org/distributions/gradle-8.5-bin.zip
unzip gradle-8.5-bin.zip
export GRADLE_HOME=$(pwd)/gradle-8.5 # Navigate to where you unzipped it
export PATH=$GRADLE_HOME/bin:$PATH
Windows
# Using Chocolatey
choco install gradle
# Manual download and setup
# Download the zip file from https://services.gradle.org/distributions/
# Extract it to a directory, e.g., C:\Gradle
# Set the GRADLE_HOME environment variable to C:\Gradle\gradle-8.5
# Add %GRADLE_HOME%\bin to your system's PATH
Core Concepts
- Build Script: Typically
build.gradle(Groovy DSL) orbuild.gradle.kts(Kotlin DSL). Defines tasks, dependencies, and project configuration. - Task: A unit of work in a build (e.g.,
compileJava,test,jar). - Project: A Gradle build is composed of one or more projects. A multi-project build has a root project and one or more subprojects.
- Dependency: External libraries or other modules that your project needs. Gradle manages these.
- Plugin: Extends Gradle’s functionality (e.g., Java plugin for compilation, Spring Boot plugin for packaging).
- Task Graph: Gradle determines the order of task execution based on dependencies between tasks.
- Build Cache: Stores outputs of tasks to avoid re-executing them if inputs haven’t changed.
- Configuration Cache: Caches the result of build script execution, speeding up subsequent builds significantly.
Commands / Usage
Running Tasks
# Run the 'build' task for the current project
./gradlew build
# Run the 'clean' and 'test' tasks
./gradlew clean test
# Run a specific task defined in your build script (e.g., 'myCustomTask')
./gradlew myCustomTask
# Run tasks from a specific subproject (e.g., 'app')
./gradlew :app:assembleDebug
# Run tasks across multiple subprojects
./gradlew :module1:build :module2:build
# List all available tasks
./gradlew tasks
# List tasks with descriptions
./gradlew tasks --all
Dependency Management
# Add a dependency to 'implementation' configuration (Java projects)
dependencies {
implementation 'com.google.guava:guava:32.1.3-jre'
}
# Add a test dependency
dependencies {
testImplementation 'junit:junit:4.13.2'
}
# Declare a dependency version in a version catalog (gradle/libs.versions.toml)
[versions]
guava = "32.1.3-jre"
[libraries]
guava = { group = "com.google.guava", name = "guava", version.ref = "guava" }
# Use a dependency from the version catalog
dependencies {
implementation libs.guava
}
Project Structure and Configuration
# Apply the Java plugin
plugins {
id 'java'
}
# Apply the application plugin (for executables)
plugins {
id 'application'
}
# Configure the main class for the application plugin
application {
mainClass = 'com.example.MyApplication'
}
# Configure the Java compiler version
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
# Define project properties (can be overridden from command line)
ext {
springVersion = '6.1.0'
}
# Access project properties
println project.ext.springVersion
Build Lifecycle Tasks
# Compile project sources
./gradlew compileJava
# Compile test sources
./gradlew compileTestJava
# Run tests
./gradlew test
# Package the project into a JAR file
./gradlew jar
# Assemble all artifacts (e.g., JARs, WARs)
./gradlew assemble
# Install artifacts into the local Maven repository
./gradlew install
# Clean the build outputs (delete build directory)
./gradlew clean
# Check the project (runs tests, static analysis, etc.)
./gradlew check
Wrapper Management
# Generate the Gradle wrapper scripts (gradlew, gradlew.bat)
./gradlew wrapper
# Specify a Gradle version for the wrapper
./gradlew wrapper --gradle-version 8.5
# Run a task using the Gradle wrapper (recommended for consistency)
./gradlew build
Information and Diagnostics
# Show Gradle version
./gradlew --version
# Show dependency tree for a configuration (e.g., 'runtimeClasspath')
./gradlew dependencies --configuration runtimeClasspath
# Show dependency insight (how a specific dependency was included)
./gradlew dependencyInsight --dependency com.google.guava:guava
# Show Gradle daemon status
./gradlew --status
# Enable detailed logging
./gradlew build --debug
# Enable very detailed logging
./gradlew build --stacktrace
# Enable daemon logging
./gradlew build --daemon-log-level=debug
Daemon Control
# Start the Gradle daemon
./gradlew --daemon
# Stop the Gradle daemon
./gradlew --stop
Configuration Cache
# Run a task with configuration cache enabled
./gradlew build --configuration-cache
# Run a task with configuration cache invalidation (forces re-execution)
./gradlew build --no-configuration-cache
Build Cache
# Enable build cache (usually enabled by default if configured)
./gradlew build --build-cache
# Disable build cache for a run
./gradlew build --no-build-cache
Common Patterns
-
Building a project with the wrapper:
./gradlew build -
Cleaning and rebuilding:
./gradlew clean build -
Running specific tests (by class name):
./gradlew test --tests com.example.MyServiceTest -
Running specific tests (by method name):
./gradlew test --tests "com.example.MyServiceTest.testSomething" -
Executing a task only if necessary:
./gradlew assemble --rerun-tasks(Note:
--rerun-tasksforces tasks to run, the opposite of what you want for "only if necessary". The default behavior is to avoid re-running if inputs/outputs are the same. To force re-run, use--rerun-tasks) -
Overriding project properties from the command line:
./gradlew build -PappVersion=1.1.0(In build script:
println project.ext.has('appVersion') ? project.ext.appVersion : 'default') -
Setting JVM arguments for tests:
./gradlew test -Dorg.gradle.jvmargs='-Xmx2048m -Dmy.system.property=value' -
Publishing a library to a local Maven repository:
./gradlew publishToMavenLocal -
Generating a project report:
./gradlew projectReport -
Finding which task depends on another:
./gradlew --dry-run --scan -m <taskName>(Note:
--scanis for Gradle Enterprise, use-mfor task dependency analysis)# More direct way to see task dependencies ./gradlew tasks --all | grep myTask -
Building only a specific subproject:
./gradlew :my-subproject:build -
Running a task for all subprojects:
./gradlew --all-projects build(Note:
--all-projectsis deprecated. Use--parallel --configure-on-demandfor better performance)# Recommended way for parallel execution ./gradlew --parallel build -
Using Kotlin DSL:
# Run tasks from a build.gradle.kts file ./gradlew build
Gotchas
./gradlewvsgradle: Always use./gradlew(orgradlew.baton Windows) to ensure you’re using the Gradle version defined in your project’s wrapper, promoting consistency across developer environments. Using the system-installedgradlecommand might lead to version mismatches and unexpected behavior.- Task Naming Conflicts: If multiple subprojects define tasks with the same name, you must qualify them with the project path (e.g.,
./gradlew :subprojectA:clean). - Daemon Overhead: While the daemon speeds up subsequent builds, the first build or builds after a long idle period can be slower due to daemon startup.
- Configuration Cache Invalidation: If your build script relies on external factors that change (e.g., file system state not managed by Gradle), the configuration cache might become invalid, leading to slower builds as Gradle needs to reconfigure.
- Dependency Hell: Gradle’s powerful dependency management can still lead to conflicts if different libraries require incompatible versions of the same transitive dependency. Use
./gradlew dependenciesand./gradlew dependencyInsightto diagnose. - Build Script Execution: Gradle executes build scripts before running tasks. Any errors in your
build.gradleorbuild.gradle.ktsfiles will prevent tasks from running. cleanTask: Thecleantask is not part of the default task graph. You must explicitly include it (e.g.,./gradlew clean build).- Default Tasks: If no task is specified, Gradle runs the default tasks, which are often
buildfor Java projects orassemblefor Android projects.