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

多子项目中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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 20:55:34