多子项目中sbt/assembly无法找到主类及子项目导入异常问题
问题背景与现象
我们将两个共享大量功能的Scala项目合并为一个新仓库,配置了如下build.sbt:
ThisBuild / scalaVersion := "2.13.10" libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.15" % Test lazy val project1 = (project in file("project1")) .dependsOn(core) .settings( name := "Project 1", assembly / mainClass := Some("project1.Main"), assembly / assemblyJarName := "project1.jar", ) lazy val project2 = (project in file("project2")) .dependsOn(core) .settings( name := "Project 2", assembly / mainClass := Some("project2.Main"), assembly / assemblyJarName := "project2.jar", ) lazy val core = (project in file("core")) .settings( name := "Core", )
Project 1和Project 2均依赖Core,彼此无依赖。当前src目录结构如下:
src main/scala core Core.scala project1 Main.scala project2 Main.scala test/scala core TestCore.scala project1 TestProject1.scala project2 TestProject2.scala
各文件代码如下:Core.scala:
package core object Core { def hello() = { println("hello from core!") } }
project1/Main.scala:
package project1 import core.Core object Main { def main(args: Array[String]): Unit = { hello() Core.hello() } def hello() = { println("hello from project 1!") } }
project2/Main.scala:
package project2 import core.Core object Main { def main(args: Array[String]): Unit = { hello() Core.hello() } def hello() = { println("hello from project 2!") } }
出现以下异常现象:
- 在项目根目录的sbt终端中,可通过
run选择主类或runMain <main_class>运行,但切换到子项目(如project project1)后执行run无法检测到主类; - 使用
assembly编译后,生成的project1.jar和project2.jar也无法找到主类; - 虽未设置子项目间的
dependsOn,仍可在Project1中导入project2,Project2中导入project1。
请问这些现象的原因是什么?
原因分析
1. 子项目run无法检测主类
sbt多项目结构中,每个子项目默认会读取自身目录下的源码(例如project1/src/main/scala),但当前所有源码都存放在根目录的src下,该目录属于根项目的源码目录,而非任何子项目。因此在根目录执行run时能扫描到所有主类,切换到子项目后,子项目找不到对应源码,自然检测不到主类。
2. assembly生成的Jar找不到主类
本质原因和上述一致:子项目project1、project2没有自身的源码文件,assembly打包时并未将project1.Main、project2.Main等类包含进Jar包。虽然配置了assembly / mainClass指定主类名,但Jar中不存在对应字节码,运行时就会报错找不到主类。
3. 子项目可互相导入对方代码
由于所有源码都在根项目的src目录下,根项目会编译所有这些代码。而sbt多项目环境中,所有子项目默认会隐式依赖根项目的编译产物,因此即使未显式设置dependsOn,子项目也能访问到根项目中其他子项目包下的代码。
内容的提问来源于stack exchange,提问作者James Kelleher
相关产品推荐
相关产品推荐

