Install Now

gradle/gradle

Gradle Build Tool

Last updated on Dec 18, 2025 (Commit: 913db15)

Overview

Relevant Files
  • README.md
  • CONTRIBUTING.md
  • architecture/README.md
  • build.gradle.kts
  • settings.gradle.kts

Gradle is a highly scalable, open-source build automation tool designed to handle everything from large multi-project enterprise builds to quick development tasks. It supports multiple languages including Java, Kotlin, Scala, Android, Groovy, C++, and Swift, making it a versatile solution for modern software development.

Core Purpose

Gradle automates the build, test, and deployment lifecycle of applications. Its modular, performance-oriented architecture seamlessly integrates with development environments and CI/CD systems, providing developers with a powerful and flexible build system.

Key Characteristics

  • Scalability: Handles projects from small single-module applications to massive multi-project enterprise builds
  • Performance: Optimized for speed with incremental builds, parallel execution, and build caching
  • Flexibility: Supports multiple programming languages and platforms through a plugin-based architecture
  • Developer Experience: Integrates with popular IDEs (IntelliJ IDEA, Android Studio, Eclipse, VS Code) and CI systems (GitHub Actions, GitLab CI, Jenkins, CircleCI)

Repository Structure

gradle/
├── platforms/              # Coarse-grained components providing specific automation
│   ├── core-configuration/ # Configuration and project setup
│   ├── core-execution/     # Task execution engine
│   ├── core-runtime/       # Runtime infrastructure
│   ├── jvm/                # Java/Kotlin/Groovy support
│   ├── native/             # C++ and native language support
│   ├── software/           # Software development features
│   ├── ide/                # IDE integration
│   └── enterprise/         # Enterprise features
├── subprojects/            # Core Gradle components
├── build-logic/            # Build system configuration and plugins
├── testing/                # Test suites and testing infrastructure
├── architecture/           # Architecture documentation and ADRs
└── packaging/              # Distribution packaging

Architecture Overview

Gradle's architecture is organized around three key concepts:

Platforms: Coarse-grained components that provide specific automation capabilities. Each platform extends others to add features like JVM support, native compilation, or IDE integration.

Runtimes: Different processes that work together (Gradle daemon, gradlew command, tooling API clients). Each runtime has different constraints and available services.

Build State Model: Tracks the state of build components (projects, tasks, configurations) and coordinates state transitions throughout the build lifecycle.

Getting Started

To contribute or develop with Gradle:

  1. Requirements: Adoptium JDK 17, IntelliJ IDEA CE (2021.2.2+), Git
  2. Setup: Fork and clone gradle/gradle, configure Git credentials
  3. Development: Import build.gradle.kts into IntelliJ as a project
  4. Testing: Run ./gradlew :<subproject>:quickTest for targeted tests
  5. Local Install: Use ./gradlew install -Pgradle_installPath=/path to test changes

Community & Support

Architecture & Platform Design

Relevant Files
  • architecture/platforms.md
  • architecture/build-execution-model.md
  • architecture/build-state-model.md
  • architecture/runtimes.md
  • settings.gradle.kts

Gradle is organized into coarse-grained platforms and architecture modules that separate concerns and enable independent evolution. Understanding this structure is essential for navigating the codebase and implementing features correctly.

Platform Architecture

Gradle's architecture is built on a layered platform model where each platform provides support for a specific domain of automation:

  • Core Platform — The foundation providing general-purpose task definition and execution. Composed of three modules: core-runtime (process containers), core-configuration (build structure and DSL), and core-execution (scheduling, caching, and execution).
  • Software Platform — Extends core to add software development automation: compilation, testing, publishing, and dependency management.
  • JVM Platform — Extends core and software to provide Java, Kotlin, Groovy, and Scala support.
  • Extensibility Platform — Extends core, software, and JVM to enable plugin development and distribution.
  • Native Platform — Extends core and software to support C++, C, and Swift development.

Cross-cutting modules like Enterprise, IDE, and Documentation integrate horizontally across platforms.

Gradle Runtimes

Gradle executes as multiple coordinated Java processes, each with distinct constraints and responsibilities:

