Appearance
增量构建
增量构建是 Gradle 最重要的性能特性之一:当任务的输入和输出没有变化时,自动跳过执行,显示 UP-TO-DATE。
工作原理
任务执行前检查:
1. 任务是否有 @Input/@Output 注解?
2. 输入文件/属性的哈希值是否与上次一致?
3. 输出文件是否存在且与上次一致?
如果三者都满足 → 跳过执行(UP-TO-DATE)
否则 → 重新执行任务状态
bash
./gradlew build
# 任务状态说明:
# > Task :compileJava ← 执行了(EXECUTED)
# > Task :test UP-TO-DATE ← 跳过,没有变化
# > Task :jar SKIPPED ← 被 -x 跳过或 enabled=false
# > Task :check FROM-CACHE ← 从构建缓存恢复
# > Task :build NO-SOURCE ← 没有源文件,跳过让自定义任务支持增量构建
kotlin
abstract class ProcessFilesTask : DefaultTask() {
@get:InputDirectory
abstract val sourceDir: DirectoryProperty
@get:Input
abstract val encoding: Property<String>
@get:OutputDirectory
abstract val outputDir: DirectoryProperty
@TaskAction
fun process() {
val src = sourceDir.get().asFile
val out = outputDir.get().asFile
val enc = encoding.get()
src.walkTopDown()
.filter { it.isFile && it.extension == "txt" }
.forEach { file ->
val outFile = File(out, file.relativeTo(src).path)
outFile.parentFile.mkdirs()
outFile.writeText(file.readText(charset(enc)).uppercase(), charset(enc))
}
}
}强制重新执行
bash
# 强制重新执行(忽略增量构建)
./gradlew build --rerun-tasks
# 只重新执行某个任务
./gradlew :test --rerun禁用增量构建
kotlin
tasks.named("myTask") {
outputs.upToDateWhen { false } // 每次都执行
}增量任务动作(Incremental Task Action)
对于大量文件的处理,增量任务动作只处理变更的文件:
kotlin
abstract class IncrementalProcessTask : DefaultTask() {
@get:Incremental
@get:InputDirectory
abstract val inputDir: DirectoryProperty
@get:OutputDirectory
abstract val outputDir: DirectoryProperty
@TaskAction
fun process(inputChanges: InputChanges) {
// 只处理变更的文件
inputChanges.getFileChanges(inputDir).forEach { change ->
val outFile = outputDir.file(change.normalizedPath).get().asFile
when (change.changeType) {
ChangeType.ADDED, ChangeType.MODIFIED -> {
outFile.parentFile.mkdirs()
outFile.writeText(change.file.readText().uppercase())
println("处理: ${change.file.name}")
}
ChangeType.REMOVED -> {
outFile.delete()
println("删除: ${change.file.name}")
}
}
}
}
}