Gradle 6.7.1强制任务执行顺序及Copy任务异常问题解析
mustRunAfter 不生效的根本原因 你对mustRunAfter的作用存在误解:它只负责排序,不负责触发任务执行。
- 只有
dependsOn这类依赖声明,才会把关联的任务加入本次构建的执行队列,同时保证依赖任务先执行。 mustRunAfter、shouldRunAfter都属于纯排序规则:只有当两个任务同时被纳入本次执行计划时,才会强制约束先后顺序,不会主动把关联任务拉进来跑。
你执行命令时只指定了createProject作为入口任务,copyProjectTemplate根本没进执行队列,排序规则自然不会生效。如果执行命令改成gradle -b create_project.gradle createProject copyProjectTemplate,两个任务都在执行队列里,你配置的顺序规则就会正常工作,保证copyProjectTemplate先执行。
如果你的需求是“执行createProject时必须先跑copyProjectTemplate”,直接用dependsOn替代mustRunAfter即可。
这是Gradle内置增量构建机制的正常表现:
Gradle所有内置的标准任务(Copy、Jar、Zip、Delete等)都默认实现了增量检查逻辑:任务执行前会扫描自身声明的所有输入、输出,如果判定没有需要处理的内容,就会直接标记为UP-TO-DATE跳过执行,任务绑定的doFirst、doLast动作都不会触发。
对Copy任务来说,它的合法输入是from声明的源文件集合,输出是into声明的目标路径。如果你没有配置任何from规则,输入集合为空,Gradle会判定这个任务没有实际工作要做,直接跳过。
而你自定义的无类型普通任务,默认没有实现增量检查逻辑,只要被加入执行队列就一定会跑,不管你有没有写实际业务逻辑,所以你写的打印语句每次都会触发。
如果你确实需要让没有配置复制规则的Copy任务强制执行,可以手动关闭它的增量检查:
task copyTemplate(type: Copy) { outputs.upToDateWhen { false } // 禁用up-to-date检查,每次强制执行 doLast { println 'copyTemplate' } }
不过更合理的实践是:不要把和文件复制无关的自定义逻辑绑定到Copy这类内置增量任务上,单独定义普通任务承载自定义逻辑,再通过依赖或者排序规则关联任务执行顺序即可。
内容的提问来源于stack exchange,提问作者Itération 122442