Loading diagram...
  • CLI Client — The gradle or gradlew command; locates, starts, and communicates with the daemon.
  • Gradle Daemon — Long-running process that configures the build, coordinates execution, and manages lifecycle.
  • Tooling API Client — Library embedded in IDEs and CI systems for programmatic build interaction.
  • Worker Processes — Daemon-spawned processes for specific work like compilation or testing.

Each runtime has different JVM compatibility requirements and available services. Code must declare its target runtime in the build script.

Build State Model

Gradle tracks state hierarchically as it executes:

Loading diagram...
  • Build Process — Global state for a Gradle process instance; persists across invocations.
  • Build Session — Single Gradle invocation (e.g., gradlew build); may run the build multiple times if continuous build is enabled.
  • Build Tree — The complete build definition for one execution; includes root and included builds.
  • Build — State for a single build within the tree.
  • Project — State for a project within a build.

Each state level is managed by a corresponding class (BuildProcessState, BuildSessionState, etc.) and can be extended by architecture modules via GradleModuleServices.

Build Execution Model

Gradle follows a simple request-response protocol:

  1. Client locates or starts an idle daemon
  2. Client sends a work request to the daemon
  3. Daemon validates it can accept the request; rejects if busy or shutting down
  4. Daemon executes the request, streaming back logs and events
  5. Daemon returns the result
  6. Client disconnects

This model ensures single-threaded execution per daemon while supporting multiple clients and background monitoring tasks.

Core Runtime & Daemon

Relevant Files
  • platforms/core-runtime/README.md
  • platforms/core-runtime/daemon-main/
  • platforms/core-runtime/daemon-server/
  • platforms/core-runtime/daemon-protocol/
  • platforms/core-runtime/daemon-services/
  • platforms/core-runtime/service-registry-impl/
  • platforms/core-runtime/service-registry-builder/
  • subprojects/core/build.gradle.kts
  • subprojects/core-api/build.gradle.kts

The Core Runtime platform provides the foundational services and infrastructure that all other Gradle platforms depend on. It includes the daemon system, service registry, and essential utilities for build execution.

Daemon System

The Gradle daemon is a long-running process that executes builds. It consists of four key modules:

  • daemon-main: Entry point for the daemon process. Bootstraps the daemon server and handles process initialization.
  • daemon-server: Core daemon implementation that accepts build requests, manages the build lifecycle, and coordinates with clients.
  • daemon-protocol: Defines the communication protocol between clients and the daemon, including message serialization and the daemon registry.
  • daemon-services: Provides daemon-specific services like payload class loaders and user input handling.

The daemon lifecycle is managed through a series of command actions that handle operations like stopping, health checks, build execution, and client communication. The daemon maintains a registry of running instances and manages idle timeouts for process cleanup.

Service Registry System

The service registry is a dependency injection framework that manages service creation and lookup across Gradle's runtime:

  • service-lookup: Defines the ServiceRegistry and ServiceLookup interfaces for read-only service access.
  • service-provider: Provides ServiceRegistrationProvider for declarative service registration using @Provides annotations.
  • service-registry-impl: Implements DefaultServiceRegistry with support for hierarchical registries, service decoration, and lifecycle management.
  • service-registry-builder: Offers ServiceRegistryBuilder for fluent construction of service registries with parent relationships.

Services are discovered through reflection-based factory methods or explicit registration. The registry supports dependency injection, service aggregation, and private services scoped to specific providers.

Core Modules

The core and core-api subprojects aggregate dozens of runtime modules:

  • core-api: Public Gradle APIs required by other subprojects (Task, Project, Plugin interfaces).
  • core: Implementation of core APIs plus internal services for build configuration, execution, and state management.

These modules depend on foundational services like logging, file operations, classloaders, and build operations tracking.

Bytecode Instrumentation

The core runtime includes infrastructure for bytecode interception used by the configuration cache and API upgrades:

  • instrumentation-agent: Java agent for runtime bytecode transformation.
  • internal-instrumentation-api: Annotations for declaring interceptors (@InterceptCalls, @ReplacesEagerProperty).
  • internal-instrumentation-processor: Annotation processor that generates bytecode interceptors from declarations.

This system enables transparent interception of method calls to track configuration inputs and migrate deprecated APIs without recompiling user code.

Key Services

