SBT - multi projects depend on one parent - scala

I have multiple projects that is independent of each other.
They share multiple libraries (reactivemongo, redis cache, akka stream, etc...).
I want to build a "parent" SBT project so all of the "child" projects inherit the shared libraries with same version.
Can this be done in SBT ? can someone share a code example/documentation ?
any help is appreciated :), Thanks.
EDIT:
To be more specific:
I have 2 repositories in Github (child1, child2).
I want to create a 3rd repository called "parent", which will include one build.sbt so other repositories inherit from it.

Something like this should work:
lazy val commonSettings = libraryDependencies ++= Seq(
"org.reactivemongo" %% "reactivemongo" % "0.16.3"
)
lazy val moduleA = (project in file("moduleA"))
.settings(commonSettings)
lazy val moduleB = (project in file("moduleB"))
.settings(commonSettings)
lazy val root = (project in file(".")).settings()
.aggregate(moduleA, moduleB)
Have a look here https://www.scala-sbt.org/1.x/docs/Multi-Project.html for more.

Multi project build using sbt.
lazy val global = project
.in(file("."))
.settings(settings)
.aggregate(
common,
project1,
project2
)
lazy val common = project
.settings(
name := "common",
settings,
libraryDependencies ++= commonDependencies
)
lazy val project1 = project
.settings(
name := "multi1",
settings,
libraryDependencies ++= commonDependencies ++ Seq(
"org.apache.parquet" % "parquet-avro" % "1.7.0",
"org.apache.kafka" % "kafka-clients" % "0.10.1.0"
)
)
.dependsOn(
common
)
lazy val project2 = project
.settings(
name := "multi2",
settings,
libraryDependencies ++= commonDependencies ++ Seq(
"org.scalikejdbc" %% "scalikejdbc" % "2.0.0"
)
)
.dependsOn(
common
)
lazy val commonSettings = Seq(
scalacOptions ++= compilerOptions,
resolvers ++= Seq(
"Local Maven Repository" at "file://" + Path.userHome.absolutePath +
"/.m2/repository",
Resolver.sonatypeRepo("releases"),
Resolver.sonatypeRepo("snapshots")
)
)
lazy val commonDependencies = Seq(
"org.slf4j" % "slf4j-simple" % "1.7.25",
"com.zaxxer" % "HikariCP" % "2.5.1"
"com.oracle" % "ojdbc6" % "11.2.0.4"
)
Please refer link https://github.com/pbassiner/sbt-multi-project-example for more info
Hope it will help!

Related

Caliban federation with scala 3

