bearrito
bearrito

Reputation: 2315

Why can't sbt find my custom command with build.scala build definition?

Why does sbt not able to find a command in a multiproject build?

My plugin resembles

object MyPlugin extends Plugin {

    lazy val plug = Seq( commands ++= Seq(versionWriteSnapshotRelease) )

     def versionWriteSnapshotRelease = Command.command(
         "versionWriteSnapshotRelease",
         "Writes the release format of the snapshot version. This is used to preserve the actual snapshot version in a release commit.",
         ""
     ) { state =>  .... }
}

I have my project/Build.scala file as follows:

lazy val app = Project(id = "app-subproject", base = file("app"))
    .settings(MyPlug.plug :_*)
    .settings(...)

lazy val common = Project(id = "library-subproject", base = file("common"))
    .settings(MyPlug.plug :_*)
    .settings(...)

With files laid out like

root
|_ common
    |_ src
|_ app
    |_ src

This configurations fails with the error:

[error] Not a valid command: versionWriteSnapshotRelease
[error] Not a valid project ID: versionWriteSnapshotRelease
[error] Expected ':' (if selecting a configuration)
[error] Not a valid key: versionWriteSnapshotRelease (similar: version, ...)
[error] versionWriteSnapshotRelease

However if I restructure to something like

lazy val app = Project(id = "app-subproject", base = file("."))
    .settings(MyPlug.plug :_*)
    .settings(...)

lazy val common = Project(id = "library-subproject", base = file("common"))
    .settings(MyPlug.plug :_*)
    .settings(...)

With files laid out like

root
|_ common
    |_ src
|_ src

Then it works. Note that my change is to put the app project /src in the basedir and set the app project to have base ".".

This plugin is used across multiple projects and has no issue when the file layout is in the second form. So I know it isn't an issue with the plugin per-se.

Upvotes: 1

Views: 851

Answers (1)

Jacek Laskowski
Jacek Laskowski

Reputation: 74669

The reason for the error is that you define two submodules common and app with the third default root project without the command set.

You should add yet another definition of a project for the default root project so the command is also defined for it as follows:

lazy val root = Project(id = "root", base = file("."))
    .settings(MyPlug.plug :_*)
    .settings(...)

You've confirmed that thinking with your test when you turned app into the default root project.

As an additional check before you add the third module definition, do projects and see what projects are defined. For every project in the list, execute [projectName]/versionWriteSnapshotRelease. I'm sure it's going to be fine for app and common, but not for the default root module.

Upvotes: 1

Related Questions