I'm trying to create a multi-project SBT build definition. I'm having trouble executing the run
command on my root project.
The folder structure is the following:
RootProjectFolder
|
|- build.sbt
|- project
|
|-Build.scala
|-plugins.sbt
|
| - play-webapp
The contents of the Build.scala
file is:
import sbt._
import Keys._
import play.Project._
object ApplicationBuild extends Build {
val appName = "project-name"
val appVersion = "0.1.0-SNAPSHOT"
lazy val root = Project(id = appName + "-root",
base = file(".")
).aggregate(webApp)
lazy val webApp = play.Project(
appName + "-website", appVersion, path = file("play-webapp")
)
}
When I launch SBT I get the following message: Set current project to project-name-root
which implies that the root project was detected correctly.
When I execute the run
command I get the following error message
> run
java.lang.RuntimeException: No main class detected.
at scala.sys.package$.error(package.scala:27)
[trace] Stack trace suppressed: run last project-name-root/compile:run for the full output.
[error] (project-name-root/compile:run) No main class detected.
The error message is correct in saying that the root project does not have any classes, but the play-webapp project has. I assumed that the result would be to run the play app.
If I type project play-webapp
before run
everything seems to be ok.
Is this the correct behavior? Or am I doing something wrong?
P.S. I'm using SBT version 0.13 and scala version 2.10.3
Another way is to redefine run:
lazy val root = Project("root", file("."))
.aggregate(subproject)
.settings(
run := {
(run in subproject in Compile).evaluated
}
)
lazy val subproject = Project(...)
I really wish I could explain it better, but it's only after lots of trial and error I have managed to find an answer. Expect a better explanation once I've learnt more.
tl;dr Add the following to RootProjectFolder/build.sbt
(in 0.13
build.sbt
can define multi-project setup):
mainClass in `project-name-root` in Compile := (mainClass in `play-webapp` in Compile).value
fullClasspath in `project-name-root` in Runtime ++= (fullClasspath in `play-webapp` in Runtime).value
Longer explanation (not necessarily complete and correct so use on your own risk).
I assume your multi-project configuration is as follows - run projects
in the sbt shell.
[project-name-root]> projects
[info] In file:/Users/jacek/sandbox/stackoverflow/sbt-run/
[info] play-webapp
[info] * project-name-root
Change the project names below when required.
When you execute inspect run
in sbt shell you'll notice that the run
task depends on project-name-root/runtime:fullClasspath
and project-name-root/compile:run::mainClass
settings.
[project-name-root]> inspect run
[info] Input task: Unit
[info] Description:
[info] Runs a main class, passing along arguments provided on the command line.
[info] Provided by:
[info] {file:/Users/jacek/sandbox/stackoverflow/sbt-run/}project-name-root/compile:run
[info] Defined at:
[info] (sbt.Defaults) Defaults.scala:688
[info] Dependencies:
[info] project-name-root/compile:run::streams
[info] project-name-root/runtime:fullClasspath
[info] project-name-root/compile:run::runner
[info] project-name-root/compile:run::mainClass
[info] Delegates:
[info] project-name-root/compile:run
[info] project-name-root/*:run
[info] {.}/compile:run
[info] {.}/*:run
[info] */compile:run
[info] */*:run
[info] Related:
[info] project-name-root/test:run
[info] sub/compile:run
[info] sub/test:run
Since I knew how to change the settings with the value of the sub project's settings, I used the :=
method for the value of the root project. It works fine, but am quite certain there are better ways to achieve it. I can't wait to find them out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With