为了加快我们的开发工作流程,我们拆分测试并在多个代理上并行运行每个部分。然而,编译测试源似乎需要大部分时间用于测试步骤。
为了避免这种情况,我们使用 sbt test:compile
预编译测试。并使用已编译的目标构建一个 docker 镜像。
稍后,此镜像在每个代理中用于运行测试。但是,即使存在已编译的类,它似乎也会重新编译测试和应用程序源。
有没有办法让 sbt 使用现有的编译目标?
更新:提供更多背景信息
这个问题与 scala 和 sbt 严格相关(因此是 sbt 标签)。
我们的 CI 过程分为多个阶段。它大致是这样的。
sbt compile
将 Scala 项目编译成 java bitcode我们使用 sbt test:compile
在同一测试中编译测试源目标捆绑在 docker 镜像中并推送到远程存储库,测试从构建的 docker 镜像运行,因此环境是
相同的。但是,正在运行
sbt test
甚至导致项目重新编译通过编译的bitcode存在。
为了说明这一点,我基本上想在一台机器上编译并在另一台机器上运行已编译的测试源,而无需重新编译
更新
我不认为 https://stackoverflow.com/a/37440714/8261是同样的问题,因为与它不同,我不安装卷或在主机上构建。一切都在 docker 中编译和运行,但分为两个构建阶段。因此,文件修改时间和路径保持不变。
调试输出有这样的东西
Initial source changes:
removed:Set()
added: Set()
modified: Set()
Invalidated products: Set(/app/target/scala-2.12/classes/Class1.class, /app/target/scala-2.12/classes/graph/Class2.class, ...)
External API changes: API Changes: Set()
Modified binary dependencies: Set()
Initial directly invalidated classes: Set()
Sources indirectly invalidated by:
product: Set(/app/Class4.scala, /app/Class5.scala, ...)
binary dep: Set()
external source: Set()
All initially invalidated classes: Set()
All initially invalidated sources:Set(/app/Class4.scala, /app/Class5.scala, ...)
Recompiling all 304 sources: invalidated sources (266) exceeded 50.0% of all sources
Compiling 302 Scala sources and 2 Java sources to /app/target/scala-2.12/classes ...
它没有初始源更改,但产品已失效。
更新:重现的最小项目
我创建了一个最小的 sbt 项目来重现该问题。
https://github.com/pulasthibandara/sbt-docker-recomplile
如您所见,除了在新步骤(新容器)的第二阶段运行之外,构建阶段之间没有任何变化。
最佳答案
虽然 https://stackoverflow.com/a/37440714/8261指向正确的方向,根本问题和解决方案是不同的。
问题
当 SBT 在 docker 构建的不同阶段运行时,它似乎会重新编译所有内容。这是因为 docker 会压缩在每个阶段创建的图像,从而从源中去除 lastModifiedDate 的毫秒部分。
SBT 在确定源是否已更改时取决于 lastModifiedDate,并且由于其不同(毫秒部分),构建会触发完整的重新编译。
解决方案
设置
-Dsbt.io.jdktimestamps=true
当按照 https://github.com/sbt/sbt/issues/4168#issuecomment-417655678 中的建议运行 SBT 时解决此问题。 遵循 https://github.com/sbt/sbt/issues/4168#issuecomment-417658294 中的推荐
我通过设置
SBT_OPTS
解决了这个问题docker 文件中的 env 变量,例如ENV SBT_OPTS="${SBT_OPTS} -Dsbt.io.jdktimestamps=true"
test project已使用此解决方法进行更新。
关于scala - 如何在不同机器上重用已编译的源代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54068316/