在构建根项目的胖 JAR 时忽略子项目

Ignoring subproject while building fat JAR of root project

我有一个根项目,我想从中使用 sbt-assembly 构建一个胖 JAR。它确实有一个子项目,它依赖于我想为胖 JAR 忽略的根(就好像它不存在一样)。我该怎么做?

基本上我想要根项目包,就好像尝试 1 中 build.sbt 中没有 localMode 子项目一样。

尝试 1

我的build.sbt

import sbt.Keys._

name := "myprojectname"
version := "0.0.1-SNAPSHOT"
scalaVersion in ThisBuild := "2.11.8"

mainClass in(Compile, run) := Some("com.mywebsite.MyExample")
mainClass in(Compile, packageBin) := Some("com.mywebsite.MyExample")
mainClass in assembly := Some("com.mywebsite.MyExample")

libraryDependencies += "org.apache.spark" %% "spark-core" % "2.0.0" % Provided
libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.0" % Test

lazy val localMode = project.
  in(file("localMode")).
  dependsOn(RootProject(file("."))).
  settings(
    name := "myprojectname_local",
    libraryDependencies += "org.apache.spark" %% "spark-core" % "2.0.0" % Compile,
    mainClass in(Compile, run) := Some("com.mywebsite.MyExample"),
    mainClass in(Compile, packageBin) := Some("com.mywebsite.MyExample")
  )

fullClasspath in assembly := { 
  (fullClasspath in assembly).value diff 
  (fullClasspath in assembly in localMode).value 
}

目前我收到错误信息:

[error] (localMode/*:assembly) deduplicate: different file contents found in the following:
[error] ~/.ivy2/cache/org.sonatype.sisu/sisu-guice/jars/sisu-guice-2.1.7-noaop.jar:com/google/inject/AbstractModule.class
[error] ~/.ivy2/cache/com.google.inject/guice/jars/guice-3.0.jar:com/google/inject/AbstractModule.class
[error] deduplicate: different file contents found in the following:
[error] ~/.ivy2/cache/org.sonatype.sisu/sisu-guice/jars/sisu-guice-2.1.7-noaop.jar:com/google/inject/Binder.class
[error] ~/.ivy2/cache/com.google.inject/guice/jars/guice-3.0.jar:com/google/inject/Binder.class
[error] deduplicate: different file contents found in the following:
[error] ~/.ivy2/cache/org.sonatype.sisu/sisu-guice/jars/sisu-guice-2.1.7-noaop.jar:com/google/inject/ConfigurationException.class
[error] ~/.ivy2/cache/com.google.inject/guice/jars/guice-3.0.jar:com/google/inject/ConfigurationException.class

and so on...

如果我命令 sbt root/assembly 我得到

[error] Expected ID character
[error] Not a valid command: root (similar: reboot, boot, project)
[error] Expected project ID
[error] Expected configuration
[error] Expected ':' (if selecting a configuration)
[error] Expected key
[error] Not a valid key: root (similar: products)
[error] root/assembly
[error]     ^

尝试 2

我的第二个 build.sbt 无法构建:

import sbt.Keys._

lazy val commonSettings = Seq(
  version := "0.0.1-SNAPSHOT",
  scalaVersion in ThisBuild := "2.11.8",
  mainClass in(Compile, run) := Some("com.mywebsite.MyExample"),
  mainClass in(Compile, packageBin) := Some("com.mywebsite.MyExample"),
  libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.0" % Test
)

lazy val root = project.
  in(file("root")).
  dependsOn(RootProject(file("."))).
  settings(
    name := "myprojectname",
    libraryDependencies += "org.apache.spark" %% "spark-core" % "2.0.0" % Provided,
    mainClass in assembly := Some("com.mywebsite.MyExample")
  )

lazy val localMode = project.
  in(file("localMode")).
  dependsOn(RootProject(file("."))).
  settings(
    name := "myprojectname_local",
    libraryDependencies += "org.apache.spark" %% "spark-core" % "2.0.0" % Compile
  )

我认为您可以使用 assembly::fullClasspath 设置来完成。通过 default 它被设置为 fullClasspath or (fullClasspath in Runtime)。所以也许你可以这样做:

fullClasspath in assembly := { 
  (fullClasspath in assembly).value diff 
  (fullClasspath in assembly in localMode).value 
}

在没有关于您的特定项目配置的详细信息的情况下,我猜 localMode 是您要排除的子项目的名称。

更新

您的尝试 2 中的 build.sbt 存在一些问题: - 你没有为你的项目添加通用设置 - "root" 是项目目录根目录中的那个(即 in file(".")) - 如果您显式定义 root 项目,另一个应该依赖于它,而不是 RootProject,这只是一种引用 "implicitly" 定义的根项目

import sbt.Keys._

lazy val commonSettings = Seq(
  version := "0.0.1-SNAPSHOT",
  scalaVersion in ThisBuild := "2.11.8",
  mainClass in(Compile, run) := Some("com.mywebsite.MyExample"),
  mainClass in(Compile, packageBin) := Some("com.mywebsite.MyExample"),
  libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.0" % Test
)

lazy val root = project.in(file(".")).
  settings(commonSettings: _*).
  settings(
    name := "myprojectname",
    libraryDependencies += "org.apache.spark" %% "spark-core" % "2.0.0" % Provided,
    mainClass in assembly := Some("com.mywebsite.MyExample")
  )

lazy val localMode = project. // by default the name of the project val is the name of its base directory
  dependsOn(root).
  settings(commonSettings: _*).
  settings(
    name := "myprojectname_local",
    libraryDependencies += "org.apache.spark" %% "spark-core" % "2.0.0" % Compile
  )

查看 Multi-project builds. To your questions about the root project, there's a chapter called Default root project 上的 sbt 文档。现在有了这些修复,root/assembly 是否按预期工作?

试试放

aggregate in (Compile, assembly) := false