SBT中的排序和覆盖任务

Pat*_*iek 15 scala heroku sbt playframework sbt-native-packager

快速摘要:我正在尝试在顶级项目中等待所有SBT子模块构建,然后删除它们的target目录.顶级应用程序聚合所有子模块,它们不会单独部署,而只是作为具有类路径依赖性的包,而子模块中的重复库会炸毁整个包的大小,并且slug超过Heroku限制.

从技术上讲,我正在尝试实际使用它 - 我正在尝试添加一个可以运行的'清理'任务stage.上面链接的解决方案对我来说似乎不起作用(Play 2.4,SBT 0.13.5),错误说它比我更好:

build.sbt:50: error: reference to stage is ambiguous;
it is imported twice in the same scope by
import _root_.com.typesafe.sbt.packager.universal.UniversalPlugin.autoImport._
and import $52e59eb09172b3222f9e._
stage := {
Run Code Online (Sandbox Code Playgroud)

假设我有清理任务:

val stageCleanupTask = taskKey[Unit]("Clean after stage task")

stageCleanupTask := {
  val log = streams.value.log
  if (sys.env.getOrElse("POST_STAGE_CLEAN", "false").equals("true")) {
    log.info("Cleaning submodules' target directories")
    sbt.IO.delete(baseDirectory.value / "modules" / "a" / "target")
    sbt.IO.delete(baseDirectory.value / "modules" / "b" / "target")
    sbt.IO.delete(baseDirectory.value / "modules" / "c" / "target")
  }
}
Run Code Online (Sandbox Code Playgroud)

而且我想要覆盖stage:

stage := {
  val f = (stage in Universal).value
  stageCleanupTask.value
  f
}
Run Code Online (Sandbox Code Playgroud)

这似乎完全错误,因为两个任务同时运行.SBT并没有真正让它变得简单,我在官方文档中找不到多少,所以我只是在玩:

  • stage.flatMap期望一个函数返回a Task[U],但是stageCleanupTaska TaskKey[T],并且.value在非常特定的区域之外不起作用,所以通过类似的东西组合stage <<= stage.flatMap(f => stageCleanupTask.map(_ => f))似乎是不可能的.

  • dependsOn只能工作stage <<= stage dependsOn stageCleanupTask,这与我想要的依赖链完全相反.stageCleanupTask应该依赖stage,但类型不匹配(Task[Unit]vs Task[File])

  • 我试图尝试覆盖内部的组合stage,如:

    stage := {
        (stage in Universal).map(f => /*follow up*/ f).value
    }
    
    Run Code Online (Sandbox Code Playgroud)

    但这通常只是用illegal dynamic dependency或者打我的脸illegal dynamic reference

什么是SBT任务排序的首选方式?

Dal*_*and 6

有关如何对任务进行排序,请参见http://www.scala-sbt.org/0.13/docs/Howto-Sequencing.html.

所以类似于:

stage in Universal := Def.sequential(
  stage in Universal,
  stageCleanupTask
)
Run Code Online (Sandbox Code Playgroud)


Mar*_*ijn 5

首先让我说这baseDirectory.value / "modules" / "a" / "target"不是您想要使用的那种路径定义,因为使用 SBT 为您提供的设置要好得多。我推荐的是使用(target in moduleName).value.

至于你的主要问题,我建议你这样做:

val stageCleanupTask = taskKey[sbt.File]("Clean after stage task")

lazy val root = project.in(file("."))
  ...
  .settings(
    stageCleanupTask := {
      val a = (stage in Universal).value
      val log = streams.value.log
      if (sys.env.getOrElse("POST_STAGE_CLEAN", "false").equals("true")) {
        log.info("Cleaning submodules' target directories")
        sbt.IO.delete((target in a).value)
        sbt.IO.delete((target in b).value)
        sbt.IO.delete((target in c).value)
      }
      a
    },
    stage <<= stageCleanupTask
Run Code Online (Sandbox Code Playgroud)

我刚刚在我自己的一个项目中进行了测试,它运行完美。


编辑 1

我的电池快死了,所以我不能看着进一步,但它可能是你在寻找的东西。


kra*_*ken 3

替换以下代码

stage := {
  val f = (stage in Universal).value
  stageCleanupTask.value
  f
}
Run Code Online (Sandbox Code Playgroud)

靠这个

import com.typesafe.sbt.packager.universal.UniversalPlugin.autoImport.Universal

stage := Def.taskDyn {
  val x = (stage in Universal).value
  Def.task {
    stageCleanupTask.value
    x
  }
}.value
Run Code Online (Sandbox Code Playgroud)

这将导致对任务进行排序并按您的预期工作。