Make42
Make42

Reputation: 13108

Ignoring subproject while building fat JAR of root project

I have a root project from which I want to build a fat JAR with sbt-assembly. It does have a subproject, which depends on root which I want to have ignored for the fat JAR (as if it didn't exist). How do I do this?

Basically I want the root project packages as if there was no localMode subproject from the build.sbt in Try 1.

Try 1

My build.sbt is

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 
}

currently I get the error message:

[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...

If I command sbt root/assembly I get

[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]     ^

Try 2

My second build.sbt cannot be build:

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
  )

Upvotes: 1

Views: 198

Answers (2)

Eugene Yokota
Eugene Yokota

Reputation: 95654

Try putting

aggregate in (Compile, assembly) := false

Upvotes: 0

laughedelic
laughedelic

Reputation: 6460

I think you can do it with the assembly::fullClasspath setting. By default it's set to fullClasspath or (fullClasspath in Runtime). So probably you can do something like this:

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

In the absence of details about you particular project configuration, I guess localMode is the name of the subproject you want to exclude.

UPDATE

There are some problems with the build.sbt in your Try 2: - you don't add common settings to your projects - "root" is the one in the, well, root of your project dir (i.e. in file(".")) - if you explicitly define root project, the other one should depend on it, instead of the RootProject, which is just a way to refer to the "implicitly" defined root project

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
  )

Check sbt docs on Multi-project builds. To your questions about the root project, there's a chapter called Default root project. Now with these fixes, does root/assembly work as expected?

Upvotes: 1

Related Questions