Markus Appel
Markus Appel

Reputation: 3238

Per-project tasks in SBT

My .sbt file looks something like this:

lazy val common = (project in file("./common"))
  .settings(
    // other settings
  )
lazy val one = (project in file("./one"))
  .dependsOn(common)
  .settings(
    // other settings
    addCommandAlias("build", ";clean;assembly;foo")
  )
lazy val two = (project in file("./two"))
  .dependsOn(common)
  .settings(
    // other settings
    addCommandAlias("build", ";clean;compile;bar")
  )

Additionally I have two tasks foo and bar which are only valid in their respective projects.

My tests show that upon calling build - no matter which project I am in - both aliases are being called.

And for tasks, the keys can already be only defined at top-level of the .sbt file (e.g. val foo = taskKey[Unit]("Does foo")).

I want to know how to correctly implement tasks and command aliases on project level.

Is that possible?

Upvotes: 2

Views: 463

Answers (1)

Ivan Stanislavciuc
Ivan Stanislavciuc

Reputation: 7275

The problem you are having is with alias in sbt. When an alias is defined, it is attached to scope GlobalScope in the form of a command and therefore available for all sub-projects. When you do multiple definitions of aliases with addCommandAlias, the last execution wins as every executions removes previously created alias with the same name.

You can see the defined alias by running sbt alias and it will print that there is only one build alias.

You could achieve separations of build by introducing it as a taskKey

lazy val build = taskKey[Unit]("Builds")

lazy val root = (project in file("."))
  .aggregate(one, two) // THIS IS NEED TO MAKE build TASK AVAILABLE IN ROOT

lazy val common = (project in file("./common"))
  .settings(
    //SOME KEYS
  )

lazy val one = (project in file("./one"))
  .dependsOn(common)
  .settings(
    build := {
      Def.sequential(clean, Compile / compile).value
    }
  )

lazy val two = (project in file("./two"))
  .dependsOn(common)
  .settings(
    build := {
      Def.sequential(clean, assembly).value
    }
  )

EDIT: Added Def.sequential as suggested by @laughedelic in the comments

Upvotes: 2

Related Questions