Sbt插件在其他任务之前/之后运行任务

时间:2018-11-14 19:56:49

标签: scala sbt

我知道,我看到了Run custom task automatically before/after standard task,但似乎已经过时了。我还发现了SBT before/after hooks for a task,但没有任何代码示例。

我在SBT 0.13.17上。

MyBeforeTask说,所以我想在其他任务之后自动运行任务MyAfterTaskCompile

因此,当您执行sbt compile时,我希望看到:

...log...
This is my before test text
...compile log...
This is my after test text

所以我需要具备:

object MyPlugin extends AutoPlugin {
  object autoImport {
     val MyBeforeTask = taskKey[Unit]("desc...")
     val MyAfterTask = taskKey[Unit]("desc...")
  }

  import autoImport._

  override def projectSettings: Seq[Def.Setting[_]] = {
     MyBeforeTask := {
       println("This is my before test text")
     },
     MyAfterTask := {
       println("This is my after test text")
     }
  }
}

所以我认为我需要dependsOnin之类的东西,但是我不确定如何设置它们。

1 个答案:

答案 0 :(得分:1)

不可能配置特定任务在给定任务之后运行 ,因为这不是任务依赖关系模型的工作方式-当您指定任务时,其依赖关系及其自身将被执行,但无法定义“之后”依赖项。但是,您可以使用动态任务来模拟它。

要先执行某些任务,可以使用dependsOn

compile in Compile := (compile in Compile).dependsOn(myBeforeTask).value

这将在两个任务之间建立依赖关系,从而确保myBeforeTask将在compile in Compile之前运行。


请注意,还有一种通用的方法可以使多个任务依次运行:

aggregateTask := Def.sequential(task1, task2, task3, task4).value

Def.sequential依赖于动态任务机制,该机制在运行时设置任务之间的依赖关系。但是,此机制有一些限制,特别是,您无法引用要执行的任务列表中定义的任务,因此无法使用Def.sequential来扩展现有任务:

compile in Compile := Def.sequential(myBeforeTask, compile in Compile).value

此定义将在运行时失败,并显示一条奇怪的错误消息,这基本上意味着您的任务依赖关系图中有一个循环。但是,对于某些用例,它非常有用。


要在另一个任务之后 运行某些任务,您必须诉诸使用Def.taskDyn定义动态任务依赖项:

compile in Compile := Def.taskDyn {
  val result = (compile in Compile).value
  Def.task {
    val _ = myAfterTask.value
    result
  }
}.value

Def.taskDyn接受一个必须返回Def.Initialize[Task[T]]的块,该块将用于实例化在Def.taskDyn主体完成后要稍后运行的任务。这允许人们动态地计算任务,并在运行时建立任务之间的依赖关系。但是,如上所述,这可能会导致在运行时发生非常奇怪的错误,这些错误通常是由依赖关系图中的循环引起的。

因此,带有“ before”和“ after”任务的完整示例如下所示:

compile in Compile := Def.taskDyn {
  val result = (compile in Compile).value
  Def.task {
    val _ = myAfterTask.value
    result
  }
}.dependsOn(myBeforeTask).value