Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 458
Denis Rosca Avatar asked Dec 07 '13 15:12

Denis Rosca


2 Answers

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(...)
like image 61
Dmitry Golubets Avatar answered Sep 21 '22 19:09

Dmitry Golubets


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.

like image 20
Jacek Laskowski Avatar answered Sep 23 '22 19:09

Jacek Laskowski