在 uber jar 中构建 sbt 项目,而不是单独的子模块 jar
Posted
技术标签:
【中文标题】在 uber jar 中构建 sbt 项目,而不是单独的子模块 jar【英文标题】:Build sbt project in uber jar instead of individual submodule jars 【发布时间】:2021-01-22 11:13:30 【问题描述】:最近一直在尝试改变我的 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 文件非常非常小(大小不超过 5mbs),并且只包含 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
会影响添加、覆盖等依赖项的方式?
【问题讨论】:
也许使用dependsOn
而不是aggregate
可以解决问题?
它确实有效!有点......在一个模块中解决的依赖问题现在在更改为dependsOn后重复......主模块是否应该包含与其子模块相同的依赖关系和着色规则? @LuisMiguelMejíaSuárez
和错误我的意思是这种错误 [error] deduplicate: different file contents found in the following:
是的,不知道,对不起。我从来没有这样做过,只是认为这可能会有所帮助。您可能还想在gitter channel 中提问。
【参考方案1】:
让我们把你的问题分成两部分,如何将子模块包含到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 导致任务在聚合模块中执行,并且所有任务都被聚合,而dependsOn 设置了一个 CLASSPATH 依赖项,因此这些库对聚合模块是可见的(取决于示例中的默认编译配置)。
因此,当您聚合 inner_module_one
和 inner_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
为了检查类 One 是否在 jar 中,我使用了以下命令:
jar tfv inner-module-one/target/scala-2.12/inner-module-one-assembly-0.1.0-SNAPSHOT.jar | grep One
然后,当使用原始 aggregate
运行 sbt assembly
时,上面的命令在输出 jar 上提供了空结果。当运行sbt assembly
和dependsOn
时,上面的命令提供了一个结果:
480 Fri Oct 09 01:48:14 IDT 2020 One.class
如果这会导致冲突,您可以在 sbt-assembly: deduplication found error 阅读相关内容
【讨论】:
那再清楚不过了!非常感谢 Tomer 的回复。以上是关于在 uber jar 中构建 sbt 项目,而不是单独的子模块 jar的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 sbt-assembly 和 sbt-native-packager 构建 deb 包以包含单个程序集 jar?