sbt how to specify dependency to a sibling project - scala

I have a main sbt project which depends on two sbt subprojects, 'util', and 'common'. In addition the common project depends on the util project. In the build.sbt of the common project, how should I specify the dependency to the sibling project util, so that I can compile the common project independently?
Many thanks.
Azad

Related

How to include jars under lib in multi-project sbt setup?

I have a project that is similar to the sbt-multi-project-example one. The only difference is that I have two already compiled jar dependencies inside a lib/ folder on root folder.
On a single-project sbt setup it automatically collects those jars and use them to compile my project, but in this case it is not being collected by the sub-projects.
Only one of my sub-projects require those jars.
Where should I put those jars and how should I setup build.sbt to recognize them?
Put the jars in a lib/ folder in the sub-project that requires them.

Control dependency loading ambiguity on SBT multi-project

I have an SBT Scala multi-project with the following structure:
multiprojectRoot
project/SharedProjectBuildCode.scala
project1
src/sourceFiles
project1-build.sbt
project2
src/sourceFiles
project2-build.sbt
projectN
src/sourceFiles
projectN-build.sbt
multiprojectRoot/project/SharedProjectBuildCode.scala: contains multi-project definitions that use dependsOn to create dependencies on local projects. For example:
lazy val project2 = Project(
...
).dependsOn(project1)
multiprojectRoot/project2/project2-build.sbt: Contains the settings and dependencies for a given project. For example:
name := "project2"
libraryDependencies ++= Seq(
...
"my.company" % "project1" % "1.0"
)
First dependency to project1 is declared with dependsOn on SharedProjectBuildCode.scala file and the second is created on standalone project2-build.sbt build definition file.
So, project2 definition contains either:
an ambiguous dependency to project1 or
a double dependency to project1
We want to keep this project structure, because is the best for our current workflow:
Independent .sbt files serve standalone deployment purposes for each project on our continuous delivery server.
Multi-project .scala file with dependsOn is used to facilitate development, allowing us to avoid things such as continuous publishLocal.
We need to have control for such dependency ambiguities someway. Can you help me?
I think you should have in SharedProjectBuildCode.scala
lazy val root = Project(id = "Main-Project",
base = file(".")) aggregate(project1, project2,..)
lazy val project2 = Project(id = "project2",
base = file("project1")).dependsOn(project1)
...
And don't need to add as dependency in build.sbt anymore.
I was able to control which dependency set loaded on each use case by using the rules of build files loading provided by SBT.
When you load SBT from a given root directory, it looks for *.sbt files on the root directory and also for *.scala on the root/project directory. If you have a multi-project build, then it also reads the definitions of .sbt files that are encountered on child projects, but it will not use project/.scala files on child projects:
.sbt build definition
Multi-project builds
So, I changed my multi-project build the following way:
multiprojectRoot
project/SharedProjectBuildCode.scala
project1
src/sourceFiles
project/DeploymentOnlyCode.scala
project1-build.sbt
project2
src/sourceFiles
project/DeploymentOnlyCode.scala
project2-build.sbt
projectN
src/sourceFiles
project/DeploymentOnlyCode.scala
projectN-build.sbt
This way, depending on the use case I run SBT from the multi-project root or a project internal directory:
Development: SBT is run from multiprojectRoot directory. It takes the advantages of having a multi-project build (such as using dependsOn and avoiding publishLocal).
Production: SBT is run from within a concrete project directory, such as multiprojectRoot/project2. It allows the project to be built as stand-alone, having all dependencies as explicit external (useful for declaring a sequence of dependencies on production, continuous integration server).
Now, a project has 3 instances of code that aggregates their attributes for a final build:
multiprojectRoot/project/SharedProjectBuildCode.scala: Contains local dependencies and other code relevant for multi-project build.
multiprojectRoot/project1/project1-build.sbt: Contains project build attributes, common for multi-project and standalone build of a project, such as name or dependencies that are always external. The same should be done for other multi-project projects of the same level, to be explicitly treated as external dependency artifacts.
multiprojectRoot/project1/project/DeploymentOnlyCode.scala: Contains build attributes that will only be taken into consideration for stand-alone build. The same can be done on other sub-projects, if these require to define deployment specific attributes.
This also gives maximum control on how a project is built, whether is a releasable artifact or not, and handle source code relevant only for a given project, as a complete and independent piece.

Include Dependencies in JAR using SBT package

Apparently project dependencies are not being packaged into the jar generated by:
sbt package
How can dependencies be included?
Well, I use sbt-assembly plugin to create jar with dependencies,
(1) add sbt-assembly to projects/assembly.sbt
echo 'addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.8")' > project/assembly.sbt
(2) run sbt clean assembly to build the jar.
It will create ${name}-assembly-${version}.jar in target/scala-${scalaVersion}
(3) Only in case you get infamous de-duplicate error, use assemblyMergeStrategy as described in here
There's a project called onejar that will package a project and all its dependencies into a single jar file. There is an SBT plugin as well:
https://github.com/sbt/sbt-onejar
However if you're just looking to create a standard package (deb, rpm, etc.) there is sbt-native-packager:
https://github.com/sbt/sbt-native-packager
It can place all your dependencies into a Linux package and add the appropriate wrappers to load all your dependencies and start your program or service.

How to use external dependencies in sbt's .scala files?

This is for Scala 2.11.1 and sbt 0.13.5.
Say I have a Scala/sbt project with the following directory structure:
root/
build.sbt
src/ ..
project/
plugins.sbt
build.properties
LolUtils.scala
and I want to use some external library in LolUtils.scala. How is this generally accomplished in sbt?
If I simply add the libs I need into build.sbt via libraryDependencies += .. then it doesn't find them and fails on the import line with not found: object ...
If I add a separate project/build.sbt, for some reason it starts failing to resolve my plugins, plus I need to manually specify the Scala version in the nested project/build.sbt, which is unnecessary duplication.
What's the best way to accomplish this?
sbt is recursive which means that it uses itself to compile a build definition, i.e. *.sbt files and *.scala files under project directory. To add extra dependencies to use them in the build definition you have to declare them in a project/build.sbt.
There is one caveat to that. You can set any scalaVersion to your project, that is in build.sbt, but you should not modify scalaVersion in the project/build.sbt as it might conflict with the version sbt itself uses (that may or may not lead to binary incompatibility for plugins).
Sbt 0.13.5 is using Scala 2.10.4, and the library you're going to use must be compatible with that particular version of Scala.
> about
[info] This is sbt 0.13.5
...
[info] sbt, sbt plugins, and build definitions are using Scala 2.10.4

Supply provided dependencies with build flag in sbt

I have a project that's main purpose is to provide a collection of algorithms to client. However, it secondarily handles a HTTP interfaces to those algorithms. Since I don't want my clients to inherent the HTTP libraries (unfiltered and dispatch) I have them scoped as provided in sbt. How can I set up my project so that when I sbt assembly, these dependencies (along with a logging implementation) are compiled but when I sbt package or sbt publish they are not?
I think the answer is as simple as telling the assembly plugin to use the compile configuration of jars instead of the runtime dependency (since provided are not on the runtime classpath).
sbt 0.13 syntax:
fullClasspath in assembly := (fullClasspath in Compile).value