There is no caliban.federation for scala 3 yet.
My question is what is a correct way to use it along with scala 3 libraries?
For now I have such a dependencies in my build.sbt:
lazy val `bookings` =
project
.in(file("."))
.settings(
scalaVersion := "3.0.1",
name := "bookings"
)
.settings(commonSettings)
.settings(dependencies)
lazy val dependencies = Seq(
libraryDependencies ++= Seq(
"com.github.ghostdogpr" %% "caliban-zio-http" % "1.1.0"
),
libraryDependencies ++= Seq(
org.scalatest.scalatest,
org.scalatestplus.`scalacheck-1-15`,
).map(_ % Test),
libraryDependencies +=
("com.github.ghostdogpr" %% "caliban-federation" % "1.1.0")
.cross(CrossVersion.for3Use2_13)
But when I'm trying to build it, it's erroring:
[error] (update) Conflicting cross-version suffixes in:
dev.zio:zio-query,
org.scala-lang.modules:scala-collection-compat,
dev.zio:zio-stacktracer,
dev.zio:izumi-reflect,
com.github.ghostdogpr:caliban-macros,
dev.zio:izumi-reflect-thirdparty-boopickle-shaded,
dev.zio:zio,
com.github.ghostdogpr:caliban,
dev.zio:zio-streams

SBT, how to add unmanaged JARs to IntelliJ?

I have build.sbt file:
import sbt.Keys.libraryDependencies
lazy val scalatestVersion = "3.0.4"
lazy val scalaMockTestSupportVersion = "3.6.0"
lazy val typeSafeConfVersion = "1.3.2"
lazy val scalaLoggingVersion = "3.7.2"
lazy val logbackClassicVersion = "1.2.3"
lazy val commonSettings = Seq(
organization := "com.stulsoft",
version := "0.0.1",
scalaVersion := "2.12.4",
scalacOptions ++= Seq(
"-feature",
"-language:implicitConversions",
"-language:postfixOps"),
libraryDependencies ++= Seq(
"com.typesafe.scala-logging" %% "scala-logging" % scalaLoggingVersion,
"ch.qos.logback" % "logback-classic" % logbackClassicVersion,
"com.typesafe" % "config" % typeSafeConfVersion,
"org.scalatest" %% "scalatest" % scalatestVersion % "test",
"org.scalamock" %% "scalamock-scalatest-support" % scalaMockTestSupportVersion % "test"
)
)
unmanagedJars in Compile += file("lib/opencv-331.jar")
lazy val pimage = project.in(file("."))
.settings(commonSettings)
.settings(
name := "pimage"
)
parallelExecution in Test := true
It is working fine, if I use sbt run, but I cannot run from IntelliJ.
I receive error:
java.lang.UnsatisfiedLinkError: no opencv_java331 in java.library.path
I can add manually (File->Project Structure->Libraries->+ necessary dir).
My question is: is it possible to specify build.sbt that it will automatically create IntelliJ project with specified library?
I would say try to: drag and drop the dependency into the /lib which should be in the root directory of your project, if it's not there create it.
Run commands:
sbt reload
sbt update
Lastly you could try something like:
File -> Project Structure -> Modules -> then mark all the modules usually 1 to 3, delete them (don't worry won't delete your files) -> hit the green plus sign and select Import Module -> select root directory of your project and it should then refresh it
If none of these help, I'm out of ideas.

Can't import from CrossType.Pure sbt project in Scala

I'm trying to make Play framework project with Scala.js on frontend and one shared project. My sbt configuration is:
import sbt.Project.projectToRef
lazy val scalaV = "2.11.8"
lazy val shared = (crossProject.crossType(CrossType.Pure) in file("shared"))
.settings(
scalaVersion := scalaV,
libraryDependencies ++= Seq(
"com.mediamath" %%% "scala-json" % "1.0"
),
resolvers += "mmreleases" at "https://artifactory.mediamath.com/artifactory/libs-release-global",
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)
)
// set up settings specific to the JS project
.jsConfigure(_ enablePlugins ScalaJSPlay)
lazy val sharedJVM = shared.jvm.settings(name := "sharedJVM")
lazy val sharedJS = shared.js.settings(name := "sharedJS")
lazy val root = (project in file(".")).settings(
scalaVersion := scalaV,
scalaJSProjects := jsProjects,
pipelineStages := Seq(scalaJSProd, gzip),
routesGenerator := InjectedRoutesGenerator,
scalikejdbcSettings,
libraryDependencies ++= Seq(
jdbc,
cache,
ws,
evolutions,
"org.scalatestplus.play" %% "scalatestplus-play" % "1.5.1" % Test,
"mysql" % "mysql-connector-java" % "5.1.39",
"com.vmunier" % "play-scalajs-scripts_2.11" % "0.5.0"
),
resolvers += "scalaz-bintray" at "http://dl.bintray.com/scalaz/releases"
).
enablePlugins(PlayScala).
aggregate(jsProjects.map(projectToRef): _*)
lazy val jsProjects = Seq(js)
lazy val js = (project in file("client")).settings(
scalaVersion := scalaV,
persistLauncher := true,
persistLauncher in Test := false,
autoCompilerPlugins := true,
scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature"),
libraryDependencies ++= Seq(
"org.scala-js" %%% "scalajs-dom" % "0.9.0",
"com.mediamath" %%% "scala-json" % "1.0"
),
resolvers += "mmreleases" at "https://artifactory.mediamath.com/artifactory/libs-release-global",
resolvers += Resolver.sonatypeRepo("releases"),
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.0" cross CrossVersion.full)
).enablePlugins(ScalaJSPlugin, ScalaJSPlay)
Everything is working fine but the problem is: I can't import anything from shared project in Scala.js and Play Framework project. Here is how my shared project structure looks:
And here is how I'm trying to import it:
import services.Encryptor
At compile time I got error:
not found: object services [error] import services.Encryptor
How this issue can be fixed?
First of all, never ever (!) do this:
lazy val sharedJVM = shared.jvm.settings(name := "sharedJVM")
lazy val sharedJS = shared.js.settings(name := "sharedJS")
This creates new projects that are picked up by sbt, so the cross project does not hold the right projects anymore. See docs for details.
Instead, use jsSettings and jvmSettings:
(crossProject.crossType(CrossType.Pure) in file("shared"))
// snip
.jsSettings(name := "sharedJS")
.jvmSettings(name := "sharedJVM")
lazy val sharedJVM = shared.jvm
lazy val sharedJS = shared.js
In your build, it seems that your js project does not depend on the shared project. So if course the shared project's contents are not available.
You need to
lazy val js = (project in file("client"))
// snip
.dependsOn(shared.js)

