Gradle Installation, Wrapper, CLI, Settings, Build Scripts, and Project Bootstrap: Concepts, Architecture, and Mental Model
Build a precise Gradle bootstrap mental model before running build logic: which executable starts the build, which JVM runs Gradle, which files define the build, and which directories are disposable state rather than source.
Build a precise Gradle bootstrap mental model before running build logic: which executable starts the build, which JVM runs Gradle, which files define the build, and which directories are disposable state rather than source.
Learning objectives
- Explain why a system Gradle installation is a bootstrap tool while a checked-in Wrapper is the normal project execution contract.
-
Distinguish
settings.gradle(.kts)build structure frombuild.gradle(.kts)project build logic. -
Separate Gradle User Home from project-local
.gradle/state and generatedbuild/outputs. - Describe how the Gradle client JVM, Daemon JVM, and Java toolchains can be related but are not the same configuration.
- Read task/project information before running mutation-heavy tasks.
- Identify the Wrapper scripts, Wrapper JAR, distribution URL, distribution SHA-256, and trust boundaries that must be reviewed before execution.
1. The practical problem: “Gradle works here” does not identify the build engine
A developer can type gradle build and a CI job can type
./gradlew build while both appear to run “Gradle.” They
may actually use different Gradle releases, different runtime JVMs,
different user-home configuration, and different cached
distributions. Those are build inputs, not workstation trivia.
Chapter 14 ended with a Maven migration dossier. Chapter 15 starts the Gradle half of the course by establishing a similarly explicit baseline: which Gradle distribution executes this repository, which JVM hosts it, which source-controlled scripts define it, and which state may safely be discarded.
Production invariant: once a trusted Wrapper
exists, developers and CI should invoke the project Wrapper rather
than relying on whatever gradle happens to be on
PATH.
2. Current baseline: Gradle 9.7.1, runtime JVM 17–26, project target Java 17
For this chapter the concrete, timestamped baseline is Gradle 9.7.1, released August 19, 2026. Gradle 9.7.1 requires a JVM from 17 through 26 to execute Gradle. The lab machine may run Gradle on JDK 21 while the Java project targets Java 17 through toolchain configuration.
| Identity | Chapter pin | Why it matters |
|---|---|---|
| Gradle distribution | 9.7.1 | Defines build-engine behavior and built-in plugins. |
| Gradle runtime JVM | JDK 21 in examples | Hosts the client/daemon; must be supported by Gradle. |
| Project Java target | 17 | Compiler/test target is a separate decision from the runtime JVM. |
| Wrapper distribution SHA-256 | acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a |
Authenticates the downloaded -bin ZIP against
the reviewed expected digest.
|
| Wrapper JAR SHA-256 | 7a9ce74cff467ca1bf60a4fcd9f05185acceda4d0f382434d393e17864262c5d | Lets reviewers verify the executable Wrapper bootstrap JAR. |
The phrase “Java version” is therefore ambiguous. Always ask whether it means the shell/client JVM, daemon JVM, compiler toolchain, or application runtime target.
3. Mental model: source-controlled build contract → executable graph → disposable state
flowchart TD A["gradlew / gradlew.bat"] --> B["gradle-wrapper.jar"] C["gradle-wrapper.properties"] --> B B --> D["Verified Gradle 9.7.1 distribution"] E["JAVA_HOME / daemon criteria"] --> D F["settings.gradle.kts"] --> G["Build structure"] H["build.gradle.kts"] --> I["Project model and tasks"] D --> G D --> I G --> J["Selected task graph"] I --> J J --> K["build/ outputs"] D --> L["GRADLE_USER_HOME caches / daemon / wrapper dists"] D --> M["project .gradle state"]
The Wrapper scripts start the bootstrap JAR. The properties file
tells that bootstrapper which distribution to provision and, when
configured, which SHA-256 it must match. Gradle then evaluates
settings to establish build structure and build scripts to configure
projects/tasks. Execution writes generated outputs under
build/ and performance state under project/user-home
caches. No arrow says “the cache is the build definition”: caches
are accelerators, not authority.
4. Four state stores beginners must not collapse into one “Gradle folder”
| State store | Examples | Authority / lifecycle |
|---|---|---|
| Repository build definition |
settings.gradle.kts,
build.gradle.kts,
gradle.properties, Wrapper files
|
Reviewed source-controlled inputs. |
| Gradle User Home |
caches/, daemon/,
wrapper/dists/, init.d/
|
User/agent state; may inject global behavior and is a trust boundary. |
| Project-local Gradle state | .gradle/ |
Transient project state for incremental/configuration features; not source truth. |
| Build outputs |
build/classes, build/libs,
build/test-results
|
Generated evidence/artifacts; reproduce from controlled inputs. |
5. Settings script and build script answer different questions
The settings script is evaluated during initialization and describes the build: root name, included projects, plugin-management/repository-management boundaries, and other build-wide setup. The build script configures a Project: plugins, dependencies, tasks, Java toolchains, testing, packaging, and related behavior.
// settings.gradle.kts
rootProject.name = "wrapper-lab"
// build.gradle.kts
plugins {
application
}
java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}
application {
mainClass = "dev.academy.bootstrap.App"
}
Single-project builds can operate without an explicit settings file, but keeping one makes the build identity deliberate. Multi-project builds require settings to declare the project structure; deeper project modeling arrives later in the Gradle chapters.
6. Wrapper files are executable supply-chain inputs
The Wrapper consists of gradlew,
gradlew.bat,
gradle/wrapper/gradle-wrapper.jar, and
gradle/wrapper/gradle-wrapper.properties. The JAR
executes before your normal build logic and may download a Gradle
distribution, so a Wrapper change deserves the same review
discipline as other executable build dependencies.
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-9.7.1-bin.zip
distributionSha256Sum=acd53f1edaf02f1a8ff99879f8a34b302661a057d9b063ae9e35b552f804d20a
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
The distribution checksum verifies the downloaded ZIP. It does
not verify that a malicious reviewer-replaced
gradle-wrapper.jar is genuine; verify the Wrapper JAR
separately against Gradle’s published Wrapper-JAR checksum.
7. CLI mental model: global options + task paths + task options
Gradle commands select tasks from a task graph.
./gradlew tasks is a read-oriented discovery command;
./gradlew build executes the lifecycle tasks
contributed by the applied plugins. Options such as
--version, --status,
--no-daemon, and --console=plain change
invocation behavior or output rather than becoming tasks.
# POSIX — read identity and model before mutation
./gradlew --version
./gradlew -q projects
./gradlew tasks --all
./gradlew help --task build
Task paths become important in multi-project builds:
:app:test names a task in project :app,
while plain test may match tasks relative to the
current build context. This chapter stays with one project so the
bootstrap model remains small.
8. The client JVM, Daemon JVM, and toolchain can intentionally differ
Gradle starts a client JVM when the Wrapper script launches. Normally it connects to or starts a compatible Gradle Daemon, which hosts the build engine. Daemon selection considers Gradle version, Java home/version, and JVM arguments. A Java toolchain configured in the build can then select another JDK for compilation or testing.
Diagnostic consequence: seeing
java -version is not enough. Capture
./gradlew --version and, when daemon behavior matters,
inspect daemon status/logs or daemon JVM criteria as well.
9. Read-only inspection before bootstrap changes
# POSIX
java -version
gradle --version 2>/dev/null || echo "No system Gradle on PATH"
# Only after Wrapper files have been reviewed/verified:
./gradlew --version
./gradlew -q projects
./gradlew tasks --all
./gradlew --status
The first two commands describe the workstation. The Wrapper command
describes the repository contract. projects proves the
settings-derived structure, tasks proves available task
names, and --status observes compatible daemons. None
of them proves that a build is trustworthy; they establish evidence
before changes.
10. DevOps connection: bootstrap identity is part of CI provenance
A CI job that runs a globally installed Gradle can silently change behavior when the runner image changes. A verified Wrapper moves the Gradle version into reviewable repository state. Pair it with an explicit runtime JDK and controlled Gradle User Home/cache policy, and CI can explain which engine produced an artifact.
This does not mean “commit every Gradle-generated file.” Commit the
Wrapper and build definitions; treat .gradle/ and
build/ as generated state. Cache restore may improve
speed, but a cache hit is never proof of artifact provenance by
itself.
Knowledge check
Why is gradle build a weaker reproducibility
contract than ./gradlew build?
The system command resolves whatever Gradle is installed on PATH. The Wrapper selects the version declared by the repository and can verify the downloaded distribution checksum.
Does distributionSha256Sum authenticate
gradle-wrapper.jar?
No. It verifies the downloaded Gradle distribution ZIP. The Wrapper JAR is a separate executable input and should be checked against Gradle’s published Wrapper-JAR checksum.
A build runs Gradle on JDK 21 and compiles with Java 17. Is that contradictory?
No. The Gradle runtime JVM and Java compiler/toolchain target are separate identities.
Where would a global init script normally live?
Under Gradle User Home, for example
$GRADLE_USER_HOME/init.d/. That is why Gradle User
Home is a configuration and trust boundary, not merely a
dependency cache.
Should build/ or project .gradle/ be
treated as source-controlled build definitions?
No. They are generated output/state. Reproducibility should come from declared inputs, the verified Wrapper, compatible JVM/toolchains, dependencies/plugins, and controlled environment state.
11. Bridge to the guided workflow
You now have the map. Lesson 2 will create a disposable Java
project, use a trusted system Gradle only for initial bootstrap,
immediately pin and verify the Wrapper, then switch every normal
operation to ./gradlew/gradlew.bat.
Official references and version notes
- Gradle 9.7.1 Release Notes — 9.7.1 is the August 19, 2026 patch release recommended over 9.7.0.
- Gradle Wrapper — Wrapper files, generation, distribution URL, checksum verification, and upgrade behavior.
- Gradle distribution and Wrapper JAR checksums — official SHA-256 reference.
- Compatibility Matrix — Gradle 9.7.1 runtime JVM support.
- Build Init Plugin — supported project types and non-interactive init options.
-
Gradle-managed Directories and Caches
— Gradle User Home, project
.gradle, build outputs, daemon logs, and dependency caches. - Gradle Daemon — client JVM, daemon JVM, status, logs, and daemon JVM criteria.
- Settings File Basics and Build File Basics.
Version snapshot: These lessons were generated for August 24, 2026 with Gradle 9.7.1 as the pinned lab release. Re-check the official release and compatibility pages before copying version-specific pins into a future production repository.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.