You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 18:08:09