在我们的项目中,我们对编译生成的.class文件进行了增强后处理。此增强步骤实际上会修改生成的.class文件,然后覆盖它。
enhance <<= enhance triggeredBy (compile in Compile)
问题是sbt有一种称为增量重新编译的机制。它监视生成的.class文件。每次增强器覆盖生成的.class文件时,sbt都会识别这些修改并在下一个编译命令中重新编译相关的源。
对我们来说,重新编译是一项非常耗时的工作。我们希望阻止sbt重新编译修改后的.class文件。这可能意味着使sbt仅监视源更改,而不是输出更改。
我做了一些搜索。但我发现了一些关于这一点的事情。现在我知道一个名为Analysis的特性可能负责从源到输出.class文件的映射。所以我向你们求助。
Ps:我们可以通过将增强的输出放到另一个文件夹来解决这个问题,但不是首选。
答案 0 :(得分:4)
sbt strongly discourages mutations to files。您应该生成不同的文件。通过这样做,您将解决您的问题,因为sbt的增量编译器仍将查看未更改的.class文件。你会做一些重新布线:
将compile
任务的输出发送到其他地方:
classDirectory in Compile := crossTarget.value / "classes-orig"
使用您的工具处理这些.class文件,并将其发送到crossTarget.value / "classes"
(原始classDirectory
:
enhance <<= enhance triggeredBy (compile in Compile)
enhance := {
val fromDir := (classesDirectory in Compile).value
val toDir := crossTarget.value / "classes"
...
}
无论如何都要productDirectories
重新使用crossTarget.value / "classes"
(否则它会查看修改过的classDirectory
:
productDirectories in Compile := Seq(crossTarget.value / "classes")
确保products
取决于您的enhance
任务:
products in Compile <<= (products in Compile) dependsOn enhance
如果您有资源,可能需要更多重新布线(请参阅copyResources
)。但基本上你应该能够到达那里。
答案 1 :(得分:2)
我说过sbt监视输出的.class文件。修改.class文件时,它会重新编译.class文件的源。
经过一些研究,我们发现sbt通过上次修改时间注意文件的修改。也就是说,我们可以通过在修改后回滚上次修改时间来欺骗sbt,以便sbt不会注意到任何更改。
所以,我们的解决方案很简单但很有效:
这是一个小技巧。我们仍然期待更强大的解决方案。
答案 2 :(得分:0)
类似于 Chenyu ,我不得不为SBT 1.x
编写一个插件,该插件会增强编译后的类,后来我想确保这些<使用strong>增强类来构建 jar
。
我不想破解此解决方案,因此Chenyu's answer对我来说是不可接受的,并且sjrd's answer很有帮助,但已调整为SBT 0.13
。
这是我的工作解决方案,并带有少量评论:
object autoImport {
val enhancedDest = settingKey[File]("Output dir for enhanced sources")
}
def enhanceTask: Def.Initialize[Task[Unit]] = Def.task {
val inputDir = (classDirectory in Compile).value
val outputDir = enhancedDest.value
enhance(inputDir, outputDir)
...
}
override def projectSettings: Seq[Def.Setting[_]] = Seq(
enhancedDest := crossTarget.value / "classes-enhanced",
products in Compile := Seq(enhancedDest.value), // mark enhanced folder to use for packaging
// https://www.scala-sbt.org/1.0/docs/Howto-Dynamic-Task.html#build.sbt+v2
compile in Compile := Def.taskDyn {
val c = (compile in Compile).value // compile 1st.
Def.task {
(copyResources in Compile).value // copy resources before enhance
enhanceTask.value // enhance
c
}
}.value
)