Core runtime provides essential services to all runtimes:

  • Logging: Structured logging with configurable levels and output formatting.
  • File Operations: File handling, temporary files, and file watching.
  • Classloaders: Custom classloader hierarchies for plugin isolation and bytecode transformation.
  • Concurrent Utilities: Thread pools, synchronization primitives, and concurrent collections.
  • Serialization: Kryo-based serialization for daemon communication and caching.
Loading diagram...

Dependency Management & Resolution

Relevant Files
  • platforms/software/dependency-management/build.gradle.kts
  • platforms/software/dependency-management/src/main/java/org/gradle/internal/management/DefaultDependencyResolutionManagement.java
  • gradle/dependency-management/capabilities.json
  • platforms/software/dependency-management/src/main/java/org/gradle/api/internal/artifacts/ivyservice/resolveengine/graph/builder/DependencyGraphBuilder.java

Gradle's dependency management system handles the complex task of resolving, retrieving, and managing project dependencies. It provides a sophisticated resolution engine that builds a dependency graph, resolves conflicts, and applies metadata rules to ensure consistent and predictable builds.

Core Architecture

The dependency management system is organized around three main responsibilities:

  1. Resolution Engine – Builds and traverses the dependency graph, resolving version conflicts and applying substitution rules
  2. Metadata Resolution – Fetches and processes component metadata from repositories
  3. Configuration Management – Manages repositories, version catalogs, and component metadata rules

The DefaultDependencyResolutionManagement class serves as the central configuration point, managing repositories, component metadata rules, and version catalogs at the settings level.

Dependency Graph Resolution

The resolution process follows a multi-phase approach:

Loading diagram...

The DependencyGraphBuilder traverses the dependency graph starting from the root component. For each dependency edge, it:

  1. Resolves the component identifier using version selectors
  2. Fetches component metadata from repositories
  3. Registers candidates for conflict detection
  4. Processes outgoing dependencies of selected components

Conflict Resolution

Gradle handles two types of conflicts:

Module Conflicts occur when multiple versions of the same module are requested. The ModuleConflictHandler detects these and delegates to a ModuleConflictResolver to select a single version. By default, Gradle selects the highest version.

Capability Conflicts occur when multiple components provide the same capability. The CapabilitiesConflictHandler manages these using capability rules defined in capabilities.json. For example, when both log4j:log4j and org.slf4j:log4j-over-slf4j are in the graph, the system selects the preferred implementation.

Component Metadata Rules

Component metadata rules allow customization of how dependencies are resolved. Rules can:

  • Add or remove transitive dependencies
  • Declare capabilities provided by components
  • Force version upgrades
  • Apply substitutions

Rules are registered in dependencyResolutionManagement blocks and applied during resolution. The ComponentMetadataHandler provides methods like all() and withModule() to target rules to specific components.

Repository and Version Catalog Management

The RepositoriesMode and RulesMode properties control whether repositories and rules are defined at the settings level or project level:

  • PREFER_PROJECT – Projects can define their own repositories and rules
  • PREFER_SETTINGS – Settings repositories and rules take precedence
  • FAIL_ON_PROJECT_REPOS – Project-level repositories cause build failure

Version catalogs provide a centralized way to manage dependency versions and plugin versions across the build, improving consistency and maintainability.

Plugin System & Extensibility

Relevant Files
  • platforms/extensibility/plugin-use/src/main/java/org/gradle/plugin/use/resolve/internal/CorePluginResolver.java
  • platforms/extensibility/plugin-use/src/main/java/org/gradle/plugin/use/internal/DefaultPluginRequestApplicator.java
  • platforms/extensibility/plugin-use/src/main/java/org/gradle/plugin/management/internal/DefaultPluginHandler.java
  • platforms/extensibility/plugin-use/src/main/java/org/gradle/plugin/use/resolve/internal/PluginResolver.java
  • platforms/extensibility/plugin-use/src/main/java/org/gradle/plugin/use/internal/PluginResolverFactory.java

Overview

Gradle's plugin system provides a flexible, extensible architecture for discovering, resolving, and applying plugins to builds. The system supports multiple plugin sources (core plugins, external repositories, TestKit classpath) and uses a chain-of-responsibility pattern to resolve plugin requests in a well-defined order.

Plugin Resolution Chain

