I have a multi-project build and I'm trying to add the jar with assets generated by sbt-web to the classpath of the launch script
The project I'm interested in is called website.
typing show website/web-assets:packageBin in sbt creates and shows the jar with the assets. I tried putting in (managedClasspath in website) += website/web-assets:packageBin, but that doesn't compile:
path/to/build.sbt:58: error: value / is not a member of sbt.Project
managedClasspath in website += website/web-assets:packageBin
How can I create the jar with assets when I run the stage task, and place it on the classpath of the launch script
You are mixing sbt-console commands with build.sbt commands.
The sbt-web docs give a clear example how you do it for a single project:
(managedClasspath in Runtime) += (packageBin in Assets).value
So now we do the same thing for a multi-module build. Assuming you have a build.sbt that looks like this
val root = (project in ".")
.aggregate(common, website)
val common = (project in "commons")
.settings(
libraryDependencies ++= Seq(...),
...
)
val website = (project in "commons")
.enablePlugins(JavaServerAppPackaging, SbtWeb)
.settings(
// ------ You configure it like a single module project
(managedClasspath in Runtime) += (packageBin in Assets).value
// ----------------------------------------------------
)
.dependsOn(common)
I have not directly tested this as I don't know your exact configuration. However this should give you the right direction.
Related
When sbt-assembly builds a fat jar, it places all the dependencies in the main folder. I need to construct a jar that looks like this
--domain
domain classes
-- lib
dependency classes
is it possible to do this with sbt assembly, or any other plugin?
If you want to seperate your app jar file and your dependecy jar files, here is the most practical method i found with sbt;
Create project/plugins.sbt file if not exists and add following line:
addSbtPlugin("org.xerial.sbt" % "sbt-pack" % "0.8.0")
After adding this line refresh your project.
Note: Plugin version might change in time.
When sbt refresh finishes update your build.sbt file like this:
lazy val MyApp = project.in(file("."))
.settings(artifactName := {(
sv: ScalaVersion,
module: ModuleID,
artifact: Artifact) => "MyApp.jar"
})
.settings(packSettings)
Then run:
sbt pack
Or if you're doing this for child project, run this:
sbt "project childproject" clean pack
This will nicely seperate your main jar file and your dependency jars.
Your app jar will be in target scala folder.
Your dependencies will be in target/pack/lib.
In this way you can deploy your dependencies once.
And whenever you change your app, you can just deploy your app jar file.
So in every change you don't have to deploy an uber jar file.
Also in production, you can run your app like:
java -cp "MyApp.jar:dependency_jars_folder/*" com.myapp.App
How do I add the resourceDirectory in Java Classpath while SBT runs tests?
For now I only have sbt jar.
My need is due to a dependency (spark-cassandra-connector EmbeddedCassandra) loading a resource via ClassLoader.getSystemResourceAsStream rather than getClass().getClassLoader().getResource ...
If you want to add a new file/folder to your Java Classpth you can add the following line in your build.sbt:
(fullClasspath in Test) := (fullClasspath in Test).value ++ Seq(Attributed.blank((resourceDirectory in Test).value))
This will add the folder given by the test:resourceDirectory setting to the Classpath under the Test configuration.
Note:
The fullClasspath task provides a classpath including both the dependencies and the products of a project. For the test classpath, this includes the main and test resources and compiled classes for the project as well as all dependencies for testing.
...
fullClasspath is the concatenation of dependencyClasspath and exportedProducts
More details can be found here.
I have a scalatra project within which I want to serve JavaScript that's been generated from a scala.js project.
I have a multi-project sbt build that allows me to build both these project successfully.
That is, I can use the compile (and run) tasks in the scalatra project; and I can use the packageJS task in the scala.js project.
However, I'd very much like to be able to have the scalatra compile task depend on the scala.js packageJS task; so when the Scalatra project is compiled, the Javascript is automatically generated in the Scala.js project.
In my multi-project build.sbt file I've tried:
lazy val wwwjs = project // Scala.js project
lazy val www = project // Scalatra project
.dependsOn(wwwjs % "compile->packageJS")
But when compiling the Scalatra project this fails with "configuration not found in wwwjs#wwwjs_2.10;0.1: 'packageJS'. It was required from www#www_2.10;0.1 compile".
I'm fairly new to sbt (and Scalatra and Scala.js!) - can anyone enlighten me as to how to do this?
Thanks :)
What you want here is not a dependency between projects (which is what dependsOn on a project does) but between tasks.
I am not familiar with Scalatra, but for the sbt side it should be extremely similar to Play, and we have a successful template for Play projects with Scala.js here:
https://github.com/vmunier/play-with-scalajs-example/blob/master/project/Build.scala
In particular, I derive the following basic adaptation from your build above:
import scala.scalajs.sbtplugin.ScalaJSPlugin._ // if Build.scala
import ScalaJSKeys._
lazy val wwwjs = project // Scala.js project
lazy val www = project // Scalatra project
.settings(
compile in Compile <<= (compile in Compile) dependsOn (fastOptJS in (wwwjs, Compile))
)
Alternatively, use fullOptJS instead of fastOptJS for the fully optimized version (but that takes several seconds to rebuild every time you make a change).
I cannot seem to configure SBT properly to resolve transitive dependencies from a RootProject my project depends on. The problem seems to be resolvers. I've been able to replicate it with a very simple structure. See below for code.
Inside common/ I can run sbt console and it will resolve the dependency and I can use it. However inside proj/ the same command fails. with UNRESOLVED DEPENDENCIES. But my edofic snapshots resolver isn't listed among tried resolvers. Somehow it isn't picked up. It works if I add the resolver manually to the Build.scala but this defeats the purpose of transitive dependency.
├── common
│ └── build.sbt
└── proj
└── project
└── Build.scala
common/build.sbt
scalaVersion := "2.10.0"
resolvers += "edofic snapshots" at "http://edofic.github.com/repository/snapshots"
libraryDependencies += "com.edofic" % "reactivemacros_2.10.0" % "0.1-SNAPSHOT"
proj/project/Build.scala
import sbt._
import Keys._
object BarBuild extends Build {
val common = RootProject(file("../common"))
val main = Project(id = "main", base = file(".")).settings(
scalaVersion := "2.10.0"
) dependsOn common
}
Just to make things clear: I want to have separate SBT configuration for "common" and I don't want to publish it locally-I want to have SBT handle incremental recompilation when needed. Is RootProject the wrong tool for the job?
Here's a solution that worked for me but it's possible it may break something else:
Inside proj/project/Build.scala add a "delegates" argument to your Project definition like this:
val main = Project(id = "main", base = file("."),
delegates = common :: Nil).settings(
scalaVersion := "2.10.0"
) dependsOn common
I think this may cause your "main" project to pick up all the configuration from the "common" project, so I'm not sure what side effects that may have. Due to this, the solution I've chosen for my project is to have a "config" project that has common configuration for all my projects and use "delegates" with that project so I can control what configuration is being picked up.
I have a library compiled to a jar (not an sbt project, no source code, just the jar file) that's not available on a repository.
Is there a way to publish the jar locally so I can add the dependency using the libraryDependencies += "org.xxx" % "xxx" % "1.0" notation? (I already know how to add the file to a project by copying it to the lib folder.)
The publishLocal action is used to publish your project to a local Ivy repository. By default, this local repository is in ${user.home}/.ivy2/local. You can then use this project from other projects on the same machine source
EDIT: Sorry I misread your question. Here is an example to publish a jar or sources to your local ivy repo.
tl;dr I'd call it a trick not a feature of sbt. You've been warned.
Let's say you've got file.jar to publish. As is for any build tool, sbt including, it's to execute tasks that eventually create an artifact - a jar file in most cases - out of the files in a project.
The project sets the coordinates for the artifact.
The trick is to leverage what sbt requires to set up the environment (= the coordinates) for the jar to be published (otherwise you'd have to specify them on command line that may or may not be very user friendly).
Create a build.sbt with the necessary settings - organization, name, version and possibly scalaVersion - and save it where the jar file is.
organization := "org.abc"
name := "my-own-publish-jar"
version := "1.0.0"
scalaVersion := "2.11.3"
packageBin in Compile := file(s"${name.value}_${scalaBinaryVersion.value}.jar")
You may've noticed, the build changes compile:package task to point at the jar file.
That's it.
Execute sbt publishLocal and the jar file should be in the Ivy2 local repository, i.e. ~/.ivy2/local/org.abc/my-own-publish-jar_2.11/1.0.0/jars/my-own-publish-jar_2.11.jar.
protip Writing a plugin to do it with the coordinates specified on command line should be quite easy now.
Let's say you have wetElephant.jar and wetElephant-javadoc.jar files some 3rd party library and corresponding javadocs which you want to publish to your local repo and referrence it from another project using libraryDependencies sbt taskKey.
Here's what you need to do.
Put your libraries (wetElephant.jar and wetElephant-javadoc.jar) into modules\wetElephant
Define project in your build.sbt file (or Build.scala file)
lazy val stolenLib = project
.in(file("modules/wetElephant"))
.settings(
organization := "com.stolenLibs",
name := "wetElephant",
version := "0.1-IDonKnow",
crossPaths := false, //don't add scala version to this artifacts in repo
publishMavenStyle := true,
autoScalaLibrary := false, //don't attach scala libs as dependencies
description := "project for publishing dependency to maven repo, use 'sbt publishLocal' to install it",
packageBin in Compile := baseDirectory.value / s"${name.value}.jar",
packageDoc in Compile := baseDirectory.value / s"${name.value}-javadoc.jar"
)
Call publishLocal task from sbt/activator (I did it from activator and prefixed it with proejct name):
./activator wetElephant/publishLocal
... and read the output to see what and where was published:
/cygdrive/d/devstation-workspace/projects/m4l-patches 1
[info] Loading project definition from D:\devstation-workspace\projects\m4l-patches\project
[info] Set current project to m4l-patches (in build file:/D:/devstation-workspace/projects/m4l-patches/)
[info] Updating {file:/D:/devstation-workspace/projects/m4l-patches/}wetElephant...
[info] Packaging D:\devstation-workspace\projects\m4l-patches\modules\wetElephant\target\wetelephant-0.1-IDonKnow-sources.jar ...
[info] Done packaging.
[info] Wrote D:\devstation-workspace\projects\m4l-patches\modules\wetElephant\target\wetelephant-0.1-IDonKnow.pom
[info] Resolving org.fusesource.jansi#jansi;1.4 ...4 ....
[info] Done updating.
[info] :: delivering :: com.stolenLibs#wetelephant;0.1-IDonKnow :: 0.1-IDonKnow :: release :: Sun Dec 20 20:09:24 CET 2015
[info] delivering ivy file to D:\devstation-workspace\projects\m4l-patches\modules\wetElephant\target\ivy-0.1-IDonKnow.xml
[info] published wetelephant to C:\Users\pawell\.ivy2\local\com.stolenLibs\wetelephant\0.1-IDonKnow\poms\wetelephant.pom
[info] published wetelephant to C:\Users\pawell\.ivy2\local\com.stolenLibs\wetelephant\0.1-IDonKnow\jars\wetelephant.jar
[info] published wetelephant to C:\Users\pawell\.ivy2\local\com.stolenLibs\wetelephant\0.1-IDonKnow\srcs\wetelephant-sources.jar
[info] published wetelephant to C:\Users\pawell\.ivy2\local\com.stolenLibs\wetelephant\0.1-IDonKnow\docs\wetelephant-javadoc.jar
[info] published ivy to C:\Users\pawell\.ivy2\local\com.stolenLibs\wetelephant\0.1-IDonKnow\ivys\ivy.xml
[success] Total time: 1 s, completed 2015-12-20 20:09:24
Optionally use these libraries in another project
libraryDependencies += "com.stolenLibs" % "wetElephant" % "0.1-IDontKnow"
Disclaimer: I don't know how not to publish sources...
Here is a blog post I followed to push sbt artifact to a maven repository (local and remote) a few months ago.
http://brizzled.clapper.org/id/100/
Try this:
http://maven.apache.org/guides/mini/guide-3rd-party-jars-local.html
I created a sample Play Framework/sbt project that creates a local repository (not just publish-local) here: https://github.com/muymoo/local-ivy-repo-sbt
Specifically look at Build.scala
makeLocalRepoSettings(publishedProjects):_*
and
localRepoArtifacts += "org.apache.ws.security" % "wss4j" % "1.6.9"
These localRepoArtifacts are found in my local ivy repo, but I think you could edit this to work with plain old jar files as well.
To run: play local-repository-created
It is a simpler version of https://github.com/sbt/sbt-remote-control which does a whole lot more in their Build.scala.