How to override dependency on certain task in sbt

I want to override dependency on project in certain Task.
I have a sbt multi-project which using spark.
lazy val core = // Some Project
val sparkLibs = Seq(
"org.apache.spark" %% "spark-core" % "1.6.1"
)
val sparkLibsProvided = Seq(
"org.apache.spark" %% "spark-core" % "1.6.1" % "provided"
)
lazy val main = Project(
id = "main",
base = file("main-project"),
settings = sharedSettings
).settings(
name := "main",
libraryDependencies ++= sparkLibs,
dependencyOverrides ++= Set(
"com.fasterxml.jackson.core" % "jackson-databind" % "2.4.4"
)
).dependsOn(core)
When I try to make fat jar to submit on my yarn cluster, I use https://github.com/sbt/sbt-assembly task. But in this case, I want to use sparkLibsProvided instead of sparkLibs something like:
lazy val sparkProvided = (project in assembly).settings(
dependencyOverrides ++= sparkLibsProvided.toSet
)
How can I properly override this dependency?
You can create a new project which is a dedicated project for creating your spark uber jar with the provided flag:
lazy val sparkUberJar = (project in file("spark-project"))
.settings(sharedSettings: _*)
.settings(
libraryDependencies ++= sparkLibsProvided,
dependencyOverrides ++= Set(
"com.fasterxml.jackson.core" % "jackson-databind" % "2.4.4"
)
)
And when you assemble in sbt, go to the said project first:
sbt project sparkUberJar
sbt assembly
This can be easily achieved by using the key provided specifically for what you want:
assemblyExcludedJars in assembly := {
val cp = (fullClasspath in assembly).value
cp filter {
_.data.getName == "spark-core-1.6.1.jar"
}
}
This approach is considered hacky, however, and it would be better if you managed to split your configuration into subprojects, as is also warned in official documentation here:
If you need to tell sbt-assembly to ignore JARs, you're probably doing it wrong. assembly task grabs deps JARs from your project's classpath. Try fixing the classpath first.

How to import Maven libraries with SBT?

I would like to import Maven libraries either with the Maven's XML file or SBT's Scala file. I guess there already are the same questions out, but I could't quite find any. Thank you!
You just treat remote Maven repositories normally. Unless you want to utilize your local .m2/repository. See below for an example Build.scala using both:
object myBuild extends Build {
lazy val mainProject = Project(
id="root",
base=file("."),
settings = Project.defaultSettings ++ Seq(
name := "Root project",
scalaVersion := "2.11.4",
version := "0.1",
resolvers ++= Seq(remoteMavenRepo, localMavenRepo),
libraryDependencies ++= List(
mavenLibrary1, mavenLibrary2
)
)
)
val remoteMavenRepo = "Sonatype Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots/"
val localMavenRepo = "Local Maven" at Path.userHome.asFile.toURI.toURL + ".m2/repository"
// if library folows scala version suffix convention, then we use %%
val mavenLibrary1 = "com.typesafe.slick" %% "slick" % "2.0.2"
// if it's a java library with no scala version suffix, then we use %
val mavenLibrary2 = "joda-time" % "joda-time" % "2.4"