Plugins are resolved through a chain of PluginResolver implementations, each handling a specific source. The resolution order is critical for performance and masking:

  1. NoopPluginResolver – Test-only resolver for the noop plugin
  2. CorePluginResolver – Built-in Gradle plugins (e.g., java, application)
  3. DefaultInjectedClasspathPluginResolver – TestKit classpath plugins
  4. Distribution Resolvers – Plugins from included builds
  5. Repository-based Resolvers – Custom plugin repositories
  6. ArtifactRepositoriesPluginResolver – Gradle Plugin Portal (default fallback)

Each resolver returns a PluginResolutionResult indicating success or failure. The CompositePluginResolver iterates through the chain until a plugin is found.

Core Plugin Resolution

The CorePluginResolver handles plugins in the core namespace. It validates that:

  • Core plugins cannot specify a version (they are versioned with Gradle)
  • Core plugins cannot use custom implementation artifacts
  • Core plugins must have apply true (they are already on the classpath)

If validation fails, an InvalidPluginRequestException is thrown with a clear error message.

Plugin Application Flow

The DefaultPluginRequestApplicator orchestrates the complete plugin lifecycle:

// 1. Resolve plugin requests through the resolver chain
PluginResolver pluginResolver = wrapInAlreadyInClasspathResolver(classLoaderScope, resolveContext);
for (PluginRequestInternal request : requests) {
    PluginResolution resolved = resolvePluginRequest(pluginResolver, request);
    // 2. Collect dependencies and classloaders
    resolved.accept(pluginDependencies);
    // 3. Queue apply actions if apply=true
    if (request.isApply()) {
        pluginApplyActions.add(new ApplyAction(request, resolved));
    }
}

// 4. Configure classloader scope with resolved dependencies
classLoaderScope.export(scriptHandler.getInstrumentedScriptClassPath());
pluginDependencies.getAdditionalClassloaders().forEach(classLoaderScope::export);
classLoaderScope.lock();

// 5. Apply plugins to target
pluginApplyActions.forEach(action -> action.apply(target));

Auto-Applied Plugins

The DefaultPluginHandler manages auto-applied plugins through the AutoAppliedPluginRegistry. Before applying auto-applied plugins, it filters out duplicates by checking:

  • Already applied plugins in the PluginContainer
  • Explicitly requested plugins in the plugins block
  • Plugins requested in the buildscript block

This prevents redundant application and allows users to override auto-applied plugins.

Key Abstractions

PluginResolver – Interface for plugin discovery. Implementations return PluginResolutionResult with either a found PluginResolution or a list of NotFound reasons.

PluginResolution – Encapsulates a resolved plugin and its dependencies. Implements the Visitor pattern to collect additional dependencies, module replacements, and classloaders.

PluginRequest – User-facing request for a plugin, including ID, version, and apply flag. The internal PluginRequestInternal adds metadata like origin and script location.

PluginRegistry – Central registry of available plugins, used by core and classpath resolvers to look up plugin implementations.

Error Handling

Plugin resolution and application errors are wrapped in LocationAwareException to provide precise error locations in build scripts. Common errors include:

  • Plugin not found in any resolver
  • Invalid plugin request (e.g., versioning a core plugin)
  • Plugin implementation missing required interface
  • Exception during plugin application

JVM Platform & Language Support

Relevant Files
  • platforms/jvm/platform-jvm/src/main/java/org/gradle/api/plugins/JvmEcosystemPlugin.java
  • platforms/jvm/plugins-java-base/src/main/java/org/gradle/api/plugins/JavaBasePlugin.java
  • platforms/jvm/plugins-java/src/main/java/org/gradle/api/plugins/JavaPlugin.java
  • platforms/jvm/testing-jvm/src/main/java/org/gradle/api/tasks/testing/Test.java
  • platforms/jvm/toolchains-jvm/src/main/java/org/gradle/api/plugins/JvmToolchainsPlugin.java

Overview

The JVM platform in Gradle provides comprehensive support for building Java Virtual Machine projects. It establishes a unified ecosystem for dependency management, language compilation, and testing across multiple JVM languages including Java, Groovy, Scala, and Kotlin.

Core Architecture

The JVM platform is built on a layered plugin hierarchy:

Loading diagram...

JvmEcosystemPlugin (since 6.7) is the foundation, configuring:

  • Attributes Schema: Defines resolution rules for Usage (API vs Runtime), LibraryElements, TargetJvmVersion, Bundling, and Category
  • SourceSetContainer: Manages source directories and compilation units
  • Variant Derivation Strategy: Handles component metadata for dependency resolution

