Gradle自定义Task必须显式声明inputs/outputs才能支持增量构建:未声明时每次均被强制重跑;注解仅在继承DefaultTask的抽象类中有效,不可用于register闭包;输出路径须在@TaskAction中真实创建并写入,否则构建失败。

Gradle自定义Task必须显式声明inputs/outputs才能支持增量构建
不声明输入输出的Task,每次执行都会被Gradle视为“脏任务”,强制重跑——哪怕源文件一个字节都没变。这不是性能问题,是契约缺失:Gradle无法判断你的任务是否真的需要重新执行。
@Input、@InputFile这些注解只能用在自定义Task类里,不能直接写在register闭包中
常见错误是试图在tasks.register("myTask") { ... }里用@Input修饰闭包里的变量,这完全无效。Gradle只识别继承DefaultTask(或其子类)的Kotlin/Java类中带注解的属性。
- 正确姿势:定义一个
abstract class MyProcessTask : DefaultTask(),在类内用@Input、@OutputDirectory等标记属性 - 注册时用
tasks.register<myprocesstask>("processStuff")</myprocesstask> - Groovy用户注意:
class MyTask extends DefaultTask也必须是abstract(Gradle 7.0+ 强制要求),否则增量构建不生效 - 属性必须有getter(Kotlin中用
val或var声明即可;Groovy需确保不是def动态类型)
inputs.dir和outputs.dir是脚本DSL写法,但只适用于简单场景且易踩坑
这种写法出现在build.gradle顶层,比如inputs.dir "src/main/resources",它本质是调用Task的inputs.files()和outputs.files()方法,但缺乏类型安全和编译期检查。
- 适合快速原型或临时任务,不适合长期维护的插件逻辑
- 路径字符串硬编码,重构时容易断;没有IDE自动补全和跳转
- 无法表达“这个目录下只有
.json文件才影响结果”这类细粒度依赖 - 若路径不存在,Gradle默认忽略(不会报错),但可能导致UP-TO-DATE误判
输出路径必须被任务实际写入,否则Gradle会报错“output property not set”
声明了@OutputDirectory却没在@TaskAction里创建该目录或写入文件,Gradle会在执行阶段抛出InvalidUserDataException,提示“output property outputDir has no value”。
- 务必在
@TaskAction开头调用outputDir.mkdirs()(Kotlin)或outputDir.mkdirs()(Groovy) - 如果输出是单个文件,用
@OutputFile并确保outputFile.parentFile.mkdirs()先执行 - 不要依赖其他Task“顺手”创建目录——Gradle不保证执行顺序能覆盖你的隐含假设
doLast{}但忘了outputs声明本身属于配置阶段——这些细节一旦漏掉,增量构建就彻底失效。


















