1

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?

Markus Appel
  • 3,138
  • 1
  • 17
  • 46

1 Answers1

2

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

Ivan Stanislavciuc
  • 7,140
  • 15
  • 18
  • Ah thank you. What happens when I call `build` in root project without using `aggregate`? The `taskKey` is already defined, but it's behaviour is not... (?) – Markus Appel Jan 28 '19 at 10:35
  • It will say something like `[error] Not a valid command: build` – Ivan Stanislavciuc Jan 28 '19 at 12:34
  • 1
    You should use `Def.sequential` to run tasks one after another. Check https://www.scala-sbt.org/release/docs/Howto-Sequential-Task.html – laughedelic Jan 28 '19 at 13:55
  • @IvanStanislavciuc so I tried this approach but I can still call `build` at root level... It fails horribly once it comes across undefined commands but still... – Markus Appel Jan 28 '19 at 18:25