sbt插件与使用插件本身的多项目构建中的项目之间交织在一起的依赖关系

时间:2016-05-24 21:50:21

标签: scala plugins sbt

我正在开发一个包含sbt插件的库。当然,我正在使用sbt来构建这个(多项目)库。我的(简化)项目如下所示:

myProject/                        # Top level of library
  -> models                       # One project in the multi-project sbt build.
      -> src/main/scala/...       # Defines common models for both sbt-plugin and framework
  -> sbt-plugin                   # The sbt plugin build
      -> src/main/scala/...
  -> framework                    # The framework. Ideally, the sbt plugin is run as part of 
      -> src/main/scala/...       # compiling this directory.
  -> project/                     # Multi-project build configuration

有没有办法让myProject / sbt-plugin中定义的sbt-plugin在统一版本中挂钩到myProject / framework的构建中?

注意:类似(但更简单)的问题:How to develop sbt plugin in multi-project build with projects that use it?

1 个答案:

答案 0 :(得分:7)

  

有没有办法让myProject / sbt-plugin中定义的sbt-plugin在统一版本中挂钩到myProject / framework的构建中?

我在Github eed3si9n/plugin-bootstrap上有一个工作示例。它不是很漂亮,但有点有用。我们可以利用sbt is recursive

这一事实
  

project目录是构建中的另一个构建,它知道如何构建构建。为了区分构建,我们有时使用术语正确构建来引用您的构建,并使用元构建来引用project中的构建。 metabuild中的项目可以执行任何其他项目可以执行的任何操作。 您的构建定义是一个sbt项目。

通过扩展,我们可以认为sbt插件是元库的根项目的库或项目间依赖项。

元构建定义(project/plugins.sbt

在此示例中,将metabuild视为具有并行多构建结构的并行Universe或阴影世界,作为正确的构建(rootmodelsbt-plugin)。< / p>

要在正确版本中重用modelsbt-plugin子项目中的源代码,我们可以在元构建中重新创建多项目构建。这样我们就不需要进入循环依赖。

addSbtPlugin("com.eed3si9n" % "sbt-doge" % "0.1.5")

lazy val metaroot = (project in file(".")).
  dependsOn(metaSbtSomething)

lazy val metaModel = (project in file("model")).
  settings(
    sbtPlugin := true,
    scalaVersion := "2.10.6",
    unmanagedSourceDirectories in Compile :=
      mirrorScalaSource((baseDirectory in ThisBuild).value.getParentFile / "model")
  )

lazy val metaSbtSomething = (project in file("sbt-plugin")).
  dependsOn(metaModel).
  settings(
    sbtPlugin := true,
    scalaVersion := "2.10.6",
    unmanagedSourceDirectories in Compile :=
      mirrorScalaSource((baseDirectory in ThisBuild).value.getParentFile / "sbt-plugin")
  )

def mirrorScalaSource(baseDirectory: File): Seq[File] = {
  val scalaSourceDir = baseDirectory / "src" / "main" / "scala"
  if (scalaSourceDir.exists) scalaSourceDir :: Nil
  else sys.error(s"Missing source directory: $scalaSourceDir")
}

当sbt加载时,它会首先构建metaModelmetaSbtSomething,并使用metaSbtSomething作为正确版本的插件。

如果您还有其他任何插件,只需添加project/plugins.sbt,就可以将其添加到sbt-doge

正确构建(build.sbt)

正确的构建看起来像普通的多项目构建。 如您所见,framework子项目使用SomethingPlugin。重要的是它们共享源代码,但target目录是完全分开的,因此一旦加载了正确的构建版本就没有干扰,并且您正在更改代码。

import Dependencies._

lazy val root = (project in file(".")).
  aggregate(model, framework, sbtSomething).
  settings(inThisBuild(List(
      scalaVersion := scala210,
      organization := "com.example"
    )),
    name := "Something Root"
  )

// Defines common models for both sbt-plugin and framework
lazy val model = (project in file("model")).
  settings(
    name := "Something Model",
    crossScalaVersions := Seq(scala211, scala210)
  )

// The framework. Ideally, the sbt plugin is run as part of building this.
lazy val framework = (project in file("framework")).
  enablePlugins(SomethingPlugin).
  dependsOn(model).
  settings(
    name := "Something Framework",
    crossScalaVersions := Seq(scala211, scala210),
    // using sbt-something
    somethingX := "a"
  )

lazy val sbtSomething = (project in file("sbt-plugin")).
  dependsOn(model).
  settings(
    sbtPlugin := true,
    name := "sbt-something",
    crossScalaVersions := Seq(scala210)
  )

演示

SomethingPlugin示例中,我定义了使用something的{​​{1}}任务。

foo.Model.x

以下是我们如何从构建中调用package foo import sbt._ object SomethingPlugin extends AutoPlugin { def requries = sbt.plugins.JvmPlugin object autoImport { lazy val something = taskKey[Unit]("") lazy val somethingX = settingKey[String]("") } import autoImport._ override def projectSettings = Seq( something := { println(s"something! ${Model.x}") } ) } 任务:

something

Something Root> framework/something something! 1 [success] Total time: 0 s, completed May 29, 2016 3:01:07 PM 来自1,因此这表明我们正在使用foo.Model.x子项目中的sbt-something插件,并且该插件正在使用framework