Gradle多模块自定义源集问题:依赖模块编译类路径缺失类
问题:Gradle多模块构建中Scala 2.13变体依赖缺失编译类
项目背景
我正在参与OpenLineage Spark集成项目,基于Java开发,使用Gradle 8.4构建,包含app、shared、spark2至spark35等多模块。
需求
为Apache Spark的Scala 2.12和2.13变体构建shared模块,spark2至spark35模块均依赖shared。目标是让spark35等模块编译出适配两个Scala版本的产物,同时shared模块需对应Spark变体构建以避免运行时错误。
实施方式
在spark33、spark34、spark35及shared模块中,通过Java Library插件引入scala213和testScala213源集,复用main和test的源码。默认依赖配置适配Scala 2.12,为Scala 2.13源集额外声明依赖,包括对shared模块的依赖。
遇到的问题
当从shared项目引入scala213RuntimeElements(或scala213ApiElements)配置时,依赖模块的编译类路径中缺少shared模块的编译类;但使用默认配置时,这些类存在于类路径中。
疑问
- 为何指定
scala213RuntimeElements配置会导致shared模块的编译类在其他模块的编译类路径中缺失? - 如何解决该问题,确保shared模块的类在Scala 2.12和2.13构建的类路径中均被包含?
相关build.gradle文件
shared/build.gradle
sourceSets { scala213 { java.srcDir("src/main/java") resources.srcDir("src/main/resources") } testScala213 { compileClasspath += sourceSets.scala213.output runtimeClasspath += sourceSets.scala213.output java.srcDir("src/test/java") resources.srcDir("src/test/resources") } } configurations { scala213Api scala213ApiElements { extendsFrom(scala213Api) canBeResolved = false canBeConsumed = true } scala213Implementation.extendsFrom(scala213Api) scala213RuntimeElements { extendsFrom(scala213Implementation, scala213RuntimeOnly) canBeResolved = false canBeConsumed = true } scala213CompileClasspath { extendsFrom(scala213CompileOnly, scala213Implementation) canBeResolved = true } scala213RuntimeClasspath { extendsFrom(scala213Implementation, scala213RuntimeOnly) canBeResolved = true } testScala213Implementation.extendsFrom(scala213Implementation) testScala213RuntimeOnly.extendsFrom(scala213RuntimeOnly) testScala213CompileClasspath { extendsFrom(testScala213CompileOnly, testScala213Implementation) canBeResolved = true } testScala213RuntimeClasspath { extendsFrom(testScala213Implementation, testScala213RuntimeOnly) canBeResolved = true } }
spark33/build.gradle
sourceSets { scala213 { java.srcDir("src/main/java") resources.srcDir("src/main/resources") } testScala213 { compileClasspath += sourceSets.scala213.output runtimeClasspath += sourceSets.scala213.output java.srcDir("src/test/java") resources.srcDir("src/test/resources") } } dependencies { implementation(project(path: ":shared")) // others removed for brevity scala213Implementation(project(path: ":shared", configuration: "scala213RuntimeElements")) // others removed for brevity }
问题原因
- 配置角色不匹配:
scala213RuntimeElements是Gradle专为运行时依赖传递设计的消费端配置,仅包含运行时所需的类和依赖,默认不包含编译期可见的API类。你在scala213Implementation(编译期依赖配置)中引用它,自然会缺失编译类。 - 未关联源集输出:shared模块的
scala213ApiElements和scala213RuntimeElements仅设置了依赖继承,但未绑定scala213源集的编译输出。Gradle的消费端配置必须明确声明要输出的产物,否则依赖模块无法解析到对应的类文件。
解决方法
步骤1:在shared模块中绑定源集输出到消费端配置
修改shared/build.gradle的configurations块,为消费端配置添加源集输出:
configurations { scala213Api scala213ApiElements { extendsFrom(scala213Api) canBeResolved = false canBeConsumed = true // 关联scala213源集的编译类文件 outgoing.artifact(sourceSets.scala213.output) } scala213Implementation.extendsFrom(scala213Api) scala213RuntimeElements { extendsFrom(scala213Implementation, scala213RuntimeOnly) canBeResolved = false canBeConsumed = true // 关联scala213源集的编译类和资源文件 outgoing.artifact(sourceSets.scala213.output) outgoing.artifact(sourceSets.scala213.resources) } // 其余配置保持不变 }
步骤2:在依赖模块中使用匹配的配置
修改spark33/build.gradle的依赖声明,区分编译期和运行时依赖:
dependencies { implementation(project(path: ":shared")) // others removed for brevity // 编译期依赖shared的Scala 2.13 API类 scala213Implementation(project(path: ":shared", configuration: "scala213ApiElements")) // 运行时依赖shared的Scala 2.13完整产物 scala213RuntimeOnly(project(path: ":shared", configuration: "scala213RuntimeElements")) // others removed for brevity }
步骤3:规范测试源集类路径配置
在shared和spark模块的testScala213源集中,用Gradle标准方式关联类路径:
testScala213 { compileClasspath = sourceSets.scala213.compileClasspath + sourceSets.scala213.output runtimeClasspath = sourceSets.scala213.runtimeClasspath + sourceSets.scala213.output // 其余配置不变 }
关键说明
- 消费端配置(
canBeConsumed = true)必须明确绑定源集输出,否则依赖模块无法获取编译后的类。 - 编译期依赖用
ApiElements类型配置,运行时依赖用RuntimeElements,保证依赖传递的正确性。 - 复用源集源码的方式可行,但需确保每个变体的配置都正确关联对应输出。
内容的提问来源于stack exchange,提问作者Marley
相关产品推荐
相关产品推荐

