此功能默认未启用

支持的插件

配置缓存对插件实现提出了新的要求。因此,核心 Gradle 插件和社区插件都需要进行调整,以确保兼容性。

本节提供有关当前支持的详细信息

核心 Gradle 插件

大多数核心 Gradle 插件目前都支持配置缓存

JVM 语言和框架

原生语言

打包与分发

 代码分析

 IDE 项目文件生成

实用工具

支持的插件

部分支持的插件(任务总是禁用配置缓存)

⚠*

部分支持的插件(某些功能可能会禁用配置缓存)

社区插件

请参阅问题 gradle/gradle#13490,了解社区插件的状态。

两个最流行的生态系统插件已受支持

  • Android Gradle 插件

  • Kotlin Gradle 插件

尚未实现

目前尚未提供某些 Gradle 功能的配置缓存支持。这些功能将在未来的 Gradle 版本中支持。

共享配置缓存

配置缓存目前只在本地存储。它可以被热和冷的本地 Gradle 守护进程重用,但不能在开发人员或 CI 机器之间共享。

请参阅 gradle/gradle#13510

源依赖项

尚未实现对源依赖项的支持。使用此功能时,构建不会失败,也不会报告任何问题,但配置缓存将自动禁用。

请参阅 gradle/gradle#13506

使用 TestKit 运行构建时使用 Java Agent

当使用TestKit运行构建时,配置缓存可能会干扰应用于这些构建的 Java Agent,例如 Jacoco agent。

请参阅 gradle/gradle#25979

细粒度跟踪 Gradle 属性作为构建配置输入

目前,所有 Gradle 属性的外部源——例如 gradle.properties 文件(在项目目录和 GRADLE_USER_HOME 中)、环境变量、设置属性的系统属性以及通过命令行标志指定的属性——都被视为构建配置输入,无论它们是否实际在配置期间使用。

但是,这些源不包含在配置缓存报告中。

请参阅 gradle/gradle#20969

Java 对象序列化

Gradle 允许支持 Java 对象序列化 协议的对象存储在配置缓存中。

目前的实现仅限于实现了 java.io.Externalizable 接口或实现了 java.io.Serializable 接口并定义了以下方法组合之一的可序列化类:

  • 一个 writeObject 方法与一个 readObject 方法结合,以精确控制要存储的信息;

  • 一个 writeObject 方法,没有相应的 readObjectwriteObject 最终必须调用 ObjectOutputStream.defaultWriteObject

  • 一个 readObject 方法,没有相应的 writeObjectreadObject 最终必须调用 ObjectInputStream.defaultReadObject

  • 一个 writeReplace 方法,允许类指定一个替代对象来写入;

  • 一个 readResolve 方法,允许类指定一个替代对象来读取;

以下 Java 对象序列化功能受支持:

  • serialPersistentFields 成员用于显式声明哪些字段是可序列化的;如果存在,该成员将被忽略;配置缓存认为除 transient 字段外的所有字段都是可序列化的;

  • ObjectOutputStream 的以下方法不受支持,并将抛出 UnsupportedOperationException

    • reset()writeFields()putFields()writeChars(String)writeBytes(String)writeUnshared(Any?)

  • ObjectInputStream 的以下方法不受支持,并将抛出 UnsupportedOperationException

    • readLine()readFully(ByteArray)readFully(ByteArray, Int, Int)readUnshared()readFields()transferTo(OutputStream)readAllBytes()

  • 通过 ObjectInputStream.registerValidation 注册的验证将被简单地忽略;

  • readObjectNoData 方法(如果存在)永不被调用;

请参阅 gradle/gradle#13588

在执行时访问构建脚本的顶层方法和变量

在构建脚本中重用逻辑和数据的常见方法是将重复部分提取到顶层方法和变量中。但是,如果启用了配置缓存,目前不支持在执行时调用此类方法。

对于用 Groovy 编写的构建脚本,任务会失败,因为找不到该方法。以下代码片段在 listFiles 任务中使用了顶层方法:

build.gradle
def dir = file('data')

def listFiles(File dir) {
    dir.listFiles({ file -> file.isFile() } as FileFilter).name.sort()
}

tasks.register('listFiles') {
    doLast {
        println listFiles(dir)
    }
}

启用配置缓存运行任务会产生以下错误:

Execution failed for task ':listFiles'.
> Could not find method listFiles() for arguments [/home/user/gradle/samples/data] on task ':listFiles' of type org.gradle.api.DefaultTask.

为了防止任务失败,请将被引用的顶层方法转换为类中的静态方法:

build.gradle
def dir = file('data')

class Files {
    static def listFiles(File dir) {
        dir.listFiles({ file -> file.isFile() } as FileFilter).name.sort()
    }
}

tasks.register('listFilesFixed') {
    doLast {
        println Files.listFiles(dir)
    }
}

用 Kotlin 编写的构建脚本根本不能在执行时将引用顶层方法或变量的任务存储在配置缓存中。存在此限制是因为捕获的脚本对象引用无法序列化。第一次运行 Kotlin 版本的 listFiles 任务时,会因配置缓存问题而失败。

build.gradle.kts
val dir = file("data")

fun listFiles(dir: File): List<String> =
    dir.listFiles { file: File -> file.isFile }.map { it.name }.sorted()

tasks.register("listFiles") {
    doLast {
        println(listFiles(dir))
    }
}

为了使此任务的 Kotlin 版本与配置缓存兼容,请进行以下更改:

build.gradle.kts
object Files { (1)
    fun listFiles(dir: File): List<String> =
        dir.listFiles { file: File -> file.isFile }.map { it.name }.sorted()
}

tasks.register("listFilesFixed") {
    val dir = file("data") (2)
    doLast {
        println(Files.listFiles(dir))
    }
}
1 在对象中定义方法。
2 在较小的作用域中定义变量。

请参阅 gradle/gradle#22879

使用构建服务使配置缓存失效

目前,如果 ValueSource 的值在配置时被访问,则无法将 BuildService 的提供者或从其派生的提供者(通过 mapflatMap)作为 ValueSource 的参数使用。当此类 ValueSource 在作为配置阶段一部分执行的任务中获取时,例如 buildSrc 构建的任务或包含的贡献插件的构建,也适用同样的情况。

请注意,使用 @ServiceReference 或将 BuildService 存储在任务的 @Internal 注释属性中是安全的。

一般来说,此限制使得无法使用 BuildService 使配置缓存失效。

请参阅 gradle/gradle#24085

使用任意提供者作为构建事件监听器

构建事件监听器注册方法 BuildEventsListenerRegistry.onTaskCompletion 接受任何 OperationCompletionListener 实现的任意提供者。然而,当使用配置缓存时,目前仅支持从 BuildServiceRegistry.registerIfAbsentBuildServiceRegistration.getService 返回的提供者。从 Gradle 9 开始,使用其他类型的提供者(包括 registerIfAbsent(…​).map { it })会导致发出配置缓存问题。在此之前,此类提供者会被静默忽略。

查阅采用指南,了解如何暂时抑制这些问题(如果被丢弃的监听器不影响您的构建)。

请参阅 gradle/gradle#33772