我正在开发一个包含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?
答案 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或阴影世界,作为正确的构建(root
,model
,sbt-plugin
)。< / p>
要在正确版本中重用model
和sbt-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加载时,它会首先构建metaModel
和metaSbtSomething
,并使用metaSbtSomething
作为正确版本的插件。
如果您还有其他任何插件,只需添加project/plugins.sbt
,就可以将其添加到sbt-doge
。
正确的构建看起来像普通的多项目构建。
如您所见,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
。