sbt - copy managed libraries to lib - sbt

How can I copy managed libraries to a specific folder with Scala Build Tool?
For example:
All the jars from this managed library, would be put in 'project/lib'
libraryDependencies += "com.miglayout" % "miglayout-swt" % "4.2"

I found the solution. Pretty simple actually.
Add the following to build.sbt
This will copy the jars to project/lib_managed/jars//*.jar
retrieveManaged := true
I'm not sure about how to specify a specific folder, but this is good enough to get the jars under the project folder.

Related

single sbt file for creating a fat jar

I work on a Java project, whose tests I want to convert to scala. I saw that it might be more convenient to package the entire project jar with sbt, rather than with maven.
However, I currently have a single pom.xml file, that creates a jar with all dependencies inside ("fat jar") using maven shade plugin, and runs the tests. This is achieved via the "mvn package" command.
With sbt, I saw that 2-3 files are needed just for the fat jar - build.sbt, assembly.sbt, possibly plugins.sbt.
Is there some way by which I can have a single xxx.sbt file, and run one / several sbt commands, to get the same effect?
No, you need at least two files: project/plugins.sbt with the
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.9")
line and build.sbt with the assembly settings. You can merge the *.sbt files in the root directory, sbt reads them all regardless of the name anyway. But the files in the project/ directory are different. You can read more about it in https://www.scala-sbt.org/1.x/docs/Organizing-Build.html

xsbt-web multi-module project: package some modules to jars, others to wars

I'm using sbt 0.13.8 and xsbt-web-plugin 2.0.3
I have a multi-module sbt project. When packaged, one of the modules should be in the form of a war file. All of the others in jar files.
When I add the xsbt-web plugin, packaging generates jars and wars for all modules. How can I tell the xsbt-web plugin to apply itself only to the module that should be packaged as a war?
I've already found one solution, which is to mutate the packagedArtifacts list for each non-war module:
packagedArtifacts <<= packagedArtifacts map { as => as.filter(_._1.`type` != "war") }
However, this is a non-local change which I would have to apply to each new non-war module that I (or a team member) might create.
I do not consider this a duplicate of the StackOverflow issue How to “package” some modules to jars and others to wars in multi-module build with single task? since I am not using assembly.
Note that the jars for the jar modules and the wars for the war modules, which are currently being generated, work splendidly. I'm only trying to avoid the situation where somebody tries to deploy a war that was meant to be a jar.
This was a bug in version 2.0.3 -- thanks for discovering it! I've fixed it in 2.0.4.
To enable .war file publishing for a single module in a multi-module project:
Add xsbt-web-plugin in project/plugins.sbt
Enable the WarPlugin plugin in [webproject]/build.sbt
project/plugins.sbt:
addSbtPlugin("com.earldouglas" % "xsbt-web-plugin" % "2.0.4")
[webproject]/build.sbt:
enablePlugins(WarPlugin)
You can find a full example of this at https://earldouglas.com/ext/stackoverflow.com/questions/31683637/

How to copy config files as part of packaging for use in deployment?

I use sbt 0.13.5 to build a project with a few config files meant to be human-edited after deployment.
Using sbt-native-packager's stage command builds my basic output directory structure for deployment. This results in a bin folder with a start script and all my jars in a lib folder. Great.
That just leaves the text config files that should be copied into a conf folder verbatim alonside the bin/ and lib/ folders (not included in any jar).
How can I copy these configuration files to the output directory on the filesystem (not into any jars) using sbt?
I'm unsure about an out-of-the-box support for src/main/conf directory or similar, and unless you find it, use the following as a workaround:
packageArchetype.java_application
mappings in Universal ++= {
((sourceDirectory in Compile).value / "conf" * "*").get.map { f =>
f -> s"conf/${f.name}"
}
}
It maps files under src/main/conf to conf directory in the package.
NB: I'm pretty sure I've seen somewhere in the code support for the conf directory.
Default Universal convention is to copy files/directories under src/univeral/. So, to include a conf/ directory in the distribution, just add src/universal/conf and copy configuration files there. Credit: this link
This seems to be a 'better' answer, as I am using sbt together with sbt-native-packager plugin:
mappings in Universal ++= contentOf( baseDirectory.value / "conf" )
This takes all the files under the specified "conf" folder and dumps them in the package root folder.
Which uses the MappingsHelper I stumbled upon in the very terse documentation for it in the sbt-native-packager.

Create standalone jar using SBT

