Gradle多项目构建中如何在配置阶段完成后获取所有应用Java插件的子项目
Gradle多项目构建中如何在配置阶段完成后获取所有应用Java插件的子项目
嗨,我来帮你搞定这个问题~
你遇到的情况确实是Gradle配置阶段的执行顺序导致的:当你在约定插件或者子项目D的任务配置块里去查找带Java插件的子项目时,那些还没轮到配置的子项目(比如E、F)还没完成Java插件的应用,所以自然被过滤掉了。要解决这个问题,核心思路就是把获取子项目列表的逻辑延迟到所有项目都完成配置阶段之后,这里有两个实用的方案:
方案一:利用全局回调gradle.projectsEvaluated
这个回调会在所有项目的配置阶段都执行完毕后触发,此时所有子项目的插件都已经应用好了,你可以在这里安全地收集所有带Java插件的子项目,再把这个集合关联到你的CopySpec里。
修改约定插件里的代码如下:
ext.copyInst = copySpec {} // 所有项目配置完成后再填充copyInst的逻辑 gradle.projectsEvaluated { def projectGroups = rootProject.subprojects.findAll { it.pluginManager.hasPlugin('java') } copyInst.with { // 这里写你需要用projectGroups实现的逻辑,比如收集输出目录 from projectGroups.collect { it.sourceSets.main.output } // 其他CopySpec配置... } }
之后子项目D里的Copy任务就可以直接沿用原来的写法,因为copyInst里的逻辑会在所有项目配置好之后才生效:
tasks.register('copy', Copy) { into "" with copyInst // 其他任务配置... }
方案二:在Copy任务中延迟求值
如果你的需求只是在单个Copy任务里用到这个子项目列表,那可以把获取列表的逻辑延迟到执行阶段(执行阶段是在所有配置阶段之后的),比如用doFirst闭包或者provider来延迟计算:
方式1:用doFirst在执行前获取列表
tasks.register('copy', Copy) { into "" // 任务执行前才去获取所有带Java插件的子项目 doFirst { def projectGroups = rootProject.subprojects.findAll { it.pluginManager.hasPlugin('java') } // 动态添加源或者其他操作 from projectGroups.collect { it.sourceSets.main.output } } // 其他任务配置... }
方式2:用provider实现延迟关联
如果需要在配置阶段就关联资源,但延迟到执行阶段才求值,provider是更优雅的选择:
tasks.register('copy', Copy) { into "" // provider会在执行阶段才去计算里面的逻辑 from provider { rootProject.subprojects.findAll { it.pluginManager.hasPlugin('java') }.collect { it.sourceSets.main.output } } // 其他任务配置... }
小提醒
尽量避免在配置阶段做跨项目的插件状态检查,除非你能确保所有相关项目都已经完成配置。用上面的延迟求值或者全局回调的方式,能有效避免这种“漏子项目”的问题,同时也符合Gradle的构建生命周期最佳实践。
备注:内容来源于stack exchange,提问作者AndreasInfo
相关产品推荐
相关产品推荐

