This is how you could achieve what you want with pure SBT 0.13.x (the example should work for older versions in general, but maybe you'd have to use different operators).
build.sbt
import Path.flat
libraryDependencies ++= Seq(
"com.fasterxml.jackson.core" % "jackson-core" % "2.3.1",
"com.netflix.rxjava" % "rxjava-core" % "0.16.1"
// maybe more dpendencies
)
packageOptions in (Compile, packageBin) +=
Package.ManifestAttributes("PluginMainClass" -> "com.xxx.xxx.Class")
// this will copy all managed jars to the ./lib in your jar
mappings in (Compile, packageBin) ++= {
val cp = (managedClasspath in Compile).value.files
cp pair flatRebase("/lib")
}
// this will move all your compiled classes to folder ./com.xxx.xxx in your jar
mappings in (Compile, packageBin) ++= {
val compiledClasses = (products in Compile).value ** "*.class"
val classDirectoryBase = (classDirectory in Compile).value
compiledClasses pair rebase(classDirectoryBase, "com.xxx.xxx")
}
You can then use package
to build the jar. In the example as above the jar will look like this:
Length Date Time Name
--------- ---------- ----- ----
301 2014-05-09 20:13 META-INF/MANIFEST.MF
0 2014-05-09 20:13 /lib/
7126003 2013-09-27 11:44 /lib/scala-library.jar
197986 2013-12-28 02:01 /lib/jackson-core-2.3.1.jar
663553 2014-01-15 08:17 /lib/rxjava-core-0.16.1.jar
--------- -------
7987843 5 files
And the manifest will look like this
Manifest-Version: 1.0
Implementation-Vendor: default
Implementation-Title: q-23553321
Implementation-Version: 0.1-SNAPSHOT
Implementation-Vendor-Id: default
PluginMainClass: com.xxx.xxx.Class // MAIN CLASS OF THE PLUGIN
Specification-Vendor: default
Specification-Title: q-23553321
Specification-Version: 0.1-SNAPSHOT
Edit
Is it possible to get the compiled classes in a multi module build though? IE if I have /modules/X,Y,Z and I want the compiled classes from those projects bundled under "com.xxx.xxx" in the artifact?
The general answer is yes, if the classes are unique. To do that you can use Scopes. In the build.sbt
, replace the mappings for classes with the following:
// define the configuration axis
val anyProjectsCompile = ScopeFilter(inAnyProject, inConfigurations(Compile))
// we want to have class directory and products together to use rebase in the next step
val classDirectoryProducts = Def.task {
(classDirectory.value, products.value)
}
mappings in (Compile, packageBin) ++= {
classDirectoryProducts.all(anyProjectsCompile).value.flatMap { case (classDir, prods) =>
val compiledClasses = (prods ** "*.class").get
compiledClasses pair rebase(classDir, "com.xxx.xxx")
}
}