Movatterモバイル変換


[0]ホーム

URL:


Previous|Contents|Next

Chapter 15. Build Cache

Table of Contents

15.1. Overview
15.2. Enable the Build Cache
15.3. Task Output Caching
15.4. Configure the Build Cache
15.5. How to set up an HTTP build cache backend
15.6. Implement your own Build Cache

The build cache feature is ready to be used for Java, Groovy and Scala projects. Work continues to make it available in more areas.

The build cache feature described here is different from theAndroid plugin build cache.

15.1. Overview

The Gradlebuild cache is a cache mechanism that aims to save time by reusing outputs produced by other builds.The build cache works by storing (locally or remotely) build outputs and allowing builds to fetch these outputs from the cache when it is determined that inputs have not changed, avoiding the expensive work of regenerating them.

A first feature using the build cache istask output caching.Essentially, task output caching leverages the same intelligence asup-to-date checks that Gradle uses to avoid work when a previous local build has already produced a set of task outputs.But instead of being limited to the previous build in the same workspace, task output caching allows Gradle to reuse task outputs from any earlier build in any location on the local machine.When using a shared build cache for task output caching this even works across developer machines and build agents.

Apart from task output caching, we expect other features to use the build cache in the future.

A complete guide is available aboutusing the build cache. It covers the different scenarios caching can improve, and detailed discussions of the different caveats you need to be aware of when enabling caching for a build.

15.2. Enable the Build Cache

By default, the build cache is not enabled. You can enable the build cache in a couple of ways:

Run with--build-cache on the command-line

Gradle will use the build cache for this build only.

Putorg.gradle.caching=true in yourgradle.properties

Gradle will try to reuse outputs from previous builds for all builds, unless explicitly disabled with--no-build-cache.

When the build cache is enabled, it will store build outputs in the Gradle user home.For configuring this directory or different kinds of build caches seeSection 15.4, “Configure the Build Cache”.

15.3. Task Output Caching

Beyond incremental builds described inSection 19.10, “Up-to-date checks (AKA Incremental Build)”, Gradle can save time by reusing outputs from previous executions of a task by matching inputs to the task.Task outputs can be reused between builds on one computer or even between builds running on different computers via a build cache.

We have focused on the use case where users have an organization-wide remote build cache that is populated regularly by continuous integration builds.Developers and other continuous integration agents should pull cache entries from the remote build cache.We expect that developers will not be allowed to populate the remote build cache, and all continuous integration builds populate the build cache after running theclean task.

For your build to play well with task output caching it must work well with theincremental build feature.For example, when running your build twice in a row all tasks with outputs should beUP-TO-DATE.You cannot expect faster builds or correct builds when enabling task output caching when this prerequisite is not met.

Task output caching is automatically enabled when you enable the build cache, seeSection 15.2, “Enable the Build Cache”.

15.3.1. What does it look like

Let us start with a project using the Java plugin which has a few Java source files. We run the build the first time.

$> gradle --build-cache compileJavaBuild cache is an incubating feature.Using local directory build cache for the root build (location = /home/user/.gradle/caches/build-cache-1).:compileJava:processResources:classes:jar:assembleBUILD SUCCESSFUL

We see the directory used by the local build cache in the output. Apart from that the build was the same as without the build cache.Let’s clean and run the build again.

$> gradle clean:cleanBUILD SUCCESSFUL
$> gradle --build-cache assembleBuild cache is an incubating feature.Using local directory build cache for the root build (location = /home/user/.gradle/caches/build-cache-1).:compileJava FROM-CACHE:processResources:classes:jar:assembleBUILD SUCCESSFUL

Now we see that, instead of executing the:compileJava task, the outputs of the task have been loaded from the build cache.The other tasks have not been loaded from the build cache since they are not cacheable. This is due to:classes and:assemble beinglifecycle tasks and:processResourcesand:jar being Copy-like tasks which are not cacheable since it is generally faster to execute them.

15.3.2. Cacheable tasks

Since a task describes all of its inputs and outputs, Gradle can compute abuild cache key that uniquely defines the task’s outputs based on its inputs.That build cache key is used to request previous outputs from a build cache or push new outputs to the build cache. If the previous build is already populated by someone else, e.g. yourcontinuous integration server or other developers, you can avoid executing most tasks locally.

