Gradle Copy任务在clean时意外执行,如何仅让其在build/run时运行?
问题分析与解决
一、Gradle dependsOn 工作机制
- 核心作用:定义任务间的依赖执行顺序。若任务
A.dependsOn(B),执行A时,Gradle 会先将B纳入执行图,完成B后再执行A。依赖是单向的,仅主动配置的依赖关系会生效,默认不存在反向依赖。 - Gradle 两个关键阶段:
- 配置阶段:Gradle 解析所有模块的构建脚本,注册并配置所有任务。你原代码中直接写在
copyAssets配置块里的println、路径定义等代码,都会在这个阶段执行——无论任务最终是否会被执行。 - 执行阶段:Gradle 根据你指定的目标任务构建执行图,仅执行执行图内任务的实际动作(比如 Copy 任务的复制操作、
doFirst/doLast块内的代码)。
- 配置阶段:Gradle 解析所有模块的构建脚本,注册并配置所有任务。你原代码中直接写在
二、你的问题根源
你观察到的「copyAssets 在 clean 时运行」,大概率是配置阶段的 println 输出造成的误解,而非复制动作真的被执行。默认情况下,clean 任务与 build/run 任务无依赖关系,执行 main:clean 时,copyAssets 不会被纳入执行图,真正的复制操作不会触发。你可以验证:执行 clean 后检查 build/assets 目录,若未创建,说明任务未执行,只是配置阶段代码跑了。
三、解决方案:让 copyAssets 仅在 build/run 时执行
修改代码区分配置与执行阶段
将执行时才需要的逻辑(比如打印日志)移到 doFirst 块,避免配置阶段输出混淆判断,同时保留原有的依赖配置:
tasks.register("copyAssets", Copy) { def fromDir = "${project.projectDir}/../assets" def toDir = "${project.buildDir}/assets" // 仅在任务执行时才打印日志 doFirst { println "Copying assets" println " from $fromDir" println " into $toDir" } from fromDir into toDir } // 保持 build 和 run 依赖 copyAssets build.dependsOn copyAssets run.dependsOn copyAssets
修改后效果:
- 执行
main:build或main:run时,copyAssets会被纳入执行图,先完成复制动作,同时输出日志。 - 执行
main:clean时,仅会完成copyAssets的基础配置(不执行复制和日志打印),因为clean未依赖copyAssets,该任务不在执行图内。
极端情况的额外保障
如果你的项目存在特殊配置导致 clean 间接依赖了 build/run,可以给 copyAssets 添加执行条件,限制仅在目标任务触发时才运行:
copyAssets.onlyIf { gradle.startParameter.taskNames.any { taskName -> taskName.contains(":build") || taskName.contains(":run") } }
内容的提问来源于stack exchange,提问作者digory doo
相关产品推荐
相关产品推荐

