我正在开发一个包含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
Run Code Online (Sandbox Code Playgroud)
有没有办法让myProject/sbt-plugin中定义的sbt-plugin在统一版本中挂钩到myProject/framework的构建中?
注意:类似(但更简单)的问题:如何使用使用它的项目在多项目构建中开发sbt插件?
有没有办法让myProject/sbt-plugin中定义的sbt-plugin在统一版本中挂钩到myProject/framework的构建中?
我在Github eed3si9n/plugin-bootstrap上有一个工作示例.它不是很漂亮,但有点有用.我们可以利用sbt是递归的这一事实.
该
project目录是构建中的另一个构建,它知道如何构建构建.为了区分构建,我们有时使用术语正确构建来引用您的构建,并使用元构建来引用构建project.metabuild中的项目可以执行任何其他项目可以执行的任何操作.您的构建定义是一个sbt项目.
通过扩展,我们可以将sbt插件视为元库的根项目的库或项目间依赖项.
project/plugins.sbt)在此实例中,认为元软件包作为并行宇宙或阴影世界具有并行多构建结构作为正确构建(的root,model,sbt-plugin).
要在正确的构建中重用源代码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")
}
Run Code Online (Sandbox Code Playgroud)
当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)
)
Run Code Online (Sandbox Code Playgroud)
在SomethingPlugin示例中,我正在定义something使用的任务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}") }
)
}
Run Code Online (Sandbox Code Playgroud)
以下是我们如何something从构建中调用任务:
Something Root> framework/something
something! 1
[success] Total time: 0 s, completed May 29, 2016 3:01:07 PM
Run Code Online (Sandbox Code Playgroud)
1来自foo.Model.x,所以这表明我们在framework子项目中使用sbt-something插件,并且该插件正在使用metaModel.