Gradle 是否执行一个任务,取决于它声明的输入与输出。这篇用真实项目验证:UP-TO-DATE 比较的是内容哈希、下游只看 ABI、没有声明输入输出会怎样、Java 的增量编译与构建缓存到底省下什么。
第一次 gradle build:rc=0,执行 10 个,UP-TO-DATE 4 个,NO-SOURCE 8 个,FROM-CACHE 0 个,共 22 个;耗时 1.0 秒 第二次 gradle build(没有任何改动):rc=0,执行 0 个,UP-TO-DATE 14 个,NO-SOURCE 8 个,FROM-CACHE 0 个,共 22 个;耗时 0.4 秒 第二次中 lib 与 app 的 compileJava / jar / test:lib:compileJava=UP-TO-DATE,lib:jar=UP-TO-DATE,app:compileJava=UP-TO-DATE,app:jar=UP-TO-DATE,app:test=NO-SOURCE --info 里 compileJava 的跳过原因:Skipping task ':lib:compileJava' as it is up-to-date. 只 touch 了 Lib.java(内容不变,修改时间推后):lib:compileJava=UP-TO-DATE,lib:jar=UP-TO-DATE,app:compileJava=UP-TO-DATE;执行 0 个,UP-TO-DATE 14 个,NO-SOURCE 8 个,FROM-CACHE 0 个,共 22 个
(a) 只在 Lib.java 末尾加了一行注释:lib:compileJava=EXECUTED,lib:classes=EXECUTED,lib:jar=UP-TO-DATE,app:compileJava=UP-TO-DATE,app:jar=UP-TO-DATE (b) 改了 private 方法体(x * 2 → x * 3):lib:compileJava=EXECUTED,lib:jar=EXECUTED,app:compileJava=UP-TO-DATE,app:jar=UP-TO-DATE (c) 新增了 public 方法 api2():lib:compileJava=EXECUTED,lib:jar=EXECUTED,app:compileJava=EXECUTED,app:jar=UP-TO-DATE;原因:Input property 'classpath' file <jtmp>/j291a/lib/build/classes/java/main/Lib.class has changed.
genVersion 第一次:EXECUTED;原因:No history is available. genVersion 第二次(没有改动):UP-TO-DATE;原因:(无,被跳过) genVersion -Pver=2:EXECUTED;原因:Value of input property 'ver' has changed for task ':genVersion' genVersion 手工改了输出文件 ver.txt:EXECUTED;原因:Output property '$1' file <jtmp>/j291a/build/ver.txt has changed. genVersion 删除输出文件 ver.txt:EXECUTED;原因:Output property '$1' file <jtmp>/j291a/build/ver.txt has been removed. noOutputs(没有声明输出)第一次 EXECUTED、第二次 EXECUTED;原因:Task has not declared any outputs despite executing actions. undeclaredInput(读了 in.txt 却没声明为输入):第一次 EXECUTED,copy.txt = 'old';把 in.txt 改成 new 之后第二次 UP-TO-DATE,copy.txt = 'old'(in.txt = 'new',产物过期了)
干净后的完整编译:没有增量编译日志(日志:Full recompilation is required because no incremental change information is available);compileJava=EXECUTED (a) C20.f 的方法体改了(签名不变):增量编译 2 个类 (b) C0.f 的签名改成 long f(long):增量编译 4 个类 (c) 常量 C0.K 由 1 改成 2(C5、C9 引用):增量编译 4 个类 (d) 没有再改:compileJava=UP-TO-DATE
缓存开启后第一次 clean build:执行 10 个,UP-TO-DATE 4 个,NO-SOURCE 8 个,FROM-CACHE 0 个,共 22 个;耗时 0.5 秒 clean 之后第二次 build:执行 6 个,UP-TO-DATE 6 个,NO-SOURCE 8 个,FROM-CACHE 2 个,共 22 个;耗时 0.4 秒 第二次的 FROM-CACHE 任务:lib:compileJava,app:compileJava 改了 C20 后 clean build:执行 8 个,UP-TO-DATE 5 个,NO-SOURCE 8 个,FROM-CACHE 1 个,共 22 个;lib:compileJava=EXECUTED(输入变了,缓存键变了),app:compileJava=FROM-CACHE 本地构建缓存里的条目数 5