How to run main project in multi-project scala - scala

I've following Build code to have multi-project setup:
import sbt._
import Keys._
import com.typesafe.sbt.SbtScalariform._
import scalariform.formatter.preferences._
import sbtunidoc.Plugin._
object DirectorynameBuild extends Build {
addCommandAlias("rebuild", ";clean; compile; package")
lazy val BoundedContext = Project(id = "BoundedContext",
base = file("."),
settings = commonSettings).aggregate(
persistence,
core,
biz,
protocol,
transport)
lazy val persistence = Project(id = "BoundedContext-persistence",
settings = commonSettings,
base = file("persistence")) dependsOn (protocol)
lazy val core = Project(id = "BoundedContext-core",
settings = commonSettings,
base = file("core")) dependsOn (
persistence,
biz,
protocol)
lazy val biz = Project(id = "BoundedContext-biz",
settings = commonSettings,
base = file("biz")) dependsOn (protocol)
lazy val protocol = Project(id = "BoundedContext-protocol",
settings = commonSettings,
base = file("protocol"))
lazy val transport = Project(id = "BoundedContext-transport",
settings = commonSettings,
base = file("transport")) dependsOn(protocol)
val ORGANIZATION = "my.first.ddd.app"
val PROJECT_NAME = "directoryname"
val PROJECT_VERSION = "0.1-SNAPSHOT"
val SCALA_VERSION = "2.11.4"
val TYPESAFE_CONFIG_VERSION = "1.2.1"
val SCALATEST_VERSION = "2.2.2"
val SLF4J_VERSION = "1.7.9"
val LOGBACK_VERSION = "1.1.2"
lazy val commonSettings = Project.defaultSettings ++
basicSettings ++
formatSettings ++
net.virtualvoid.sbt.graph.Plugin.graphSettings
lazy val basicSettings = Seq(
version := PROJECT_VERSION,
organization := ORGANIZATION,
scalaVersion := SCALA_VERSION,
libraryDependencies ++= Seq(
"com.typesafe" % "config" % TYPESAFE_CONFIG_VERSION,
"org.slf4j" % "slf4j-api" % SLF4J_VERSION,
"ch.qos.logback" % "logback-classic" % LOGBACK_VERSION % "runtime",
"org.scalatest" %% "scalatest" % SCALATEST_VERSION % "test"
),
scalacOptions in Compile ++= Seq(
"-unchecked",
"-deprecation",
"-feature"
),
/*javaOptions += "-Djava.library.path=%s:%s".format(
sys.props("java.library.path")
),*/
fork in run := true,
fork in Test := true,
parallelExecution in Test := false
)
lazy val formatSettings = scalariformSettings ++ Seq(
ScalariformKeys.preferences := FormattingPreferences()
.setPreference(IndentWithTabs, false)
.setPreference(IndentSpaces, 2)
.setPreference(AlignParameters, false)
.setPreference(DoubleIndentClassDeclaration, true)
.setPreference(MultilineScaladocCommentsStartOnFirstLine, false)
.setPreference(PlaceScaladocAsterisksBeneathSecondAsterisk, true)
.setPreference(PreserveDanglingCloseParenthesis, true)
.setPreference(CompactControlReadability, true)
.setPreference(AlignSingleLineCaseStatements, true)
.setPreference(PreserveSpaceBeforeArguments, true)
.setPreference(SpaceBeforeColon, false)
.setPreference(SpaceInsideBrackets, false)
.setPreference(SpaceInsideParentheses, false)
.setPreference(SpacesWithinPatternBinders, true)
.setPreference(FormatXml, true)
)
//credentials += Credentials(Path.userHome / ".ivy2" / ".credentials")
}
I've not defined src/main/scala in root folder.
I could run individual project using sbt "project ****" run
If I follow command: sbt run then I'm getting "No Main Class Detected"
I could see lagom framework is easily implementing the process I wanted. But I couldn't figure out the process.
What should I do to make the main project run without use of src/main/scala/***App.scala?

Related

Cross compiling Scala versions with differing project modules

I'm trying to use sbt-projectmatrix to cross compile scala versions. However, I want one of the final modules to use different internal dependencies, based on the target Scala version.
This is a toy example of where I am right now:
lazy val root: Project = (projectMatrix in file("."))
.settings(commonSettings: _*)
.settings(publish := {})
.aggregate(
a_spark21.projectRefs ++
a_spark22.projectRefs ++
a_spark23.projectRefs ++
a_spark24.projectRefs ++
top.projectRefs ++: _*
)
lazy val top: Project = (projectMatrix in file("vulcan-hive"))
.disablePlugins(SitePreviewPlugin, SitePlugin, ParadoxPlugin, ParadoxSitePlugin)
.settings(name := "vulcan-hive")
.settings(commonSettings: _*)
.jvmPlatform(scalaVersions = Seq(versions.scala211, versions.scala212))
.customRow(
scalaVersions = Seq(versions.scala211),
axisValues = Seq(VirtualAxis.jvm),
_.settings(
SubModuleDependencies.hiveDependencies24,
libraryDependencies ++= Dependencies.Spark24.Compile.all.map(_.force()),
)
)
.customRow(
scalaVersions = Seq(versions.scala212),
axisValues = Seq(VirtualAxis.jvm),
_.settings(
SubModuleDependencies.hiveDependencies24,
libraryDependencies ++= Dependencies.Spark24.Compile.all.map(_.force()),
)
)
.dependsOn(a_spark24 % "compile->compile;test->test", a_spark23 % "compile->compile;test->test", a_spark22 % "compile->compile;test->test", a_spark21 % "compile->compile;test->test")
lazy val a_spark21: Project = (projectMatrix in file(a_spark21))
.jvmPlatform(scalaVersions = Seq(versions.scala211))
.customRow(
scalaVersions = Seq(versions.scala211),
axisValues = Seq(VirtualAxis.jvm),
_.settings(
libraryDependencies ++= Dependencies.Spark21.Compile.all.map(_.force())
)
)
lazy val a_spark22: Project = ...
lazy val a_spark23: Project = ...
lazy val a_spark24: Project = (projectMatrix in file(a_spark24))
.jvmPlatform(scalaVersions = Seq(versions.scala211, versions.scala212))
.customRow(
scalaVersions = Seq(versions.scala211),
axisValues = Seq(VirtualAxis.jvm),
_.settings(
libraryDependencies ++= Dependencies.Spark24.Compile.all.map(_.force())
)
)
.customRow(
scalaVersions = Seq(versions.scala212),
axisValues = Seq(VirtualAxis.jvm),
_.settings(
libraryDependencies ++= Dependencies.Spark24.Compile.all.map(_.force())
)
)
This fails with this error:
no rows were found in a_spark23 matching ProjectRow(true, List(PlatformAxis(jvm,JVM,jvm), ScalaVersionAxis(2.12.12,2.12))): List(ProjectRow(true, List(PlatformAxis(jvm,JVM,jvm), ScalaVersionAxis(2.11.12,2.11))), ProjectRow(true, List(PlatformAxis(jvm,JVM,jvm), ScalaVersionAxis(2.11.12,2.11))))
This error makes sense since top is trying is trying to find 2.12 dependencies for a_spark23 even though a_spark23 doesn’t have a 2.12 row defined. Is there a way to move dependsOn definitions to the customRow arguments? Or access the scalaBinaryVersion in outside the settings closure so that I can pass different lists to dependsOn?
The final product I want is top_2.12 that's depends on a_spark24_2.12 and top_2.11 that depends on [a_spark21_2.11, a_spark22_2.11, a_spark23_2.11, a_spark24_2.11]
Any help or guidance would be greatly appreciated!

Read config file while generating Slick code via SBT

I am reading this sample which shows me how to generate source code using Slick-CodeGen
https://github.com/slick/slick-codegen-example/blob/master/build.sbt
And while this sample, is good, I want to modify it so that it reads the database config from application.conf using typesafe config.
Otherwise I will have to replicate the database connection configuration here and also in application.conf file.
Does anyone know, how can this sample be modified so that we can use the typesafe config to read the config values from application.conf?
Edit: Based on the suggestion below, I tried the following
I created a file called build.sbt in the project folder
libraryDependencies += "com.typesafe" % "config" % "1.3.1"
modified my main build.sbt file (in project root) as
val slickVersion = "3.1.1"
lazy val mainProject = Project(
id = "FooBar",
base=file("."),
settings = Defaults.coreDefaultSettings ++ Seq(
scalaVersion := "2.11.8",
libraryDependencies ++= Seq(
"com.typesafe.slick" %% "slick" % slickVersion,
"com.typesafe.slick" %% "slick-codegen" % slickVersion,
"mysql" % "mysql-connector-java" % "5.1.35",
"com.typesafe" % "config" % "1.3.1"
),
myConf := {
ConfigFactory.parseFile(new File("src/main/resources/application.conf"))
},
slick <<= slickCodeGenTask,
sourceGenerators in Compile <+= slickCodeGenTask
)
)
lazy val slick = TaskKey[Seq[File]]("gen-tables")
lazy val myConf = settingKey[Config]("The application properties")
lazy val slickCodeGenTask = (sourceManaged, dependencyClasspath in Compile, runner in Compile, streams) map {(dir, cp, r, s) =>
val outputDir = (dir / "slick").getPath
val username = myConf.value.getString("mysql.username")
val password = myConf.value.getString("mysql.password")
val port = myConf.value.getInt("mysql.port")
val db = myConf.value.getString("mysql.db")
val server = myConf.value.getString("mysql.server")
val url = s"jdbc:mysql://$server:$port/$db?username=$username&password=$password"
val jdbcDriver = myConf.value.getString("mysql.jdbcDriver")
val slickDriver = myConf.value.getString("mysql.slickDriver")
val pkg = "sql"
val fname = outputDir + "/db/Tables.scala"
toError(r.run("slick.codegen.SourceCodeGenerator", cp.files, Array(slickDriver, jdbcDriver, url, outputDir, pkg), s.log))
Seq(file(fname))
}
But it cannot resolve the Config and the ConfigFactory classes.
Declare a dependency on Typesafe Config in project/build.sbt:
libraryDependencies += "com.typesafe" % "config" % "1.3.1"
And define a setting holding your config file in build.sbt:
lazy val myConf = settingKey[Config]("The application properties")
myConf := {
ConfigFactory.parseFile(new File("src/main/resources/application.conf"))
}
Now you can use myConf.value.getString("xyz") to get hold of your configuration values in other tasks or settings.

Confused how to set up a multi-project sbt project

I'm using sbt .13 here.
I have this so far:
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appVersion = "1.0"
resolvers += "local maven" at "/Users/blankman/.m2/repository/"
val commonDependencies = Seq()
val modelDependencies = Seq(
"com.typesafe.slick" %% "slick" % "2.0.1",
"org.slf4j" % "slf4j-nop" % "1.6.4"
)
val serviceDependencies = Seq(
"com.typesafe.slick" %% "slick" % "2.0.1",
"org.slf4j" % "slf4j-nop" % "1.6.4"
)
val webDependencies = Seq(
//"org.apache.tomcat" % "tomcat-jdbc" % "8.0.3",
"mysql" % "mysql-connector-java" % "5.1.30",
"com.typesafe.slick" %% "slick" % "2.0.1"
)
lazy val common = Project(
id = "app-common",
base = file("app-common"),
dependencies = commonDependencies
)
lazy val models = Project(
id = "app-models",
base = file("app-models"),
settings(modelDependencies: _*)
)
).dependsOn(common)
lazy val services = Project(
id = "app-services",
base = file("app-services"),
settings = Seq(
libraryDependencies ++= serviceDependencies
)
).dependsOn(models, common)
lazy val web = play.Project("app-web", appVersion, webDependencies,
path = file("app-web"))
.settings(playScalaSettings: _*)
.dependsOn(services)
}
This doesn't work. For example, if I go into:
project app-models
and try and compile, it says compile isn't valid or something.
I'm really confused how to set up a project. What is the correct way?
Looking at this slide #10 here http://jsuereth.com/scala/2013/06/11/effective-sbt.html it says I can do:
lazy val web = (
Project("app-models", file("app-models"))
settings(
libraryDependencies += modelDependencies
)
)
But when I do this I get an error also.
I basically have a few projects inside of sbt:
common
models
services
web (which is play)
models depends on commons
services depends on commons + models
web depends on services
Can someone help me get this to work?
There are a few issues I found in your build definition, but since you bought up Josh's Effective sbt talk, I think we should go whole hog on the style.
Effective sbt
Here are the files.
project/build.properties
sbt.version=0.13.2
project/play.sbt
val playVersion = "2.2.2"
resolvers += Resolver.typesafeRepo("releases")
addSbtPlugin("com.typesafe.play" % "sbt-plugin" % playVersion)
project/commons.scala
import sbt._
import Keys._
object Commons {
val appVersion = "1.0"
val settings: Seq[Def.Setting[_]] = Seq(
version := appVersion,
resolvers += Opts.resolver.mavenLocalFile
)
}
project/dependencies.scala
import sbt._
import Keys._
object Dependencies {
val slickVersion = "2.0.1"
val slick = "com.typesafe.slick" %% "slick" % slickVersion
val slf4jVersion = "1.6.4"
val slf4jNop = "org.slf4j" % "slf4j-nop" % slf4jVersion
val mysqlConnectorVersion = "5.1.30"
val mysqlConnector = "mysql" % "mysql-connector-java" % mysqlConnectorVersion
val commonDependencies: Seq[ModuleID] = Seq(
slick,
slf4jNop
)
val modelDependencies: Seq[ModuleID] = Seq()
val serviceDependencies: Seq[ModuleID] = Seq()
val webDependencies: Seq[ModuleID] = Seq(
mysqlConnector
)
}
build.sbt
import play.Project._
import Dependencies._
lazy val appCommon = (project in file("app-common")).
settings(Commons.settings: _*).
settings(
libraryDependencies ++= commonDependencies
)
lazy val appModels = (project in file("app-models")).
settings(Commons.settings: _*).
settings(
libraryDependencies ++= modelDependencies
).
dependsOn(appCommon)
lazy val appServices = (project in file("app-services")).
settings(Commons.settings: _*).
settings(
libraryDependencies ++= serviceDependencies
).
dependsOn(appModels, appCommon)
lazy val appWeb = (project in file("app-web")).
settings(Commons.settings: _*).
settings(playScalaSettings: _*).
dependsOn(appServices)
notes
settings parameter vs settings method
For models and services, you're passing in settings sequence into Project(...) constructor, so the default settings are likely not loaded. You can pass in the default settings manually, or use settings(...) method on Project, which I would recommend.
lazy val appModels = (project in file("app-models")).
settings(
libraryDependencies ++= modelDependencies
).
dependsOn(appCommon)
Josh uses postfix notation using parenthesis, but I prefer using dot notation for this, so that's a slight deviation from the talk.
libraryDependencies ++=
As the above example, you have to pass modelDependencies to libraryDependencies. You had it calling directly into settings.
resolvers
The resolvers setting is not passed into anything, which likely is not correct.

Why does SBT compile just the last subproject?

I'm getting crazy, really :-(
Given the following SBT build file...
import sbt._
import sbt.Keys._
object BrixBuild extends Build {
lazy val buildSettings = Project.defaultSettings ++ Seq(
organization := "com.mycompany",
version := "0.1-SNAPSHOT",
scalaVersion := "2.10.0-RC3",
scalacOptions in Compile ++= Seq("-encoding", "UTF-8", "-deprecation", "-feature", "-unchecked"),
resolvers += Resolvers.typesafe,
target := file("target")
)
lazy val util = Project(
id = "brix-util",
base = file("brix-util"),
settings = buildSettings ++ Seq(
libraryDependencies ++= Dependencies.util
)
)
lazy val slick = Project(
id = "brix-slick",
base = file("brix-slick"),
settings = buildSettings ++ Seq(
libraryDependencies ++= Dependencies.slick
)
)
}
object Resolvers {
val typesafe = "Typesafe Releases" at "http://repo.typesafe.com/typesafe/releases"
}
object Dependencies {
private object Compile {
val commonsCodec = "commons-codec" % "commons-codec" % "1.7"
val slick = "com.typesafe" %% "slick" % "1.0.0-RC1"
}
private object Test {
val specs2 = "org.specs2" %% "specs2" % "1.12.3" % "test"
val slf4j = "org.slf4j" % "slf4j-nop" % "1.6.4" % "test"
val h2 = "com.h2database" % "h2" % "1.3.166" % "test"
}
val util = Seq(Compile.commonsCodec, Test.specs2, Test.slf4j)
val slick = Seq(Compile.slick, Test.specs2, Test.slf4j, Test.h2)
}
... only the last subproject get compiled. Why? Am I missing something?
Any help would be really appreciated. Tx.
You should define a "parent" project that aggregates the subprojects. For an example see https://github.com/typesafehub/scalalogging/blob/master/project/Build.scala.

How can I add jars from more than one unmanaged directory in an SBT .scala project configuration

I'm trying to get SBT to build a project that could have more than one unmanaged directory. If I had a single directory, I could easily do it like this:
unmanagedBase := file( "custom-libs" ).getAbsoluteFile
But since I have two directories with unmanaged jars, I need to be able to add them all. I have found some information in here, but still doesn't seem useful for my full .scala file build.
I have created a simple project that shows the issue in here. And below is my Build.scala file.
UPDATE
I've got some help form the sbt-users list and have been able to define the unmanaged-jars correctly, but the code still doesn't compile (but sbt show unmanaged-jars shows the files correctly).
import sbt._
import com.github.siasia._
import PluginKeys._
import Keys._
object Build extends sbt.Build {
import Dependencies._
val unmanagedListing = unmanagedJars := {
Dependencies.listUnmanaged( file(".").getAbsoluteFile )
}
lazy val myProject = Project("spray-template", file("."))
.settings(WebPlugin.webSettings: _*)
.settings(port in config("container") := 8080)
.settings(
organization := "com.example",
version := "0.9.0-RC1",
scalaVersion := "2.9.1",
scalacOptions := Seq("-deprecation", "-encoding", "utf8"),
resolvers ++= Dependencies.resolutionRepos,
libraryDependencies ++= Seq(
Compile.akkaActor,
Compile.sprayServer,
Test.specs2,
Container.jettyWebApp,
Container.akkaSlf4j,
Container.slf4j,
Container.logback
),
unmanagedListing
)
}
object Dependencies {
val resolutionRepos = Seq(
ScalaToolsSnapshots,
"Typesafe repo" at "http://repo.typesafe.com/typesafe/releases/",
"spray repo" at "http://repo.spray.cc/"
)
def listUnmanaged( base : RichFile ) : Keys.Classpath = {
val baseDirectories = (base / "custom-libs") +++ ( base / "custom-libs2" )
(baseDirectories ** "*.jar").classpath
}
object V {
val akka = "1.3"
val spray = "0.9.0-RC1"
val specs2 = "1.7.1"
val jetty = "8.1.0.v20120127"
val slf4j = "1.6.4"
val logback = "1.0.0"
}
object Compile {
val akkaActor = "se.scalablesolutions.akka" % "akka-actor" % V.akka % "compile"
val sprayServer = "cc.spray" % "spray-server" % V.spray % "compile"
}
object Test {
val specs2 = "org.specs2" %% "specs2" % V.specs2 % "test"
}
object Container {
val jettyWebApp = "org.eclipse.jetty" % "jetty-webapp" % V.jetty % "container"
val akkaSlf4j = "se.scalablesolutions.akka" % "akka-slf4j" % V.akka
val slf4j = "org.slf4j" % "slf4j-api" % V.slf4j
val logback = "ch.qos.logback" % "logback-classic" % V.logback
}
}
I just post the fragment from my build.sbt file, using sbt 0.11.x. It could probably be refactored a bit.
unmanagedJars in Compile <++= baseDirectory map { base =>
val libs = base / "lib"
val dirs = (libs / "batik") +++ (libs / "libtw") +++ (libs / "kiama")
(dirs ** "*.jar").classpath
}
You can add additional paths to the list of folders to scan for unmanaged dependencies. For example, to look in a folder called "config" in addition to "lib" for the run task, you can add the following. For the compile task change Runtime to Compile.
unmanagedClasspath in Runtime <+= (baseDirectory) map {
bd => Attributed.blank(bd / "config")
}
As answered by Eugene Vigdorchik, what made it work as the following code:
import sbt._
import com.github.siasia._
import PluginKeys._
import Keys._
object Build extends sbt.Build {
import Dependencies._
var unmanagedListing = unmanagedJars in Compile := {
Dependencies.listUnmanaged( file(".").getAbsoluteFile )
}
lazy val myProject = Project("spray-template", file("."))
.settings(WebPlugin.webSettings: _*)
.settings(port in config("container") := 8080)
.settings(
organization := "com.example",
version := "0.9.0-RC1",
scalaVersion := "2.9.1",
scalacOptions := Seq("-deprecation", "-encoding", "utf8"),
resolvers ++= Dependencies.resolutionRepos,
libraryDependencies ++= Seq(
C.akkaActor,
C.sprayServer,
Test.specs2,
Container.jettyWebApp,
Container.akkaSlf4j,
Container.slf4j,
Container.logback
),
unmanagedListing
)
}
object Dependencies {
val resolutionRepos = Seq(
ScalaToolsSnapshots,
"Typesafe repo" at "http://repo.typesafe.com/typesafe/releases/",
"spray repo" at "http://repo.spray.cc/"
)
def listUnmanaged( base : RichFile ) : Keys.Classpath = {
val baseDirectories = (base / "custom-libs") +++ ( base / "custom-libs2" )
(baseDirectories ** "*.jar").classpath
}
object V {
val akka = "1.3"
val spray = "0.9.0-RC1"
val specs2 = "1.7.1"
val jetty = "8.1.0.v20120127"
val slf4j = "1.6.4"
val logback = "1.0.0"
}
object C {
val akkaActor = "se.scalablesolutions.akka" % "akka-actor" % V.akka % "compile"
val sprayServer = "cc.spray" % "spray-server" % V.spray % "compile"
}
object Test {
val specs2 = "org.specs2" %% "specs2" % V.specs2 % "test"
}
object Container {
val jettyWebApp = "org.eclipse.jetty" % "jetty-webapp" % V.jetty % "container"
val akkaSlf4j = "se.scalablesolutions.akka" % "akka-slf4j" % V.akka
val slf4j = "org.slf4j" % "slf4j-api" % V.slf4j
val logback = "ch.qos.logback" % "logback-classic" % V.logback
}
}
Source repo with the full example available on Github.
Here's a general solution to recursive loading of unmanaged JARs (for sbt 0.13.x): https://stackoverflow.com/a/29357699/1348306