为什么sbt/assembly在有多个子项目的项目中找不到主类?

问题描述 投票:0回答:1

我们正在合并我们的两个 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",
  )

基本上,项目 1 和项目 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>
(这两个主要类是
project1.Main
project2.Main
)。但是,如果我切换到其中一个子项目(例如,通过输入
project project1
)然后输入
run
,sbt 将不再能够检测到主类。此外,如果我使用
assembly
编译项目,我无法运行
project1.jar
project2.jar
,因为它们也找不到它们的主类。为什么会这样?

此外,我注意到我仍然可以将

project2
导入项目 1,将
project1
导入项目 2,即使我只为
dependsOn
设置了
core
。这是预期的行为吗?

scala maven sbt
1个回答
1
投票

你混淆了完全不同的概念、子项目和包。

如果你想有子项目

lazy val project1 = (project in file("project1"))

lazy val project2 = (project in file("project2"))

lazy val core = (project in file("core"))

那么项目结构应该完全不同

core
  src
    main/scala
      Core.scala
    test/scala
      TestCore.scala
project1
  src
    main/scala
      Main.scala
    test/scala
      TestProject1.scala
project2
  src
    main/scala
      Main.scala
    test/scala
      TestProject2.scala

https://www.scala-sbt.org/1.x/docs/Directories.html

https://www.scala-sbt.org/1.x/docs/Multi-Project.html

如果你放

package core

object Core 
package project1

object Main
package project2

object Main

到相同的

src/main/scala
然后
core
project1
project2
是包,而不是子项目,你有唯一的项目。

当然你可以同时拥有子项目和包。那么项目结构就可以了

core                    <-- this is a subproject
  src
    main/scala
      core              <-- this is a package
        Core.scala
    test/scala
      core
        TestCore.scala
project1
  src
    main/scala
      project1
        Main.scala
    test/scala
      project1
        TestProject1.scala
project2
  src
    main/scala
      project2
        Main.scala
    test/scala
      project2
        TestProject2.scala

但是子项目名和包名一般是没有联系的

原则上您可以修改项目结构,使其与默认不同

https://www.scala-sbt.org/1.x/docs/Howto-Customizing-Paths.html

如果我切换到其中一个子项目(例如,通过输入

project project1
)然后输入
run
,sbt 将不再能够检测到主类

那是因为现在您的子项目

project1
project2
core
(在
build.sbt
中声明)是空的。你把所有东西都放在属于
的单
src/main/scala

lazy val root = (project in file("."))

如果您不手动创建它,默认情况下会隐式创建它。

© www.soinside.com 2019 - 2024. All rights reserved.