Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some more content to architecture documentation #29017

Merged
merged 3 commits into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Your code needs to run on [all versions of Java that Gradle supports](platforms/
* Be careful when using features introduced in Java 1.7 or later. Some parts of Gradle still need to run on Java 6.
* Normalize file paths in tests. The `org.gradle.util.internal.TextUtil` class has some useful functions for this purpose.

You can consult the [Architecture Decision Records](architecture-standards) to learn about some of the architectural decisions the team took.
You can consult the [Architecture documentation](architecture) to learn about some of the architecture of Gradle.

### Contributing to documentation

Expand Down
72 changes: 27 additions & 45 deletions architecture/README.md
Original file line number Diff line number Diff line change
@@ -1,60 +1,42 @@
<!--
-- Note: this file contains a generated diagram. Use `./gradlew :architectureDoc` to generate
-->
# Gradle architecture documentation

# Gradle platform architecture
This directory contains documentation that describes Gradle's architecture and how the various pieces fit together and work.

The diagram below shows the main components of the Gradle architecture. See [ADR4](standards/0004-use-a-platform-architecture.md) for more details.
## Architecture decision records (ADRs)

<!-- This diagram is generated. Use `./gradlew :architectureDoc` to update it -->
```mermaid
graph TD
The Gradle team uses ADRs to record architectural decisions that the team has made.

subgraph core["core platform"]
See [Architecture decisions records](standards) for the list of ADRs.
Be aware these are very technical descriptions of the decisions, and you might find the documentation below more useful as an introduction to the internals of Gradle.

core_runtime["core-runtime module"]
style core_runtime stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;
## Platform architecture

core_configuration["core-configuration module"]
style core_configuration stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;
Gradle is arranged into several coarse-grained components called "platforms".
Each platform provides support for some kind of automation, such as building JVM software or building Gradle plugins.
Most platforms typically build on the features of other platforms.

core_execution["core-execution module"]
style core_execution stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;
end
style core fill:#c2e0f4,stroke:#3498db,stroke-width:2px,color:#000;
By understanding the Gradle platforms and their relationships, you can get a feel for where in the Gradle source a particular feature might be implemented.

documentation["documentation module"]
style documentation stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;
See [Gradle platform architecture](platforms.md) for a list of the platforms and more details.

ide["ide module"]
style ide stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;
## Gradle runtimes

subgraph software["software platform"]
end
style software fill:#c2e0f4,stroke:#3498db,stroke-width:2px,color:#000;
software --> core
Gradle is also made up of several different processes that work together to "run the build", such as the Gradle daemon and the `gradlew` command.

subgraph jvm["jvm platform"]
end
style jvm fill:#c2e0f4,stroke:#3498db,stroke-width:2px,color:#000;
jvm --> core
jvm --> software
Each process, or "runtime", applies different constraints to the code that runs in that process.
For example, each process has different supported JVMs and a different set of services available for dependency injection.
While a lot of Gradle source code runs only in the Gradle daemon, not all of it does and so, when working on some source code it is important to be aware of the runtimes in which it will run.

subgraph extensibility["extensibility platform"]
end
style extensibility fill:#c2e0f4,stroke:#3498db,stroke-width:2px,color:#000;
extensibility --> core
extensibility --> jvm
See [Gradle runtimes](runtimes.md) for a list of these runtimes and more details.

subgraph native["native platform"]
end
style native fill:#c2e0f4,stroke:#3498db,stroke-width:2px,color:#000;
native --> core
native --> software
## Build state model

enterprise["enterprise module"]
style enterprise stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;
As Gradle executes, it acts on various pieces of the build definition, such as each project in the build.
Gradle tracks the state of each piece and transitions each piece through its lifecycle as the build runs.

build_infrastructure["build-infrastructure module"]
style build_infrastructure stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;
```
A central part of the Gradle architecture is the "build state model", which holds the state for each piece and coordinates state transitions and other mutations.
Most source code in Gradle is arranged by which part(s) of the build state model it acts on.
This affects the lifecycle of the code and the set of services available for dependency injection.
When working on some source code it is important to be aware of the model it acts on.

See [build state model](build-state-model.md) for more details.
87 changes: 87 additions & 0 deletions architecture/build-state-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Build state model

The Gradle daemon tracks state for various elements. These are arranged in a hierarchy:

```mermaid
graph TD

process["build process"]

session["build session"]
process --> session

build_tree["build tree"]
session --> build_tree

build1["root build"]
build_tree --> build1

project1["root project"]
build1 --> project1

project2["project"]
build1 --> project2

build2["included build"]
build_tree --> build2

project3["root project"]
build2 --> project3

project4["project"]
build2 --> project4

```

### Build process state

The "build process state" holds the global state of the build process and manages all the other state.

The build process state also includes state that is tied to a particular Gradle user home directory.
When that directory changes between Gradle invocations, the state is discarded and recreated.
Typically, the Gradle user home directory does not change for a given process, so this is effectively process state.

The build process state is created once for a given process.

### Build session state

A "build session" represents a single invocation of Gradle, for example when you run `gradlew build`.
A session runs the build one or more times.
For example, when continuous build is enabled, the session may run the build many times, but when it is disabled, the session will run the build once only.

The build session state is managed by the `BuildSessionState` class.
An instance is created at the start of a Gradle invocation and discarded at the end of that invocation.

The build session state also includes "cross session" state that is shared with any "nested" sessions that need to be created.
This only happens when the `GradleBuild` task is used. You can mostly ignore the distinction between "cross session" and "build session" state.

### Build tree state

"Build tree" is another name for the build definition.
The "build tree state" holds the state for the entire build definition for a single build execution within a session.

The build tree state is managed by the `BuildTreeState` class.
An instance is created at the start of a build execution and discarded at the end of the execution.

### Build state

The "build state" holds the state for a build within the build definition for a single build execution, and is contained by the build tree state.

The build state is managed by the `BuildState` class.
An instance is created for each build in the build definition, once per build execution and is discarded at the end of the execution.

The build state also includes what is currently called the "Gradle state". The Gradle state is being merged into the build state and is mostly empty.

### Project state

The "project state" holds the state for a project for a single build execution, and is contained by the build state (and not the state of the parent project).

The project state is managed by the `ProjectState` class.
It is created for each project in the build definition, once per build execution and is discarded at the end of the execution.

## Composition by architecture modules

Each [architecture module and platform](platforms.md) can contribute code to any of the elements.
Not every module contributes to every element.

A module does this by providing an implementation of `PluginServiceRegistry` that registers the services that the module contributes to each element.
133 changes: 133 additions & 0 deletions architecture/platforms.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
<!--
-- Note: this file contains a generated diagram. Use `./gradlew :architectureDoc` to generate
-->

# Gradle platform architecture

Gradle is arranged into coarse-grained components called "architecture modules" and "platforms".
See [ADR4](standards/0004-use-a-platform-architecture.md) for a definition of these terms.

The diagram below shows the current set of architecture modules and platforms:

<!-- This diagram is generated. Use `./gradlew :architectureDoc` to update it -->
```mermaid
graph TD

subgraph core["core platform"]

core_runtime["core-runtime module"]
style core_runtime stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;

core_configuration["core-configuration module"]
style core_configuration stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;

core_execution["core-execution module"]
style core_execution stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;
end
style core fill:#c2e0f4,stroke:#3498db,stroke-width:2px,color:#000;

documentation["documentation module"]
style documentation stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;

ide["ide module"]
style ide stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;

subgraph software["software platform"]
end
style software fill:#c2e0f4,stroke:#3498db,stroke-width:2px,color:#000;
software --> core

subgraph jvm["jvm platform"]
end
style jvm fill:#c2e0f4,stroke:#3498db,stroke-width:2px,color:#000;
jvm --> core
jvm --> software

subgraph extensibility["extensibility platform"]
end
style extensibility fill:#c2e0f4,stroke:#3498db,stroke-width:2px,color:#000;
extensibility --> core
extensibility --> jvm

subgraph native["native platform"]
end
style native fill:#c2e0f4,stroke:#3498db,stroke-width:2px,color:#000;
native --> core
native --> software

enterprise["enterprise module"]
style enterprise stroke:#1abc9c,fill:#b1f4e7,stroke-width:2px,color:#000;
```

## Platforms

### Core automation platform

This is a general-purpose automation platform which takes care of the efficient definition and execution of work, such as tasks.
This platform is agnostic to what exactly the purpose of the work is.
It might be creating an application, setting up development environments, orchestrating deployments, running simulations, etc.

This platform does not provide special support for a particular kind of automation. This is the responsibility of other platforms.

It is made up of 3 architecture modules:

- **core-runtime**: Provides the runtimes or "containers" in which code runs. These runtimes include the Gradle client, the daemon and the worker processes. This is the base module on which all other architecture modules depend.
- **core-configuration**: Allows the build structure and work, such as tasks, to be specified. This includes the project model, the DSL and so on.
- **core-execution**: Runs the work efficiently. This includes scheduling, execution, caching and so on.

### Software development platform

This is a general purpose platform that builds on the core automation platform to add support for the automation of software development.
This includes work such as compiling, testing and documenting software, plus sharing that software via publishing and dependency management.
This platform is agnostic to what kind of software is being developed.
It might be Java or Kotlin libraries running on the JVM, Gradle plugins, Android or iOS applications, C++ libraries, and so on.

This platform does not provide special support for a particular language or ecosystem.

### JVM platform

This is a platform that builds on the core and software platforms to add support for developing software that runs on the JVM.
This includes software that is implemented using Java, Kotlin or some other JVM language.

This platform provides specific support for Java, Groovy and Scala, and includes the foojay toolchain plugin.

### Extensibility platform

This is a platform that builds on the core, software and JVM platforms to add support for extending Gradle by implementing and applying plugins.

This platform includes the plugin publishing plugin and the plugin portal.

### Native platform

This is a platform that builds on the core and software platforms to add support for developing native software.

This platform provides specific support for Swift, C++ and C.

## Cross-cutting architecture modules

There are some additional cross-cutting architecture modules that aren't platforms:

### Enterprise integration

Provides cross-cutting integration with Gradle's commercial product.

### IDE integration

Provides cross-cutting integration with IDEs and other tooling.

### Build infrastructure

Provides build logic, libraries, test suites and infrastructure to support developing and releasing Gradle.

### Documentation

Provides cross-cutting Gradle documentation and samples, along with the infrastructure to write, test, publish and host the documentation.

## Structure

Each platform and module has its own source directory under [platforms/](../platforms).
In these source directories, you will find the Gradle projects that make up the platform or module.

The platforms and modules are defined using a DSL in [settings.gradle.kts](../settings.gradle.kts)

Each platform and module can contribute code to the [Gradle runtimes](runtimes.md) and [Build state model](build-state-model.md).
56 changes: 56 additions & 0 deletions architecture/runtimes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Gradle runtimes

Gradle is made up of the following processes that work together to "run the build":

- Gradle daemon. This is the process that actually runs the build. It hosts build logic and coordinates the lifecycle of the build. It is a long-running daemon process.
- CLI client. This is the `gradle` or `gradlew` command, and is responsible for locating, starting and interacting with the Gradle daemon, potentially downloading the Gradle distribution.
- Tooling API client. This a library that is embedded into applications, such as IDEs or CI agents, that allows them to act as a Gradle client.
- Worker processes. Long-running daemon processes that the Gradle daemon starts to run specific kinds of work, such as compilation or test execution.

The diagram below shows the relationships between the different processes:

```mermaid
graph LR

gradle["Gradle CLI client"]

gradlew["Gradlew CLI client"]

subgraph IDE
tapi["Tooling API client"]
end

daemon["Gradle daemon"]
gradle --> daemon
gradlew --> daemon
tapi --> daemon

worker["Worker process"]
daemon --> worker

worker2["Worker process"]
daemon --> worker2

worker3["Worker process"]
daemon --> worker3

```

These are all Java processes. Each process has a corresponding "runtime".
All source code in Gradle is written to target one or more of these runtimes.
Most source code targets the daemon and the remaining code either targets a single runtime, for example the Gradle client, or is shared across multiple runtimes.

## Composition by architecture modules

Each [architecture module and platform](platforms.md) can contribute code to any of the runtimes.
Not every module contributes to every runtime.

The core-runtime module defines each runtime:

- The target JVM for the runtime. Each runtime has its own JVM compatibility constraints.
- Some base services that are available to code hosted by the runtime. This varies by runtime.
- Additional constraints. For example, the CLI client runtimes limit the libraries that are available to the code in that runtime, for performance reasons.

Other modules and platforms define the services that they contribute to the runtime.

The build script for each project declares which runtime the project targets.