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

如何将Gradle子项目的source set输出合并到其他子项目Jar中?

问题场景与优化方案

项目结构

三个子项目均使用java-library插件,根项目仅通过allprojects块设置group和version信息:

Root project 'project'
+--- Project ':project-a'
+--- Project ':project-b'
+--- Project ':project-c'

依赖关系

  • project-a无依赖
  • project-c通过api(project(":project-a"))依赖project-a
  • project-b通过api(project(":project-c"))依赖project-c(间接依赖project-a)

需求

  • 构建project-c时,生成的Jar需包含project(":project-a").sourceSets["main"].output的所有类
  • 构建project-b时,生成的Jar需包含project(":project-a").sourceSets["main"].output和project(":project-c").sourceSets["main"].output的所有类

已尝试方案

在根项目build.gradle.kts中添加:

project(":project-c").evaluationDependsOn(":project-a")
project(":project-b").evaluationDependsOn(":project-c")

并分别在project-c和project-b的build.gradle.kts中配置:

// project-c/build.gradle.kts
tasks.jar { from(project(":project-a").sourceSets["main"].output) }
// project-b/build.gradle.kts
tasks.jar { 
   from(project(":project-a").sourceSets["main"].output) 
   from(project(":project-c").sourceSets["main"].output) 
}

该方案可行但不够优雅,希望通过Gradle配置实现更优方案。

补充: 经查阅资料,若懒加载配置jar任务,无需调用evaluationDependsOn。


更优解决方案

方案1:懒加载配置Jar任务(消除evaluationDependsOn)

利用Gradle的懒加载特性,通过provider延迟解析依赖项目的sourceSets,无需手动指定项目评估顺序,代码更简洁且符合Gradle最佳实践:

project-c/build.gradle.kts 配置:

tasks.jar {
    // 懒加载获取project-a的main输出,任务执行阶段才解析
    from(provider { project(":project-a").sourceSets.main.get().output })
}

project-b/build.gradle.kts 配置:

tasks.jar {
    from(provider { project(":project-a").sourceSets.main.get().output })
    from(provider { project(":project-c").sourceSets.main.get().output })
}

方案2:使用Shadow插件(规范的Fat Jar构建)

如果需要更灵活的打包控制(比如重复类处理、资源合并),可以使用官方推荐的com.github.johnrengelman.shadow插件,它是Gradle生态中成熟的Fat Jar构建工具:

  1. 根项目引入插件:
plugins {
    id("com.github.johnrengelman.shadow") version "8.1.1" apply false
}
  1. project-c/build.gradle.kts 配置:
plugins {
    id("java-library")
    id("com.github.johnrengelman.shadow")
}

shadowJar {
    from(project(":project-a").sourceSets.main.get().output)
    classifier = "" // 去掉默认的"-all"后缀,替代默认jar输出
}

// 让build任务自动触发shadowJar
tasks.build {
    dependsOn(tasks.shadowJar)
}
  1. project-b/build.gradle.kts 配置:
plugins {
    id("java-library")
    id("com.github.johnrengelman.shadow")
}

shadowJar {
    from(project(":project-a").sourceSets.main.get().output)
    from(project(":project-c").sourceSets.main.get().output)
    classifier = ""
}

tasks.build {
    dependsOn(tasks.shadowJar)
}

方案3:自定义配置管理嵌入项目

如果不想依赖第三方插件,可通过自定义配置统一管理需要嵌入的项目,后续维护更便捷:

project-c/build.gradle.kts 配置:

// 定义自定义配置,用于管理需要嵌入的项目
val embeddedProjects by configurations.creating {
    isCanBeConsumed = false
    isCanBeResolved = false
}

dependencies {
    embeddedProjects(project(":project-a"))
}

tasks.jar {
    // 遍历配置中的项目,获取其main输出
    from(embeddedProjects.map { project(it.name).sourceSets.main.get().output })
}

project-b/build.gradle.kts 配置:

val embeddedProjects by configurations.creating {
    isCanBeConsumed = false
    isCanBeResolved = false
}

dependencies {
    embeddedProjects(project(":project-a"))
    embeddedProjects(project(":project-c"))
}

tasks.jar {
    from(embeddedProjects.map { project(it.name).sourceSets.main.get().output })
}

内容的提问来源于stack exchange,提问作者Alex R

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 22:45:39