在 SBT 中定义子项目之间的插件依赖关系?



编辑:

既然我提出了赏金,我想我应该重申这个问题

一个SBT项目如何P,有两个子项目AB,设置B有一个插件依赖于A,这是一个SBT插件?

  • P一个插件对A的依赖是行不通的,因为A依赖于P中的其他东西,这会导致循环依赖图
  • 它必须是一个插件依赖项,因为A是运行B测试套件所需的插件。
  • dependsOn不起作用,因为,好吧,它必须是一个插件依赖项

我想知道其中任何一个

  • 如何执行此操作,或
  • 为什么这是不可能的,以及下一个最佳选择是什么。

编辑:澄清这是一个插件依赖,因为构建依赖是模棱两可的

当您有一个包含"项目 P 和两个子项目 A 和 B">的多项目构建配置时,它归结为以下配置:

build.sbt

lazy val A, B = project

根据设计,"如果未为构建中的根目录定义项目,则 sbt 会创建一个默认项目,用于聚合构建中的所有其他项目。这意味着您将拥有一个隐式根项目,例如P(但名称是任意的):

[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

这为我们提供了预期的项目结构。关于定义BA之间的插件依赖关系。

在 SBT 项目中定义插件的唯一方法是使用plugins项目的构建定义project目录 - "插件定义是/project/中的一个项目。这意味着在项目A上定义插件依赖项的唯一方法是使用以下方法:

project/plugins.sbt

addSbtPlugin("org.example" % "example-plugin" % "1.0")
lazy val plugins = project in file(".") dependsOn(file("../A"))

在此构建配置中,plugins项目依赖于另一个 SBT 项目,该项目恰好是我们A而另一个项目又是一个插件项目。

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(...)
}

目录A中的build.sbtMyPlugin.scala这两个文件构成了插件项目。

唯一缺少的部分是定义插件A的项目B设置。

B/build.sbt

MyPlugin.newSettings

这几乎就是你在SBT中可以做的事情。如果你想拥有多项目构建配置,并且在(子)项目之间有一个插件依赖关系,除了上面描述的之外,你没有太多选择。

话虽如此,让我们看看项目A中的插件是否可以访问。

[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]          ^

您可能已经注意到,newTask(来自项目A的插件)在(默认)根项目和项目B中可用,但在A中不可用。

正如 Jacek 所说,它不能按照我的意愿完成,因为子项目不能有根项目没有的 SBT 插件。另一方面,邮件列表上的讨论包含几种替代方案,无疑对将来遇到此问题的任何人都有用。

编辑:好吧,最后提到的替代方案(sbt脚本等)很难使用。我的最终解决方案是在存储库中有一个单独的项目(不是子项目),该项目通过它的常春藤坐标依赖于原始项目,并使用 bash 发布第一个项目,进入第二个项目并运行其测试

sbt publishLocal; cd test; sbt test; cd ..

我一直以为像SBT这样的事情的目的是避免做这种猛击体操,但绝望的时刻需要绝望的措施......

这个答案可能包括解决方案 https://stackoverflow.com/a/12754868/3189923。

简而言之,从该链接设置exportJars := true并获取(子)项目exportedProducts in Compile的 jar 文件路径。

抛开插件的事实,你有一个父项目 P,其中包含子项目 A 和 B。然后你说 A 取决于 P。但 P 是 A 和 B 的集合,因此依赖于 A。所以你已经有一个循环依赖在 A 和 P 之间。这永远行不通。

你必须将P分成两部分:A依赖的部分(我们称之为A部分)和其余部分(我们称之为P_rest)。然后你扔掉P,做一个由A'、A和B组成的新项目P_rest。而 A 取决于 A'。

最新更新