在标准任务之前/之后自动运行自定义任务

Posted

技术标签:

【中文标题】在标准任务之前/之后自动运行自定义任务【英文标题】:Run custom task automatically before/after standard task 【发布时间】:2011-12-10 21:06:37 【问题描述】:

我经常想在运行其中一项标准任务之前进行一些自定义。我意识到我可以按照我想要的顺序创建执行现有任务的新任务,但是我发现这很麻烦,并且开发人员错过了他应该运行 my-compile 而不是 compile 的机会很大并且导致难以修复错误.

所以我想定义一个自定义任务(例如 prepare-app)并将其注入现有任务的依赖关系树(例如 package-bin),以便每次有人调用 package-bin 我的自定义任务都会在它之前运行。

我试过这样做

  def mySettings = 
    inConfig(Compile)(Seq(prepareAppTask <<= packageBin in Compile map  (pkg: File) =>
      // fiddle with the /target folder before package-bin makes it into a jar
    )) ++
    Seq(name := "my project", version := "1.0")
  

  lazy val prepareAppTask = TaskKey[Unit]("prepare-app")

但它不会在将编译输出打包到 jar 之前由 package-bin 自动执行。那么如何更改上述代码以在正确的时间运行?

更一般地说,我在哪里可以找到有关挂钩到其他任务(如编译)的信息,是否有一种通用方法可以确保在调用标准任务之前和之后运行您自己的任务?

【问题讨论】:

***.com/q/12360974/1305344 的可能重复项。绝对需要合并。 【参考方案1】:

Tasks 的 SBT 文档记录了扩展现有任务(请参阅 Modifying an Existing Task 部分)。

类似这样的:

compile in Compile <<= (compile in Compile) map  _ => 
  // what you want to happen after compile goes here 

其实还有另一种方式——定义你的任务依赖于编译

prepareAppTask := (whatever you want to do) dependsOn compile

然后修改 packageBin 以依赖它:

packageBin <<= packageBin dependsOn prepareAppTask

(以上所有内容都未经测试,但我希望一般的推力应该有效)。

【讨论】:

感谢我尝试执行此操作的链接,但如何使其工作并不明显。我需要两件事。我需要在编译运行后定义一个新任务来完成我的自定义工作,并且我需要从 Compile 修改 package-bin 以依赖于这个自定义任务(即我的任务管道应该是 compile -> my-task -> package-bin )。 不,您不需要 - 您需要将新任务的代码添加到重新定义的编译任务中,该任务取决于先前的编译任务。我会看看我是否可以拼凑一个例子并将其添加到我的答案中...... 像魅力一样工作也很好,您的答案显示了解决此问题的两种方法(在现有任务之后或之前运行某些东西)。谢谢! 这对于插入任意动作是正确的。但是,该动作通常不是任意的。根据您想做什么,您在excluding classes from the jar 上的其他问题的答案也可能适用于此处。 啊 - 自从我写下这个答案以来,SBT 似乎有所进步。 &lt;&lt;= 运算符曾经是您做事的方式,但正如您所说,它不再出现在文档中。恐怕我已经离开 Scala 世界一段时间了,我不确定如何最好地将这个答案更新为新的事物。【参考方案2】:

作为@Paul Butcher 先前回答的更新,这可以在 SBT 1.x 版本中以稍微不同的方式完成,因为不再支持 &lt;&lt;==。我举了一个示例任务示例,在我在我的一个项目中使用的编译之前运行:

lazy val wsdlImport = TaskKey[Unit]("wsdlImport", "Generates Java classes from WSDL")

wsdlImport := 
  import sys.process._
  "./wsdl/bin/wsdl_import.sh" !
  // or do whatever stuff you need


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

这与 1.x 之前的做法非常相似。

另外,official SBT docs 还建议了另一种方式,它基本上是任务的组合(而不是依赖关系层次结构)。以与上述相同的示例:

(compile in Compile) := 
  val w = wsdlImport.value
  val c = (compile in Compile).value
  // you can add more tasks to composition or perform some actions with them
  c

感觉在某些情况下提供了更大的灵活性,尽管对我来说第一个示例看起来更简洁一些。

已在 SBT 1.2.3 上测试,但也应与其他 1.x 一起使用。

【讨论】:

你会如何在一个构建中让它适应多个项目? (ThisBuild / compile in Compile) := ... 不适合我 @Troy Daniels 我不确定你的具体情况,但一般来说,sbt 建议使用dependsOn 来设置模块之间的依赖关系。例如。我在我的一个项目中使用的一个示例是:1)我有一个自定义任务要在 compile 之前在一个名为 wsdl 的子项目中运行,以及 2)对于我的主要 build.sbt,我使用 val root = (project in file(".")).aggregate(wsdl).dependsOn(wsdl)...所以自定义任务在编译主项目之前执行。 HTH! @Vladimar Salin 我的项目间依赖关系正常工作。我要更改的是项目内任务依赖项。作为compile 任务的一部分,我想运行另一个运行样式检查器的任务。没有为每个项目重复(prj1 / compile in Compile) = ...,我没有看到在每个项目中运行样式检查器的方法。

以上是关于在标准任务之前/之后自动运行自定义任务的主要内容,如果未能解决你的问题,请参考以下文章

《上海悠悠接口自动化平台》-5.测试计划与定时任务

制作自定义Gradle任务,生成代码,在IDE导入上运行

如何设置 Celery 在运行任务之前调用自定义初始化函数?

win7任务计划

如何从外部jar自动运行java任务?

如何在 sbt 中的测试任务之前附加自定义任务以执行?