JavaBasePlugin extends JvmEcosystemPlugin with:

  • Compilation defaults for Java source
  • Source set conventions (src/main/java, src/test/java)
  • Javadoc generation
  • Test task configuration
  • Archive defaults (JAR output directory)

JavaPlugin adds:

  • Default test suite via JVM Test Suite plugin
  • Software component registration for publishing
  • Main feature configuration

Language Support

Gradle supports multiple JVM languages through specialized plugins that extend JavaPlugin:

  • Java: Core language via java plugin
  • Groovy: Via groovy plugin (extends JavaPlugin, adds Groovydoc)
  • Scala: Via scala plugin (adds Scaladoc, Zinc compiler integration)
  • Kotlin: Via external Kotlin plugin (community-maintained)

Each language plugin registers custom source directories (e.g., src/main/groovy, src/main/scala) and compilation tasks while reusing the JVM ecosystem infrastructure.

Testing Framework Integration

The Test task supports multiple test frameworks running in isolated JVMs:

test {
  useJUnit()           // JUnit 3.8.x, 4.x
  useTestNG()          // TestNG
  useJUnitPlatform()   // JUnit 5.x (Jupiter, Vintage, custom engines)
}

Test frameworks are pluggable through TestFramework implementations:

  • JUnitTestFramework: Detects and runs JUnit 4 tests
  • JUnitPlatformTestFramework: Runs JUnit Platform engines with filtering by tags/engines
  • TestNGTestFramework: Supports TestNG with suite configuration

Toolchains & JDK Management

JvmToolchainsPlugin provides JavaToolchainService for:

  • Specifying target JDK versions independent of build JVM
  • Automatic JDK discovery and download
  • Configuring compiler and launcher executables
java {
  toolchain {
    languageVersion = JavaLanguageVersion.of(17)
  }
}

Dependency Management

The attributes schema enables intelligent variant selection:

  • Usage: Distinguishes JAVA_API (compile-time) from JAVA_RUNTIME (runtime)
  • LibraryElements: Identifies JAR, classes directory, or resources
  • TargetJvmVersion: Ensures compatibility between consumer and library JVM targets

This allows Gradle to automatically select the correct variant when multiple are available, preventing version conflicts and incompatibilities.

Testing Infrastructure & Frameworks

Relevant Files
  • contributing/Testing.md
  • testing/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractIntegrationSpec.groovy
  • testing/internal-testing/build.gradle.kts
  • testing/internal-integ-testing/build.gradle.kts
  • build-logic/integration-testing/src/main/kotlin/gradlebuild.integration-tests.gradle.kts

Test Framework & Language

Gradle uses Spock as its primary testing framework. Spock is a Groovy-based BDD framework that provides expressive syntax for both unit and integration tests. All tests are written in Groovy and compiled with the Gradle build system.

Test Types

The repository employs multiple test categories:

  1. Unit Tests – Test small, isolated pieces of code with high input variation. Best for complex logic that benefits from mocking.

  2. Integration Tests – Run entire Gradle builds with specific build files and verify external effects (e.g., generated files, build outputs). These are end-to-end tests that exercise real build scenarios.

  3. Cross-Version Tests – Verify compatibility across multiple Gradle versions using the @CrossVersionTest annotation.

  4. Performance Tests – Measure build performance and generate flamegraphs. Located in testing/performance/ and testing/internal-performance-testing/.

  5. Smoke Tests – Quick validation tests for real-world projects (Android, Gradle builds). Found in testing/smoke-test/.

Core Testing Infrastructure

AbstractIntegrationSpec is the base class for integration tests. It provides:

  • GradleExecuter – Executes Gradle builds in various modes (embedded, forking, daemon, parallel, configuration cache, isolated projects)
  • Test Fixtures – Maven/Ivy repositories, temporary directories, build files, and artifact builders
  • Build Operations Tracking – Inspect build operations and configuration cache behavior
  • Problems API Validation – Verify expected problems are reported during builds

Test Fixtures & Helpers

