如何解决Gradle中cobertura插件与其他插件的clean任务冲突?
问题场景
在多模块Gradle项目的根项目中应用net.saliman.cobertura插件时,由于该插件会依赖LifecycleBasePlugin并自动注册clean任务,但项目中已存在其他无法移除的插件也创建了同名的clean任务,执行gradle cobertura命令时会触发任务重名错误:
- What went wrong:
A problem occurred evaluating root project 'root-project'.Failed to apply plugin [id 'cobertura']
Failed to apply plugin [class 'org.gradle.language.base.plugins.LifecycleBasePlugin']
Cannot add task ':clean' as a task with that name already exists.
解决方案
方案1:提前拦截重复任务创建
在应用cobertura插件前,先检查clean任务是否已存在,若存在则跳过base插件(LifecycleBasePlugin是base插件的核心部分)的自动任务注册,再加载cobertura插件:
// 检查根项目是否已有clean任务,不存在才应用base插件 if (!tasks.findByPath(':clean')) { apply plugin: 'base' } // 应用cobertura插件 apply plugin: 'net.saliman.cobertura'
方案2:重新绑定cobertura任务依赖
如果不想调整插件加载顺序,可以直接修改cobertura任务的依赖关系,让它关联到已有的clean任务,同时处理可能的冗余任务:
// 先应用cobertura插件 apply plugin: 'net.saliman.cobertura' // 覆盖cobertura任务的依赖,指向已存在的clean任务 tasks.cobertura.dependsOn tasks.clean // 移除插件可能创建的重复clean任务实例 gradle.projectsEvaluated { def allCleanTasks = tasks.withType(Delete).findAll { it.name == 'clean' } if (allCleanTasks.size() > 1) { allCleanTasks.drop(1).each { tasks.remove(it) } } }
方案3:限定cobertura在子模块生效
如果根项目的clean任务冲突无法避免,可以不在根项目直接应用cobertura插件,而是在需要代码覆盖率的子模块中单独配置,根项目仅统一管理插件版本:
// 根项目build.gradle plugins { id 'net.saliman.cobertura' version '4.0.0' apply false } // 子模块build.gradle plugins { id 'net.saliman.cobertura' }
这种方式下,子模块的clean任务不会与根项目的clean任务冲突,同时根项目可以通过gradle cobertura触发所有子模块的覆盖率任务。
内容的提问来源于stack exchange,提问作者Nicolas Baumann

