Is there a way to tell sbt to package all needed libraries (scala-library.jar) into the main package, so it is stand-alone? (static?)
-
possible duplicate of [How to run a sbt-managed application project without sbt?](http://stackoverflow.com/questions/7195079/how-to-run-a-sbt-managed-application-project-without-sbt) – Jacek Laskowski Dec 28 '13 at 20:44
-
Duplicate of http://stackoverflow.com/q/7195079/1305344 and http://stackoverflow.com/q/7134993/1305344 – Jacek Laskowski Dec 28 '13 at 20:44
-
http://blog.prabeeshk.com/blog/2014/04/01/a-standalone-spark-application-in-scala/ – USB Apr 09 '15 at 03:33
5 Answers
Edit 2011:
Since then, retronym (which posted an answer in this page back in 2010), made this sbt-plugin "sbt-onejar", now in its new address on GitHub, with docs updated for SBT 0.12.
Packages your project using One-JAR™
onejar-sbt
is a simple-build-tool plugin for building a single executable JAR containing all your code and dependencies as nested JARs.
Currently One-JAR version 0.9.7 is used. This is included with the plugin, and need not be separately downloaded.
Original answer:
Directly, this is not possible without extending sbt (a custom action after the model of the "package" sbt action).
GitHub mentions an assembly task, custom made for jetty deployment. You could adapt it for your need though.
The code is pretty generic (from this post, and user Rio):
project / build / AssemblyProject.scala
import sbt._
trait AssemblyProject extends BasicScalaProject
{
def assemblyExclude(base: PathFinder) = base / "META-INF" ** "*"
def assemblyOutputPath = outputPath / assemblyJarName
def assemblyJarName = artifactID + "-assembly-" + version + ".jar"
def assemblyTemporaryPath = outputPath / "assembly-libs"
def assemblyClasspath = runClasspath
def assemblyExtraJars = mainDependencies.scalaJars
def assemblyPaths(tempDir: Path, classpath: PathFinder, extraJars: PathFinder, exclude: PathFinder => PathFinder) =
{
val (libs, directories) = classpath.get.toList.partition(ClasspathUtilities.isArchive)
for(jar <- extraJars.get ++ libs) FileUtilities.unzip(jar, tempDir, log).left.foreach(error)
val base = (Path.lazyPathFinder(tempDir :: directories) ##)
(descendents(base, "*") --- exclude(base)).get
}
lazy val assembly = assemblyTask(assemblyTemporaryPath, assemblyClasspath, assemblyExtraJars, assemblyExclude) dependsOn(compile)
def assemblyTask(tempDir: Path, classpath: PathFinder, extraJars: PathFinder, exclude: PathFinder => PathFinder) =
packageTask(Path.lazyPathFinder(assemblyPaths(tempDir, classpath, extraJars, exclude)), assemblyOutputPath, packageOptions)
}
-
3imho it should be. I've successfully used a slightly modified version of this AssemblyProject for a few months now. It will fail on duplicate files (something to watch for if you have a complex project with sub-projects), and will fail with the latest build of hibernate (hibernate includes some weird zip entries that cause it grief). – Michael May 22 '10 at 12:36
-
1The URL to sbt-onejar has changed: https://github.com/sbt/sbt-onejar (has new version and docs updated for SBT 0.12) – akauppi Nov 01 '12 at 11:58
It takes a bit of work, but you can also use Proguard from within SBT to create a standalone JAR.
I did this recently in the SBT build for Scalala.

- 54,768
- 12
- 155
- 168
-
1Proguard is powerful, but if you have a lot of jars, you have to manually define every class or method called dynamically - see http://proguard.sourceforge.net/index.html#/manual/limitations.html and see "problems at runtime" http://proguard.sourceforge.net/index.html#/manual/troubleshooting.html – Jonathan Hendler Apr 11 '11 at 06:27
-
https://github.com/ymasory/sbt-prototype uses [Proguard](http://proguard.sourceforge.net/) to make an executable jar. The prototype works out-of-the-box flawlessly at least on a simple applications. – user272735 May 11 '12 at 17:25
The simplest example using sbt-assembly
Create directory project in your home project dir with file assembly.sbt including
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")
In file build.sbt
import AssemblyKeys._ // put this at the top of the file
assemblySettings
jarName += "Mmyjarnameall.jar"
libraryDependencies ++= Seq( "exmpleofmydependency % "mydep" % "0.1" )
mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
{
case s if s.endsWith(".class") => MergeStrategy.last
case s if s.endsWith("pom.xml") => MergeStrategy.last
case s if s.endsWith("pom.properties") => MergeStrategy.last
case x => old(x)
}
}

- 486
- 4
- 6
The simplest method is just to create the jar from the command line. If you don't know how to do this I would highly recommend that you do so. Automation is useful, but its much better if you know what the automation is doing.
The easiest way to automate the creation of a runnable jar is to use a bash script or batch script in windows.
The simplest way in sbt is just to add the Scala libraries you need to the resource directories:
unmanagedResourceDirectories in Compile := Seq(file("/sdat/bins/ScalaCurrent/lib/scalaClasses"))
So in my environment ScalaCurrent is a link to the current Scala library. 2.11.4 at the time of writing. The key point is that I extract the Scala library but place it inside a ScalaClassses directory. Each extracted library needs to go into its top level directory.

- 6,001
- 4
- 34
- 57
Working off of what @retronym offered above, I built a simple example that builds a stand alone jar which includes the Scala libraries (i.e. scala-library.jar) using Proguard with sbt. Thanks, retronym.

- 3,693
- 26
- 43