The testing/internal-integ-testing/ module provides extensive fixtures:

  • BuildOperationsFixture – Inspect and query build operations
  • ConfigurationCacheFixture – Test configuration cache behavior
  • DaemonsFixture – Manage Gradle daemon lifecycle
  • MavenFileRepository / IvyFileRepository – Create test repositories
  • BuildTestFixture – Generate single/multi-project builds with DSL support (Groovy/Kotlin)

Best Practices

  • Verify External State – Integration tests should check resulting files and build outputs, not internal state
  • Use Data-Driven Tables – Spock's data tables test multiple scenarios efficiently
  • Avoid Build Script Assertions – Print data to stdout and verify in test code instead
  • Link to Issues – Use @Issue("https://github.com/gradle/gradle/issues/XXXX") to track bug fixes
  • Keep Tests Simple – Avoid over-engineering with deeply-nested helpers; readability matters
  • Reuse Existing Fixtures – Check testing/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/ for helpers

Execution Modes

Integration tests run with different executers controlled by system properties:

  • embedded – In-process execution
  • forking – Separate JVM process
  • noDaemon – No daemon reuse
  • parallel – Parallel task execution
  • configCache – Configuration cache enabled
  • isolatedProjects – Isolated projects mode

Tests can be filtered by executer using Spock annotations like @MultiVersionTest or @CrossVersionTest.

Running Tests

Integration tests are organized by module. Use Gradle's test tasks:

./gradlew integ-test
./gradlew integMultiVersionTest
./gradlew smokeTest
./gradlew performanceTest

Test execution respects timeouts (default 120 seconds) and can be debugged with standard JVM debugging options.

Build Logic & Gradle Plugins

Relevant Files
  • build-logic/uber-plugins/build.gradle.kts
  • build-logic/jvm/build.gradle.kts
  • build-logic-commons/gradle-plugin/src/main/kotlin/gradlebuild.build-logic.kotlin-dsl-gradle-plugin.gradle.kts
  • build-logic/settings.gradle.kts
  • build-logic-commons/settings.gradle.kts

Overview

Gradle's build system is organized into three layered plugin hierarchies: build-logic-commons, build-logic, and the root build. This architecture enables reusable, composable plugins that enforce conventions across the entire project.

Plugin Architecture

The plugin system uses composite builds to organize build logic:

  • build-logic-commons: Foundational plugins shared between build-logic and the root build (basics, module-identity, publishing, code-quality-rules)
  • build-logic: Specialized plugins for subproject configuration (jvm, uber-plugins, packaging, profiling, integration-testing)
  • Root build: Uses plugins from build-logic to configure the main Gradle distribution

Plugins are discovered via pluginManagement blocks in settings.gradle.kts files, which include composite builds and configure repositories.

Plugin Categories

Uber-Plugins (build-logic/uber-plugins) combine multiple plugins for specific project types:

  • gradlebuild.jvm-library — Applies 15+ plugins for JVM libraries (testing, quality, CI reporting, dependency analysis)
  • gradlebuild.java-library — Java-specific conventions
  • gradlebuild.kotlin-library — Kotlin-specific conventions
  • gradlebuild.distribution.* — Distribution packaging variants

JVM Plugins (build-logic/jvm) handle compilation and runtime concerns:

  • gradlebuild.jvm-compile — Creates jvmCompile extension for per-source-set JVM version targeting
  • gradlebuild.strict-compile — Enforces strict compilation flags
  • gradlebuild.unittest-and-compile — Configures test and compile tasks
  • gradlebuild.platform — Manages dependency versions

Plugin Composition Pattern

Plugins are written as Kotlin DSL scripts (.gradle.kts files) and use the kotlin-dsl plugin for type-safe configuration. Each plugin:

  1. Declares dependencies on other plugins via implementation(projects.xxx) or implementation("gradlebuild:xxx")
  2. Applies prerequisite plugins in its plugins block
  3. Configures extensions and tasks for downstream consumers

Example from gradlebuild.jvm-library:

plugins {
    id("java-library")
    id("gradlebuild.module-identity")
    id("gradlebuild.dependency-modules")
    // ... 12 more plugins
}

Plugin Validation & Quality

All build-logic plugins are validated with strict rules:

  • validatePlugins task runs with failOnWarning = true and enableStricterValidation = true
  • Kotlin compiler treats all warnings as errors (allWarningsAsErrors = true)
  • Detekt static analysis enforces code quality
  • Tests use JUnit Platform with strict isolation

Dependency Management

