Gradle复合构建中主项目未等待includedBuild的editJar任务完成
Gradle变体解析与复合构建任务依赖问题解决方案
问题根源解析
这是Gradle变体解析的预期行为:
- 当你添加
AttributeCompatibilityRule将jar和edited-jar标记为兼容后,Gradle的变体选择逻辑会认为jar变体已满足消费方对edited-jar的需求。 - 由于
jar任务的依赖链更短(不需要执行editJar),Gradle会优先选择这个“更廉价”的变体,从而跳过editJar任务的执行。 - 移除兼容性规则后,消费方严格要求
edited-jar变体,但部分库未定义该变体,自然会导致编译失败。
同时复合构建中任务顺序异常的原因:
- 原
editJar任务直接覆盖jar的输出文件,导致Gradle无法正确跟踪两个变体的产物依赖,mainProj可能在editJar执行前就读取了未编辑的jar文件。 - 未将
releaseBuild属性传递到includedBuild,导致library中的editJar任务未触发执行。
分步解决方案
1. 添加变体消歧规则,优先选择edited-jar
保留兼容性规则(用于无edited-jar变体时回退),同时添加AttributeDisambiguationRule强制Gradle优先选择edited-jar变体:
// mainProj/build.gradle abstract class EditedJarsDisambiguationRule implements AttributeDisambiguationRule<LibraryElements> { @Override void execute(DisambiguationDetails<LibraryElements> details) { // 当存在edited-jar变体时,优先选择它 if (details.candidate.name == 'edited-jar') { details.select() } } } dependencies { attributesSchema { attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE) { compatibilityRules.add(EditedJarsRule) // 添加消歧规则 disambiguationRules.add(EditedJarsDisambiguationRule) } } implementation 'org.libs:library' }
2. 隔离editJar任务的输出,避免覆盖原jar
修改library中的editJar任务,输出到独立文件,确保jar和edited-jar变体的产物分离:
// library/build.gradle task editJar { dependsOn jar onlyIf { project.hasProperty('releaseBuild') } // 生成独立的编辑后jar文件,不覆盖原jar def editedJarName = "edited-${jar.archiveFileName.get()}" outputs.file file("${jar.destinationDirectory.get()}/${editedJarName}") doLast { def originalJar = jar.archiveFile.get().asFile def editedJar = outputs.files.singleFile // 先复制原jar到目标文件,再执行编辑逻辑 copy { from originalJar into editedJar.parent rename { editedJarName } } // 在这里执行你的jar编辑操作 // ... } } // 移除compileJava.finalizedBy editJar,由变体配置自动触发任务
3. 传递构建属性到复合构建的子项目
在settings.gradle中配置,确保releaseBuild属性传递给includedBuild:
// settings.gradle rootProject.name = 'mainProj' includedBuild('library') { def releaseProp = gradle.startParameter.projectProperties['releaseBuild'] if (releaseProp != null) { projectProperties['releaseBuild'] = releaseProp } }
4. 验证变体选择与任务依赖
执行以下命令验证变体选择是否正确:
./gradlew -PreleaseBuild=true dependencyInsights --configuration compileClasspath --dependency org.libs:library
确认输出中显示选择的是edited-jar变体,且任务依赖包含library:editJar。
关键注意事项
- 变体属性与任务绑定:确保
editableJar配置的builtBy(editJar)正确设置,这样Gradle会自动在消费该变体时触发editJar任务。 - 避免产物覆盖:永远不要让自定义任务覆盖Gradle默认任务的输出,否则会破坏变体的独立性和任务依赖跟踪。
- 复合构建属性传递:默认情况下,Gradle不会将命令行属性传递给includedBuild,必须显式配置。
内容的提问来源于stack exchange,提问作者PentaKon
相关产品推荐
相关产品推荐

