在 uber jar 而不是单独的子模块 jar 中构建 sbt 项目

Build sbt project in uber jar instead of individual submodule jars

最近一直在尝试更改我的 Scala 项目进行组装的方式,以便仅从中生成一个 jar,而不是每个模块生成一个。

main-project
| - inner-module-one [inner_module_one]
| - inner-module-two [inner_module_two]

我目前所做的是主模块的以下内容(我希望它的 uber jar 包含其他模块内容)。

project
  .in(file("."))
  .settings(
    name := "main-project",
    assemblyName,
    settings
  )
  .aggregate(
    inner_module_one,
    inner_module_two
  )

其他两个模块声明如下。

lazy val inner_module_one = project
  .in(file("inner-module-one"))
  .settings(
    name := "inner-module-one",
    assemblyName,
    settings,
    dependencies and such (...)
  )
  .dependsOn(
    inner_module_two
  )

main-project 生成的 jar 文件非常非常小(大小不超过 5mb)并且只包含 Scala 相关的东西,没有项目 类 之类的。但是,其他模块 jar 是完整的并且包含它们所需的一切。

我已经尝试将以下设置添加到 main-project

aggregate in assembly := false

但到目前为止仍然没有运气。子模块的 jar 没有生成,但是 main-project jar 仍然不包含子模块的内容。

任何问题可能出在哪里的线索?

编辑

尝试了@LuisMiguelMejíaSuárez 的建议并且似乎想要构建,但是,出现了一些错误,这些错误已经在各自的模块中得到解决。在给定的模块中有一些冲突由于一些覆盖而得到解决,但现在它们又出现了。

[error] deduplicate: different file contents found in the following:

使用 dependsOn 而不是 aggregate 会影响依赖项的添加、覆盖等方式吗?

让我们将您的问题分为两部分,如何将子模块包含到 main-project,以及您想知道如何不打包组装这 2 个子模块。

让我们从容易的第二个开始。 sbt-assembly, 是sbt的插件。就像任何其他插件一样,您可以使用 disablePlugins 命令禁用它。因此,如果您定义:

lazy val inner_module_one = project.disablePlugins(AssemblyPlugin)
  .in(file("inner-module-one"))
  .settings(
    name := "inner-module-one"
)
.dependsOn(
  inner_module_two
)

然后 inner_module_one 不会构建 jar。

要解决第一个问题,我们需要了解aggregate和dependsOn的区别。为此,我将引用 Jacek Laskowski great explanation:

aggregate causes the tasks to be executed in the aggregating module and all aggregated one while dependsOn sets a CLASSPATH dependency so the libraries are visible to the aggregateing module (depending on the configuration that's compile aka default in the example).

因此,当您聚合 inner_module_oneinner_module_two 时,您也只是导致组装。为了让这些成为 main-project 的一部分,您需要做的就是声明:

project
  .in(file("."))
  .settings(
    name := "main-project",
    assemblyName,
    settings
  )
  .dependsOn(
    inner_module_one,
    inner_module_two
  )

为了测试它,我创建了以下结构:

main-project
|-inner_module_one
 |-main
  |-scala
   |One.scala
|-inner_module_two
 |-main
  |-scala
   |Two.scala

为了检查 class 一个是否在罐子里,我使用了命令:

jar tfv inner-module-one/target/scala-2.12/inner-module-one-assembly-0.1.0-SNAPSHOT.jar | grep One 

然后,当 运行 sbt assembly 与原始 aggregate 时,上面的命令在输出 jar 上提供了空结果。当 运行 sbt assemblydependsOn 时,上面的命令提供了一个结果:

480 Fri Oct 09 01:48:14 IDT 2020 One.class

如果这会导致冲突,您可以在 sbt-assembly: deduplication found error

阅读相关内容