Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining plugin dependency between subprojects in SBT?

Tags:

sbt

EDIT:

Since I put up the bounty, I thought I should restate the question

How can a SBT project P, with two sub-projects A and B, set up B to have a plugin dependency on A, which is a SBT plugin?

  • Giving P a plugin dependency on A does not work, since A depends on other things in P, which results in a circular dependency graph
  • It has to be a plugin dependency, for A is a plugin needed to run Bs test suite.
  • dependsOn doesn't work, because, well, it has to be a plugin dependency

I'd like to know either of

  • How to do this, or
  • Why this is impossible, and what the next best alternatives are.

EDIT: clarified that it's a plugin-dependency, since build-dependency is ambiguous

like image 266
Li Haoyi Avatar asked Feb 02 '14 01:02

Li Haoyi


1 Answers

When you have a multi-project build configuration with "project P and two sub-projects A and B" it boils down to the following configuration:

build.sbt

lazy val A, B = project

As per design, "If a project is not defined for the root directory in the build, sbt creates a default one that aggregates all other projects in the build." It means that you will have an implicit root project, say P (but the name is arbitrary):

[plugin-project-and-another]> projects
[info] In file:/Users/jacek/sandbox/so/plugin-project-and-another/
[info]     A
[info]     B
[info]   * plugin-project-and-another

That gives us the expected project structure. On to defining plugin dependency between B and A.

The only way to define a plugin in a SBT project is to use project directory that's the plugins project's build definition - "A plugin definition is a project in <main-project>/project/." It means that the only way to define a plugin dependency on the project A is to use the following:

project/plugins.sbt

addSbtPlugin("org.example" % "example-plugin" % "1.0")

lazy val plugins = project in file(".") dependsOn(file("../A"))

In this build configuration, the plugins project depends on another SBT project that happens to be our A that's in turn a plugin project.

A/build.sbt

// http://www.scala-sbt.org/release/docs/Extending/Plugins.html#example-plugin
sbtPlugin := true

name := "example-plugin"

organization := "org.example"

version := "1.0"

A/MyPlugin.scala

import sbt._

object MyPlugin extends Plugin
{
    // configuration points, like the built in `version`, `libraryDependencies`, or `compile`
    // by implementing Plugin, these are automatically imported in a user's `build.sbt`
    val newTask = taskKey[Unit]("A new task.")
    val newSetting = settingKey[String]("A new setting.")

    // a group of settings ready to be added to a Project
    // to automatically add them, do
    val newSettings = Seq(
        newSetting := "Hello from plugin",
        newTask := println(newSetting.value)
    )

    // alternatively, by overriding `settings`, they could be automatically added to a Project
    // override val settings = Seq(...)
}

The two files - build.sbt and MyPlugin.scala in the directory A - make up the plugin project.

The only missing piece is to define the plugin A's settings for the project B.

B/build.sbt

MyPlugin.newSettings

That's pretty much it what you can do in SBT. If you want to have multi-project build configuration and have a plugin dependency between (sub)projects, you don't have much choice other than what described above.

With that said, let's see if the plugin from the project A is accessible.

[plugin-project-and-another]> newTask
Hello from plugin
[success] Total time: 0 s, completed Feb 13, 2014 2:29:31 AM
[plugin-project-and-another]> B/newTask
Hello from plugin
[success] Total time: 0 s, completed Feb 13, 2014 2:29:36 AM
[plugin-project-and-another]> A/newTask
[error] No such setting/task
[error] A/newTask
[error]          ^

As you may have noticed, newTask (that comes from the plugin from the project A) is available in the (default) root project and the project B, but not in A.

like image 64
Jacek Laskowski Avatar answered Oct 23 '22 08:10

Jacek Laskowski