The following inputs contribute to the build cache key for a task in the same way that they do forup-to-date checks:

  • The task type and its classpath

  • The names of the output properties

  • The names and values of properties annotated as described inthe section called “Custom task types”

  • The names and values of properties added by the DSL viaTaskInputs

  • The classpath of the Gradle distribution, buildSrc and plugins

  • The content of the build script when it affects execution of the task

Task types need to opt-in to task output caching using the@CacheableTask annotation.Note that@CacheableTask is not inherited by subclasses.Custom task types arenot cacheable by default.

Built-in cacheable tasks

Currently, the following built-in Gradle tasks are cacheable:

Caching native compilation

It is also possible to enable caching for the native toolchain.This can be done by setting the system propertyorg.gradle.caching.native totrue.Caching is then enabled forCCompile andCppCompile.

Caching native tasks is experimental.

C/C++ compilers embed absolute paths to sources into object files, so you may not be able to debug object files which have been loaded from the cache.

Non-cacheable tasks

All other tasks are currently not cacheable, but this may change in the future for other languages (Kotlin) or domains (native, Android, Play).Some tasks, likeCopy orJar, usually do not make sense to make cacheable because Gradle is only copying files from one location to another.It also doesn’t make sense to make tasks cacheable that do not produce outputs or have no task actions.

15.3.3. Declaring task inputs and outputs

It is very important that a cacheable task has a complete picture of its inputs and outputs, so that the results from one build can be safely re-used somewhere else.

Missing task inputs can cause incorrect cache hits, where different results are treated as identical because the same cache key is used by both executions.Missing task outputs can cause build failures if Gradle does not completely capture all outputs for a given task.Wrongly declared task inputs can lead to cache misses especially when containing volatile data or absolute paths.(SeeSection 19.10.1, “Task inputs and outputs” on what should be declared as inputs and outputs.)

The task path isnot an input to the build cache key.This means that tasks with different task paths can re-use each other’s outputs as long as Gradle determines that executing them yields the same result.

In order to ensure that the inputs and outputs are properly declared use integration tests (for example using TestKit) to check that a task produces the same outputs for identical inputs and captures all output files for the task.We suggest adding tests to ensure that the task inputs are relocatable, i.e. that the task can be loaded from the cache into a different build directory (see@PathSensitive).

In order to handle volatile inputs for your tasks considerconfiguring input normalization.

15.3.4. Known issues with task output caching

The task output caching feature has known issues that may impact the correctness of your build when using the build cache,and there are some caveats to keep in mind which may reduce the number of cache hits you get between machines.These issues will be corrected as this feature becomes stable.

Note that task output caching relies onincremental build.Problems that affect incremental builds can also affect task output caching even if the affected tasks are not cacheable.Most issues only cause problems if your build cache is populated by non-clean builds or if caching has been enabled for unsupported tasks.For a current list of open problems with incremental builds see theseGithub issues.

Whenreporting issues with the build cache, please check if your issue is a known issue or related to a known issue.

Correctness issues

These issues may affect the correctness of your build when using the build cache. Please consider these issues carefully.

Table 15.1. Correctness issues

DescriptionImpactWorkaround

Tracking the Java vendor implementation

Gradle currently tracks the major version of Java that is used for compilation and test execution. If your build uses several Java implementations (IBM, OpenJDK, Oracle, etc) that are the same major version, Gradle will treat them all as equivalent and re-use outputs from any implementation.

Only enable caching for builds that all use the same Java implementation or manually add the Java vendor as an input to compilation and test execution tasks by usingthe runtime api for adding task inputs.

Tracking the Java version

Gradle currently tracks the major version of Java (6 vs 7 vs 8) that is used for compilation and test execution. If your build expects to use several minor releases (1.8.0_102 vs 1.8.0_25), Gradle will treat all of these as equivalent and re-use outputs from any minor version. In our experience, bytecode produced by each major version is functionally equivalent.

Manually add the full Java version as an input to compilation and test execution tasks by usingthe runtime api for adding task inputs.

Environment variables are not tracked as inputs.

For tasks that fork processes (likeTest), Gradle does not track any of the environment variables visible to the process. This can allow undeclared inputs to affect the outputs of the task.

