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

时间:2014-02-02 01:55:13

标签: sbt

编辑:

由于我提出了赏金,我认为我应该重申这个问题

  
    

具有两个子项目PA的SBT项目B如何设置B以使A具有插件依赖项,这是一个SBT插件?

         
        
  • P提供A插件依赖项不起作用,因为A取决于P中的其他内容,这会产生循环依赖关系图
  •     
  • 它必须是插件依赖项,因为A是运行B测试套件所需的插件。
  •     
  • dependsOn不起作用,因为它必须是插件依赖
  •     
         

我想知道

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

编辑:澄清它是一个插件依赖,因为构建依赖是模糊的

4 个答案:

答案 0 :(得分:12)

当你有一个带有“项目P和两个子项目A和B”的多项目构建配置时,它归结为以下配置:

<强> build.sbt

lazy val A, B = project

根据设计,"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."这意味着你将有一个隐含的根项目,比如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项目中定义插件的唯一方法是使用project项目的构建定义的plugins目录 - "A plugin definition is a project in <main-project>/project/."这意味着定义插件依赖项的唯一方法在项目A上使用以下内容:

<强>项目/ 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(...)
}

目录build.sbt中的两个文件 - MyPlugin.scalaA - 组成了插件项目。

唯一缺少的是为项目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

答案 1 :(得分:1)

As Jacek said,它不能按照我的意愿完成,因为子项目不能有根项目没有的SBT插件。另一方面,this discussion on the mailing list包含多个替代方案,对于将来遇到此问题的任何人都无疑会有用。

编辑:嗯,最后提到的替代品(sbt脚本等)使用起来很困难而且很笨重。我的最终解决方案是在repo中有一个独立的项目( not 子项目),它依赖于原始项目的常春藤坐标,并使用bash来发布第一个项目的本地项目,进入第二个项目,运行测试

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

我一直认为像SBT这样的东西是为了避免做这种bash体操,但是绝望的时候需要采取绝望的措施......

答案 2 :(得分:0)

此答案可能包含解决方案https://stackoverflow.com/a/12754868/3189923

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

答案 3 :(得分:0)

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

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