【问题标题】:Sbt plugin run tasks before / after an other taskSbt 插件在其他任务之前/之后运行任务
【发布时间】:2019-04-17 20:56:56
【问题描述】:

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

我在SBT 0.13.17

所以我想在其他任务之后自动运行我的任务 MyBeforeTaskMyAfterTaskCompile 说。

所以当你做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 这样的东西,但我不知道如何设置它们。

【问题讨论】:

    标签: scala sbt


    【解决方案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 的主体完成后实例化稍后运行的任务。这允许动态计算任务,并在运行时建立任务之间的依赖关系。然而,正如我上面所说,这可能会导致在运行时发生非常奇怪的错误,这通常是由依赖图中的循环引起的。

    因此,包含“之前”和“之后”任务的完整示例将如下所示:

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

    【讨论】:

    • compile in Compile := {val r = (compile in Compile).value ; /* run after? */ ; r } 这样的事情怎么样?抱歉不能在 cmets 中真正做多行:/
    • @Wonay,是的,确实,这会起作用 - 它会在您的代码之前运行原始编译任务。但是,这不允许您将“追赶”任务表达为真正的任务。话虽如此,也许您可​​以通过仔细的Def.taskDyn 应用程序来模拟这一点,动态任务会引入所有潜在问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-03
    • 1970-01-01
    • 1970-01-01
    • 2011-12-10
    • 2015-01-18
    相关资源
    最近更新 更多