我试图运行代码生成器,并传递文件名以写入输出:
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
但是,这给了我:
build.sbt:172: error: Illegal dynamic reference: file
(runMain in (proj, Compile)).toTask(s"api.swagger.SwaggerDump $file").value
答案 0 :(得分:6)
您的代码段有两个问题:
{ ... }.value
代替{ ... }.taskValue
。资源生成器的类型为Seq[Task[Seq[File]]]
,当您执行value
时,您会Seq[File]
而不是Task[Seq[File]]
。这会导致合法的编译错误。file
用作toTask
的参数,当前宏实现禁止该参数。 Sbt强制任务实现对其他任务具有静态依赖性。否则,sbt无法执行任务重复数据删除,无法在inspect
命令中提供正确的信息。这意味着您在任务中执行的任务评估不能依赖于变量(仅在运行时已知的值),就像file
中的toTask
那样。
为克服此限制,存在动态任务,其主体允许您返回任务。每一个"动态依赖"必须在动态任务中定义,然后您可以依赖于返回的任务中提升的动态值。
The following 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
如果您修复了taskValue
错误,您的任务实现是否应该正确编译?
在我看来,是的,但是我还没有看到内部实现足以断言你的任务实现不会妨碍任务重复数据删除和依赖项提取。如果没有,非法参考检查应该消失。
这是我想要摆脱的sbt的当前限制,要么通过改进整个宏实现(提升值并确保依赖性分析涵盖更多案例),要么只是通过改进"非法参考检查"不要过于悲观。然而,这是一个难题,需要时间,而且短期内不太可能发生。
如果这对您来说是个问题,请在sbt / sbt中提交一张票。这是了解解决此问题的紧迫性的唯一方法,如果有的话。目前,我们所能做的最好的就是记录它。