Declare environment variables as inputs to the task withTaskInputs.property(java.lang.String, java.lang.Object).

Changes in Gradle’s file encoding that affect the build script

Gradle can produce different task output based on the file encoding used by the JVM. Gradle will use a default file encoding based on the operating system iffile.encoding is not explicitly set.

Set the UTF-8 file encoding on all tasks which allow setting the encoding. Use UTF-8 file encoding everywhere by settingfile.encoding toUTF-8 for the Gradle JVM.

Javadoc ignores custom command-line options

Gradle’s Javadoc task does not take into account any changes to custom command-line options.

You can add your custom options as input properties or disable caching of Javadoc.

Caveats

These issues may affect the number of cache hits you get between machines.

Table 15.2. Caveats

DescriptionImpactWorkaround

Overlapping outputs between tasks

If two or more tasks share an output directory or files, Gradle will disable caching for these tasks when it detects an overlap.

Use separate output directories for each task.

Line endings in build scripts files.

Gradle calculates the build cache key based on the MD5 hash of the build script contents. If the line endings are different between developers and the CI servers, Gradle will calculate different build cache keys even when all other inputs to a task are the same.

Check if your VCS will change source file line endings and configure it to have a consistent line ending across all platforms.

Absolute paths in command-line arguments and system properties.

Gradle provides ways of specifying the path sensitivity for individual task properties (see@PathSensitive);however, it is common to need to pass absolute paths to tools or to tests via system properties or command line arguments.These kinds of inputs will cause cache misses because not every developer or CI server uses an identical absolute path to the root of a build.Tasks likeTest include system properties and JVM arguments as inputs to the build cache key.

If possible, use relative paths (viaProject.relativePath(java.lang.Object)). Further tooling will be provided later.

Using JaCoCo disables caching of the Test task.

The JaCoCo agent relies on appending to a shared output file that may be left over from a different test execution. If Gradle allowed Test tasks to be cacheable with the JaCoCo plugin, it could not guarantee the same results each time.

None.

Adding new actions to cacheable tasks in a build file makes that task sensitive to unrelated changes to the build file.

Actions added by a plugin (from buildSrc or externally) do not have this problem because their classloader is restricted to the classpath of the plugin.

Avoid adding actions to cacheable tasks in a build file.

Modifying inputs or outputs during task execution.

It’s possible to modify a task’s inputs or outputs during execution in ways that change the output of a task. This breaks incremental builds and can cause problems with the build cache.

Use a configure task to finalize configuration for a given task. A configure task configures another task as part of its execution.

Order of input files affects outputs.

Some tools are sensitive to the order of its inputs and will produce slightly different output. Gradle will usually provide the order of files from the filesystem, which will be different across operating systems.

Provide a stable order for tools affected by order.

ANTLR3 produces output with a timestamp.

When generating Java source code with ANTLR3 and theChapter 59,The ANTLR Plugin, the generated sources contain a timestamp that reduces how often Java compilation will be cached. ANTLR2 and ANTLR4 are not affected.

If you cannot upgrade to ANLTR4 use a custom template or remove the timestamp in adoLast action.

15.4. Configure the Build Cache

You can configure the build cache by using theSettings.buildCache(org.gradle.api.Action) block insettings.gradle.

Gradle supports alocal and aremote build cache that can be configured separately.When both build caches are enabled, Gradle tries to load build outputs from the local build cache first, and then tries the remote build cache if no build outputs are found.If outputs are found in the remote cache, they are also stored in the local cache, so next time they will be found locally.Gradle pushes build outputs to any build cache that is enabled and hasBuildCache.isPush() set totrue.

By default, the local build cache has push enabled, and the remote build cache has push disabled.

The local build cache is pre-configured to be aDirectoryBuildCache and enabled by default.The remote build cache can be configured by specifying the type of build cache to connect to (BuildCacheConfiguration.remote(java.lang.Class)).

15.4.1. Built-in local build cache

The built-in local build cache,DirectoryBuildCache, uses a directory to store build cache artifacts.By default, this directory resides in the Gradle user home directory, but its location is configurable.

