Pergunta

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?)

Foi útil?

Solução

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)
 }

Outras dicas

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.

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.

The simplest example using sbt-assembly

  1. Create directory project in your home project dir with file assembly.sbt including

    addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.11.2")

  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)

    }

    }

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top