在runMain中sbt非法动态引用

Rea*_*onk 2 scala sbt

我正在尝试运行代码生成器,并传递文件名以写入输出:

resourceGenerators in (proj, Compile) += Def.task {
  val file = (resourceManaged in (proj, Compile)).value / "swagger.yaml"
  (runMain in (proj, Compile)).toTask(s"api.swagger.SwaggerDump $file").value
  Seq(file)
}.value
Run Code Online (Sandbox Code Playgroud)

但是,这给了我:

build.sbt:172: error: Illegal dynamic reference: file
  (runMain in (proj, Compile)).toTask(s"api.swagger.SwaggerDump $file").value
Run Code Online (Sandbox Code Playgroud)

Jor*_*ero 6

您的代码段有两个问题:

  1. 你用{ ... }.value而不是{ ... }.taskValue.资源的类型发电机的是Seq[Task[Seq[File]]],当你这样做value,你Seq[File]不是Task[Seq[File]].这会导致合法的编译错误.
  2. 动态变量file用作toTask当前宏实现禁止的参数.

静电为什么?

Sbt强制任务实现对其他任务具有静态依赖性.否则,sbt无法执行任务重复数据删除,无法在inspect命令中提供正确的信息.这意味着您在任务中执行的任务评估不能依赖于变量(仅在运行时已知的值),就像您的filein toTask.一样.

为了克服这个限制,存在动态任务,其主体允许您返回任务.每个"动态依赖"都必须在动态任务中定义,然后您可以依赖于返回的任务中提升的动态值.

动态解决方案

以下Scastie是您的任务的正确实现.我复制粘贴代码,以便人们可以快速查看,但去Scastie检查它是否成功编译并运行.

resourceGenerators in (proj, Compile) += Def.taskDyn {
  val file = (resourceManaged in (proj, Compile)).value / "swagger.yaml"
  Def.task {
    (runMain in (proj, Compile))
      .toTask(s"api.swagger.SwaggerDump $file")
      .value
    Seq(file)
  }
}.taskValue
Run Code Online (Sandbox Code Playgroud)

讨论

如果您已修复taskValue错误,您的任务实现是否应该正确编译?

在我看来,是的,但我没有看好内部实现,足以断言你的任务实现不会妨碍任务重复数据删除和依赖项提取.如果没有,非法参考检查应该消失.

这是我想要摆脱的sbt的当前限制,要么通过改进整个宏实现(提升值并确保依赖性分析涵盖更多情况),要么只是改进"非法引用检查"而不是过于悲观.然而,这是一个难题,需要时间,而且不太可能在短期内发生.

如果这对您来说是个问题,请在sbt/sbt中提交一张票.这是了解解决此问题的紧迫性的唯一方法,如果有的话.目前,我们所能做的最好的就是记录它.