Gradle will periodically clean-up the local cache directory to reduce it to a configurable target size.This means that the local build cache directory may temporarily grow over the target size until the next clean-up is scheduled.

For more details on the configuration options refer to the DSL documentation ofDirectoryBuildCache.Here is an example of the configuration.

Example 15.1. Configure the local cache

settings.gradle

buildCache {    local(DirectoryBuildCache) {        directory =new File(rootDir,'build-cache')        targetSizeInMB =1024    }}

15.4.2. Remote HTTP build cache

Gradle has built-in support for connecting to a remote build cache backend via HTTP.For more details on what the protocol looks like seeHttpBuildCache.Note that by using the following configuration the local build cache will be used for storing build outputs while the local and the remote build cache will be used for retrieving build outputs.

Example 15.2. Pull from HttpBuildCache

settings.gradle

buildCache {    remote(HttpBuildCache) {        url ='https://example.com:8123/cache/'    }}

You can configure the credentials theHttpBuildCache uses to access the build cache server as shown in the following example.

Example 15.3. Configure remote HTTP cache

settings.gradle

buildCache {    remote(HttpBuildCache) {        url ='http://example.com:8123/cache/'        credentials {            username ='build-cache-user'            password ='some-complicated-password'        }    }}

You may encounter problems with an untrusted SSL certificate when you try to use a build cache backend with an HTTPS URL.The ideal solution is for someone to add a valid SSL certificate to the build cache backend, but we recognize that you may not be able to do that.In that case, setHttpBuildCache.isAllowUntrustedServer() totrue:

Example 15.4. Allow untrusted SSL certificate for HttpBuildCache

settings.gradle

buildCache {    remote(HttpBuildCache) {        url ='https://example.com:8123/cache/'        allowUntrustedServer = true    }}

This is a convenient workaround, but you shouldn’t use it as a long-term solution.

15.4.3. Configuration use cases

The recommended use case for the build cache is that your continuous integration server populates the remote build cache with clean builds while developers pullfrom the remote build cache and push to a local build cache. The configuration would then look as follows.

Example 15.5. Recommended setup for CI push use case

settings.gradle

ext.isCiServer = System.getenv().containsKey("CI")buildCache {    local {        enabled = !isCiServer    }    remote(HttpBuildCache) {        url ='https://example.com:8123/cache/'        push = isCiServer    }}

If you use abuildSrc directory, you should make sure that it uses the same build cache configuration as the main build.This can be achieved by applying the same script tobuildSrc/settings.gradle andsettings.gradle as shown in the following example.

Example 15.6. Consistent setup for buildSrc and main build

settings.gradle

apply from:new File(settingsDir,'gradle/buildCacheSettings.gradle')

buildSrc/settings.gradle

apply from:new File(settingsDir,'../gradle/buildCacheSettings.gradle')

gradle/buildCacheSettings.gradle

ext.isCiServer = System.getenv().containsKey("CI")buildCache {    local {        enabled = !isCiServer    }    remote(HttpBuildCache) {        url ='https://example.com:8123/cache/'        push = isCiServer    }}

It is also possible to configure the build cache from aninit script, which can be used from the command line, added to your Gradle user home or be a part of your custom Gradle distribution.

Example 15.7. Init script to configure the build cache

init.gradle

gradle.settingsEvaluated { settings ->    settings.buildCache {// vvv Your custom configuration goes here        remote(HttpBuildCache) {            url ='https://example.com:8123/cache/'        }// ^^^ Your custom configuration goes here    }}

15.5. How to set up an HTTP build cache backend

Gradle provides a Docker image for abuild cache node, which can connect with Gradle Enterprise for centralized management.The cache node can also be used without a Gradle Enterprise installation with restricted functionality.

15.6. Implement your own Build Cache

Using a different build cache backend to store build outputs (which is not covered by the built-in support for connecting to an HTTP backend) requires implementingyour own logic for connecting to your custom build cache backend.To this end, custom build cache types can be registered viaBuildCacheConfiguration.registerBuildCacheService(java.lang.Class, java.lang.Class).For an example of what this could look like see theGradle Hazelcast plugin.

Gradle Enterprise includes a high-performance, easy to install and operate, shared build cache backend.

Previous|Contents|Next

[8]ページ先頭

©2009-2025 Movatter.jp