应用Java插件后复合构建中Gradle无法找到Zip构件问题
当你给testA应用Java插件后,Gradle的构件解析逻辑发生了关键变化:
Java插件会自动为项目注册一个Java软件组件,并将它设为项目的默认组件。在使用includeBuild依赖本地项目时,Gradle默认会优先解析项目的默认组件所提供的构件,而不是直接读取default配置下的所有构件。
你之前通过artifacts.add('default', zipTask)把Zip构件加到了default配置,但这个构件并没有关联到Java插件创建的默认Java组件上。此时Java组件只包含它自动生成的Jar构件,所以当testB中用org.test:testA:0.0.0.+@zip请求Zip类型的构件时,Gradle在默认Java组件里找不到匹配的构件,就会抛出找不到testA.zip的错误。
从你提供的诊断输出也能佐证这一点:应用Java插件后,default配置里确实有两个构件,但Gradle在解析依赖时只认默认组件的输出。
下面提供几种可行的解决办法,你可以根据自己的需求选择:
方法1:将Zip构件关联到Java组件
在testA的build.gradle中,把自定义的Zip构件添加到Java组件的输出变体里,这样Gradle解析默认组件时就能找到它:
plugins { id 'base' id 'java' } group = 'org.test' version = '0.0.0.1_test' task zipTask(type: Zip) { from './settings.gradle' } artifacts.add('default', zipTask) // 将Zip构件添加到Java组件的变体中 components.java { addVariantsFromConfiguration(configurations.default) { // 保留Zip构件的扩展名,让Gradle能正确匹配@zip的请求 mapToOptional() } }
这样修改后,Java组件会包含Jar和Zip两个构件,testB的原有依赖写法myConfiguration 'org.test:testA:0.0.0.+@zip'就能正常找到Zip构件了。
方法2:在testB中直接依赖testA的default配置
如果不想修改testA的配置,可以在testB的依赖中跳过组件解析,直接指定依赖testA的default配置,然后过滤出Zip构件:
dependencies { myConfiguration project(path: ':testA', configuration: 'default') } task doubleZipTask(type: Zip) { // 只从依赖中选取扩展名是zip的构件 from configurations.myConfiguration.filter { it.name.endsWith('.zip') } }
这种方式直接读取testAdefault配置下的所有构件,再通过过滤拿到需要的Zip,也能解决问题。
方法3:为Zip构件创建单独的配置和变体
如果希望把Zip构件和Java的Jar构件区分开,可以在testA中创建一个专门的配置来托管Zip构件,然后在testB中依赖这个配置:
testA的build.gradle修改:
plugins { id 'base' id 'java' } group = 'org.test' version = '0.0.0.1_test' task zipTask(type: Zip) { from './settings.gradle' } // 创建专门的配置用于Zip构件 configurations { zipArtifact } artifacts.add('zipArtifact', zipTask) // 注册一个自定义组件,关联这个配置(可选,让依赖更规范) components.add('zipComponent', AdhocComponentWithVariants) { addVariantsFromConfiguration(configurations.zipArtifact) { } }
testB的build.gradle修改:
dependencies { // 直接依赖testA的zipArtifact配置 myConfiguration project(path: ':testA', configuration: 'zipArtifact') }
这种方式更清晰,适合构件类型较多的场景,避免不同类型构件互相干扰。
内容的提问来源于stack exchange,提问作者Piotr Siupa