I was a heavy Maven user and now I'm gradually using SBT for some of my projects.
I'd like to know how could I use SBT to create a standalone Java project? This project should be packaged as a JAR file and this JAR file would be used as a dependency in another SBT project.
In Maven, I could tell in my pom.xml what type of artifact it should produce when I build it. Is there something similar that I can do in SBT?
There is a difference between standalone and making a project useable as a dependency or another project. In the first case, you would use a plugin such as sbt-assembly. What it will do is create one jar file containing the project class files along with all of its dependencies. If you write an application, what you get is a double-clickable jar that you can execute from anywhere.
If you want to use your project A as a dependency for another project B, you have different options. You could just package the class files of A, using sbt package (answer of #Channing Walton). Then you could drop the resulting .jar file in the lib directory of project B. However, if A also requires libraries, you must make sure that they also end up in project B's libraries.
A better approach is to publish your project. You can do that purely on your local machine, using sbt publish-local. That will store the jar as produced by package in a special local directory which can be accessed from sbt in another project, along with a POM file that contains the dependencies of A. It will use a group-ID (organization) and artifact-ID (name) and a version of your project A. For example, in build.sbt:
name := "projecta"
version := "0.1.0-SNAPSHOT"
organization := "com.github.myname"
scalaVersion := "2.10.3"
publishMavenStyle := true
After publishing with sbt publish-local, you can add the following dependency to your project B:
libraryDependencies += "com.github.myname" %% "projecta" % "0.1.0-SNAPSHOT"
If you have a pure Java project, you can omit the Scala version suffix, i.e. in Project A:
crossPaths := false
autoScalaLibrary := false
And then in Project B:
libraryDependencies += "com.github.myname" % "projecta" % "0.1.0-SNAPSHOT"
(using only one % character between group and artifact ID).
More on publishing in the sbt documentation.
'sbt package' will produce a jar file.
If you want it to be executable you need to add the following to your .sbt config:
mainClass in Compile := Some("your.main.Class")
Sure, you can use 'sbt package' command, it creates a jar file but this jar will be without any dependencies. To run it necessary to specify 'classpath' arg to the libraries.
In your case you wish a standalone runnable file. And you need to add the dependencies.
To do this you can use 'assembly' plugin for SBT, see https://github.com/sbt/sbt-assembly/
Afterward you can just run 'sbt assembly' command, it provides a fat jar file with all dependencies that you can deploy and run anywhere and at any time.
For details see this article
publishLocal
builds the artifact and publish in the local Ivy repository making it available for your local project dependencies.
publishM2
same as above, but the artifact is published in local Maven repo instead of Ivy repo.
I think the easiest way to produce a stand-alone jar with your project in it,
is sadly not lying inside sbt.
I personally use my IDE: Intellij to make the jar (through the 'build artifact' feature).
Thanks to Intellij I can easily choose which library I want to include in the jar or not, (for instance the scala stl).
IMHO, this is by far the simplest method to get an executable jar for your project.
If you put the scala stl you can run your jar with the "java -jar" command, if you don't you have to run it somewhere with the correct version of scala installed with "scala".

Handling unmanaged classpath jars in a library using SBT so that a dependent project can access them

I'm writing a library which depends on code (let's call it foo.jar) which is only available as a binary jar. As is standard, I'm putting this in the lib/ directory so SBT will treat is as an unmanaged dependency. This is fine so far.
However, since this is a library, I'd like to be able to publish it so that other projects which depend on it to also have access to the unmanaged code in foo.jar without having to manually locate it. I originally thought I could use a fat jar plugin such as SBT Assembly to create a jar with the dependencies, but that doesn't affect what is actually published using sbt publish-local – it only creates a fat jar when you run sbt assembly. Is there some standard simple way to handle this? It seems like a bad idea for every library which uses unmanaged dependencies to break when used by other projects downstream so I wonder if I'm missing something obvious.
I don't know if that's a good use of sbt-assembly, since other libraries could depend on a different version of foo.jar etc.
One way to work around it is to publish foo.jar in a Maven repository yourself. Some people in Scala and/or sbt community have been talking about bintray. It's still in beta, but looks promising if you want some jars published.
You might be able to get the result you want by manipulating the mappings in (Compile, packageBin) to include the files you want your packaged jar to have (publish uses the output from packageBin). This technique will allow you to include absolutely any file you want within the jar. The official sbt doc is here: http://www.scala-sbt.org/0.12.3/docs/Howto/package.html#contents
As an example, consider the common case of including a .properties file within your jar. Lets say you need to include "messages.properties" under the path "com/bigco/messages.properties" in your packaged jar. And lets say that this file is under src/main/scala/ ... You can add the following to your build.sbt:
mappings in (Compile, packageBin) <+= baseDirectory map { base =>
(base / "src" / "main" / "scala" / "com" / "bigco" / "messages.properties") -> "com/bigco/messages.properties"
}
To attempt to answer your original question, you could unzip foo.jar and add each one of the class files within to the packaged jar, according to their correct package paths. So something similar to
mappings in (Compile, packageBin) <+= baseDirectory map { base =>
(base / path / to / unzipped / file.class) -> "path.to.unzipped.file.class"
...
}
Or you might be able to get away with simply including foo.jar at the root of the packaged jar like so:
mappings in (Compile, packageBin) <+= baseDirectory map { base =>
(base / "lib" / "foo.jar") -> "foo.jar"
}

Resources