如何使Gradle任务:birds:generateStringResources始终优先执行?
问题场景
我在项目级build.gradle中添加了以下代码,想要让:birds:generateStringResources任务在任何其他任务之前执行:
tasks.all { Task t -> if (t != ':birds:generateStringResources') { println("Adding dependsOn(':birds:generateStringResources') to: $t") t.dependsOn(':birds:generateStringResources') } }
运行./gradlew trees时,配置阶段的输出显示已经给多个任务添加了依赖:
Configure project :
Adding dependsOn(':birds:generateStringResources') to: task ':build'
Adding dependsOn(':birds:generateStringResources') to: task ':assemble'
Adding dependsOn(':birds:generateStringResources') to: task ':buildDependents'
Adding dependsOn(':birds:generateStringResources') to: task ':buildEnvironment'
etc...
但实际执行时,第一个运行的任务却是:trees:preBuild,而非预期的:birds:generateStringResources:
Task :trees:preBuild UP-TO-DATE // <-- 我希望
:birds:generateStringResources在此之前运行
Task :trees:preArm64DebugBuild UP-TO-DATE
Task :trees:mergeArm64DebugNativeDebugMetadata NO-SOURCE
Task :dogs:preBuild UP-TO-DATE
etc...
只有运行./gradlew tasks --all时,:birds:generateStringResources才会作为第一个任务执行:
Task :birds:generateStringResources // 执行成功,这是第一个任务
Task :tasks
后续构建依赖该任务生成的字符串资源,需要实现:无论执行./gradlew后传入什么任务名,:birds:generateStringResources都始终在所有任务之前执行。
解决方案
方法1:监听所有任务创建并添加依赖
原代码的问题在于tasks.all只能捕获配置阶段已经存在的任务,而像模块preBuild这类任务是在子项目配置阶段才动态创建的,不会被原代码覆盖。
改用tasks.whenTaskAdded监听所有任务的创建事件,确保所有任务都添加依赖:
// 项目级build.gradle def generateTask = tasks.getByPath(':birds:generateStringResources') allprojects { tasks.whenTaskAdded { t -> if (t != generateTask) { t.dependsOn(generateTask) } } }
如果是Android项目,更精准的方式是只让所有preBuild任务依赖它(因为Android构建流程中preBuild是大部分任务的前置):
// 项目级build.gradle def generateTask = tasks.getByPath(':birds:generateStringResources') allprojects { tasks.whenTaskAdded { t -> if (t.name == 'preBuild' && t != generateTask) { t.dependsOn(generateTask) } } }
方法2:通过任务图强制调整执行顺序
利用Gradle的任务图API,在任务图构建完成后,确保目标任务被加入执行队列,并且所有任务都在它之后运行:
// 项目级build.gradle def generateTask = tasks.getByPath(':birds:generateStringResources') gradle.taskGraph.whenReady { graph -> // 如果任务图中没有目标任务,主动添加 if (!graph.hasTask(generateTask)) { graph.addTasks([generateTask]) } // 让所有其他任务必须在目标任务之后执行 graph.allTasks.each { t -> if (t != generateTask) { t.mustRunAfter(generateTask) } } }
注意事项
- 务必避免给
:birds:generateStringResources本身添加依赖,否则会触发循环依赖错误 - 全局依赖可能会影响构建性能,若能明确哪些任务需要用到生成的资源,优先给这些任务单独设置依赖
- 如果
:birds模块是其他模块的依赖,也可以在:birds模块的build.gradle中让generateStringResources成为preBuild的依赖,这样依赖该模块的项目会自动触发它
内容的提问来源于stack exchange,提问作者h.and.h

