How to (re)define run on root project to launch aggregated Play (sub)project in sbt 0.13

playframework-2.2, sbt, scala

Solution

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.

Problem

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

Original source