Overview
Relevant Files
README.mdCONTRIBUTING.mdarchitecture/README.mdbuild.gradle.ktssettings.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:
- Requirements: Adoptium JDK 17, IntelliJ IDEA CE (2021.2.2+), Git
- Setup: Fork and clone
gradle/gradle, configure Git credentials - Development: Import
build.gradle.ktsinto IntelliJ as a project - Testing: Run
./gradlew :<subproject>:quickTestfor targeted tests - Local Install: Use
./gradlew install -Pgradle_installPath=/pathto test changes
Community & Support
- Documentation: Gradle User Manual
- Forum: Gradle Community Forum
- Slack: Gradle Community Slack
- Learning: DPE University Free Courses
Architecture & Platform Design
Relevant Files
architecture/platforms.mdarchitecture/build-execution-model.mdarchitecture/build-state-model.mdarchitecture/runtimes.mdsettings.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
gradleorgradlewcommand; 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:
- Client locates or starts an idle daemon
- Client sends a work request to the daemon
- Daemon validates it can accept the request; rejects if busy or shutting down
- Daemon executes the request, streaming back logs and events
- Daemon returns the result
- 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.mdplatforms/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.ktssubprojects/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
ServiceRegistryandServiceLookupinterfaces for read-only service access. - service-provider: Provides
ServiceRegistrationProviderfor declarative service registration using@Providesannotations. - service-registry-impl: Implements
DefaultServiceRegistrywith support for hierarchical registries, service decoration, and lifecycle management. - service-registry-builder: Offers
ServiceRegistryBuilderfor 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.ktsplatforms/software/dependency-management/src/main/java/org/gradle/internal/management/DefaultDependencyResolutionManagement.javagradle/dependency-management/capabilities.jsonplatforms/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:
- Resolution Engine – Builds and traverses the dependency graph, resolving version conflicts and applying substitution rules
- Metadata Resolution – Fetches and processes component metadata from repositories
- 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:
- Resolves the component identifier using version selectors
- Fetches component metadata from repositories
- Registers candidates for conflict detection
- 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 rulesPREFER_SETTINGS– Settings repositories and rules take precedenceFAIL_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.javaplatforms/extensibility/plugin-use/src/main/java/org/gradle/plugin/use/internal/DefaultPluginRequestApplicator.javaplatforms/extensibility/plugin-use/src/main/java/org/gradle/plugin/management/internal/DefaultPluginHandler.javaplatforms/extensibility/plugin-use/src/main/java/org/gradle/plugin/use/resolve/internal/PluginResolver.javaplatforms/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:
- NoopPluginResolver – Test-only resolver for the
noopplugin - CorePluginResolver – Built-in Gradle plugins (e.g.,
java,application) - DefaultInjectedClasspathPluginResolver – TestKit classpath plugins
- Distribution Resolvers – Plugins from included builds
- Repository-based Resolvers – Custom plugin repositories
- 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
pluginsblock - Plugins requested in the
buildscriptblock
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.javaplatforms/jvm/plugins-java-base/src/main/java/org/gradle/api/plugins/JavaBasePlugin.javaplatforms/jvm/plugins-java/src/main/java/org/gradle/api/plugins/JavaPlugin.javaplatforms/jvm/testing-jvm/src/main/java/org/gradle/api/tasks/testing/Test.javaplatforms/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, andCategory - 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
javaplugin - Groovy: Via
groovyplugin (extends JavaPlugin, adds Groovydoc) - Scala: Via
scalaplugin (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) fromJAVA_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.mdtesting/internal-integ-testing/src/main/groovy/org/gradle/integtests/fixtures/AbstractIntegrationSpec.groovytesting/internal-testing/build.gradle.ktstesting/internal-integ-testing/build.gradle.ktsbuild-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:
-
Unit Tests – Test small, isolated pieces of code with high input variation. Best for complex logic that benefits from mocking.
-
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.
-
Cross-Version Tests – Verify compatibility across multiple Gradle versions using the
@CrossVersionTestannotation. -
Performance Tests – Measure build performance and generate flamegraphs. Located in
testing/performance/andtesting/internal-performance-testing/. -
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 executionforking– Separate JVM processnoDaemon– No daemon reuseparallel– Parallel task executionconfigCache– Configuration cache enabledisolatedProjects– 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.ktsbuild-logic/jvm/build.gradle.ktsbuild-logic-commons/gradle-plugin/src/main/kotlin/gradlebuild.build-logic.kotlin-dsl-gradle-plugin.gradle.ktsbuild-logic/settings.gradle.ktsbuild-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 conventionsgradlebuild.kotlin-library— Kotlin-specific conventionsgradlebuild.distribution.*— Distribution packaging variants
JVM Plugins (build-logic/jvm) handle compilation and runtime concerns:
gradlebuild.jvm-compile— CreatesjvmCompileextension for per-source-set JVM version targetinggradlebuild.strict-compile— Enforces strict compilation flagsgradlebuild.unittest-and-compile— Configures test and compile tasksgradlebuild.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:
- Declares dependencies on other plugins via
implementation(projects.xxx)orimplementation("gradlebuild:xxx") - Applies prerequisite plugins in its
pluginsblock - 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:
validatePluginstask runs withfailOnWarning = trueandenableStricterValidation = 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.mdcontributing/Testing.mdcontributing/Debugging.mdcontributing/ErrorMessages.mdcontributing/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:
- Open
build.gradle.ktsin the project root and select "Open as Project" - Select Adoptium Java 17 VM as the Gradle JVM
- Revert Git changes to files in the
.ideafolder
Important Tips:
- IntelliJ hides
org.gradlestacktrace 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 buildlocally—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
@Issueannotation
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,<and>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
ResolutionProviderinterface for custom suggestions
Commits:
- Write clear, descriptive commit messages following the seven rules
- Sign off commits with
git commit --signoffto 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
debugDaemonproperty to debug the daemon - Set
debugLauncherproperty to debug the launcher (port 5006) - For compiler daemons, add JVM debug args to
JavaCompiletasks - For worker processes, enable debugging via fork options or switch to classloader isolation
Submitting Your Change
- Fork gradle/gradle and create a pull request
- Ensure all commits are signed off (required for DCO compliance)
- If your PR changes the public API, the binary compatibility check will run. Accept intentional changes in
accepted-public-api-changes.jsonand run./gradlew :architecture-test:sortAcceptedApiChanges - A Gradle developer will review your PR—multiple iterations are normal
- 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