我经常想在运行其中一个标准任务之前进行一些自定义。我意识到我可以按照我想要的顺序创建执行现有任务的新任务,但我发现这很麻烦,并且开发人员错过了他应该运行my-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 不会自动执行它。那么如何更改上面的代码才能在合适的时间运行?
更一般地说,我在哪里可以找到有关挂钩到其他任务(如编译)的信息,是否有一般方法可以确保在调用标准任务之前和之后运行自己的任务?
答案 0 :(得分:34)
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
(所有上述未经测试,但总体推力应该有效,我希望)。
答案 1 :(得分:0)
作为@Paul Butcher先前回答的更新,在SBT 1.x版本中可以用另一种方式完成此操作,因为不再支持<<==
。我以一个示例任务为例,该示例任务要在我的一个项目中使用的编译之前运行:
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一起使用。