Plugins declare dependencies on:

  • Platform BOM: api(platform("gradlebuild:build-platform")) for version alignment
  • Internal plugins: implementation(projects.jvm) for local plugin composition
  • External libraries: Kotlin Gradle plugin, Develocity, dependency-analysis-gradle-plugin, ASM, Guava, etc.

The build-logic/gradle.properties and root gradle.properties must have identical org.gradle.jvmargs to prevent daemon spawning issues.

Contributing & Development Guide

Relevant Files
  • CONTRIBUTING.md
  • contributing/Testing.md
  • contributing/Debugging.md
  • contributing/ErrorMessages.md
  • contributing/JavadocStyleGuide.md

Getting Started

Before contributing, discuss your changes with the team by opening a GitHub issue. For non-trivial changes, be prepared to answer: Why is this change needed? What's the use case? What will the API look like? What test cases should it have? How will it be implemented?

Development Requirements:

  • Adoptium JDK version 17 (required for remote build cache)
  • IntelliJ IDEA 2021.2.2 or newer (Community or Ultimate)
  • Git and a GitHub account

Setting Up Your Environment

IntelliJ IDEA Import:

  1. Open build.gradle.kts in the project root and select "Open as Project"
  2. Select Adoptium Java 17 VM as the Gradle JVM
  3. Revert Git changes to files in the .idea folder

Important Tips:

  • IntelliJ hides org.gradle stacktrace elements by default. Disable this in Preferences > Editor > General > Console to debug tests more easily.
  • Install the Develocity IntelliJ plugin for real-time build analysis.
  • Do NOT run gradle build locally—the repository is massive. Use targeted testing instead.

Code Contribution Guidelines

Testing Requirements:

  • Write tests using Spock framework
  • Create integration tests that verify external build effects (files, outputs)
  • Avoid testing internal state in integration tests; use unit tests for that
  • Use data-driven tables for testing multiple scenarios
  • Link bug-related tests to GitHub issues with @Issue annotation

Documentation & Code Quality:

  • Add Javadoc for new public types and methods (required for top-level types)
  • Follow the Javadoc Style Guide: use {@code} for keywords, {@link} for references, &lt; and &gt; for angle brackets
  • Add documentation to the User Manual under platforms/documentation/docs/src/docs/
  • Use American English spelling (e.g., "color", not "colour")
  • For error messages, implement the ResolutionProvider interface for custom suggestions

Commits:

  • Write clear, descriptive commit messages following the seven rules
  • Sign off commits with git commit --signoff to agree to the Developer Certificate of Origin
  • Keep commits discrete and self-contained

Testing Your Changes

Run targeted tests:

./gradlew :<subproject>:quickTest

Install and test locally:

./gradlew install -Pgradle_installPath=/any/path
/any/path/bin/gradle taskName

Sanity check before submitting:

./gradlew sanityCheck

Debugging

Unit Tests: Run in debug mode directly in your IDE.

Integration Tests: Start the "Daemon debug" run configuration in IntelliJ, then run the test in debug mode. The debugger automatically connects to the Gradle Daemon.

Other Debugging Options:

  • Set debugDaemon property to debug the daemon
  • Set debugLauncher property to debug the launcher (port 5006)
  • For compiler daemons, add JVM debug args to JavaCompile tasks
  • For worker processes, enable debugging via fork options or switch to classloader isolation

Submitting Your Change

  1. Fork gradle/gradle and create a pull request
  2. Ensure all commits are signed off (required for DCO compliance)
  3. If your PR changes the public API, the binary compatibility check will run. Accept intentional changes in accepted-public-api-changes.json and run ./gradlew :architecture-test:sortAcceptedApiChanges
  4. A Gradle developer will review your PR—multiple iterations are normal
  5. Check CI status at builds.gradle.org (log in as guest for external contributors)

Key Build Features

Configuration Cache: Enabled by default. Disable with --no-configuration-cache if needed.

Remote Build Cache: Anonymous read access available. Use EU (default), US (-DcacheNode=us), or AU (-DcacheNode=au) nodes.

Java Toolchain: Gradle automatically detects and uses available JDKs. Specify a version with -PtestJavaVersion=#.

Building Distributions:

./gradlew :distributions-full:binDistributionZip
./gradlew :distributions-full:allDistributionZip