Skip to content

Commit 57af755

Browse files
author
Blaine Freestone
committed
add sourceroot flag with absolute root path of the sandbox worker in order to make the filepath relative in the tasty file
this should not invalidate the bazel cache every time because of the path mapping set in the bazel rule config remove sourceroot flag from analysis_store file content (it's not deterministic) add -sourceroot conditionally (it was introduced in Scala 3); change from --sourceroot to -sourceroot !fixup add -sourceroot !fixup add -sourceroot !fixup add -sourceroot add comment explaining change
1 parent b7d7639 commit 57af755

File tree

2 files changed

+69
-8
lines changed

2 files changed

+69
-8
lines changed
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package sbt.internal.inc
2+
3+
import xsbti.compile.{CompileOptions, MiniSetup}
4+
import java.nio.file.{Path, Paths}
5+
6+
/**
7+
* Zinc's MiniSetup contains scalacOptions which include the -sourceroot flag that references absolute sandbox paths.
8+
* These paths are non-deterministic across builds because the sandbox directory changes (e.g., __sandbox/4/_main vs
9+
* __sandbox/8/_main), making the analysis files non-deterministic.
10+
*
11+
* This class filters out the -sourceroot option from the scalacOptions to ensure deterministic analysis files.
12+
*
13+
* TODO: Consider if there's a better way to handle this upstream in Zinc
14+
*/
15+
16+
object FilteredSetup {
17+
private val sourcerootFlag = "-sourceroot"
18+
19+
def getFilteredSetup(setup: MiniSetup): MiniSetup = {
20+
val options = setup.options()
21+
// Filter out the -sourceroot option and its value
22+
val filteredScalacOptions = {
23+
val originalOptions = options.scalacOptions()
24+
val filtered = scala.collection.mutable.ArrayBuffer[String]()
25+
var i = 0
26+
while (i < originalOptions.length) {
27+
val option = originalOptions(i)
28+
if (option == sourcerootFlag) {
29+
// Skip both the flag and its value (next argument)
30+
i += 2
31+
} else {
32+
filtered += option
33+
i += 1
34+
}
35+
}
36+
filtered.toArray
37+
}
38+
39+
// Create new CompileOptions with filtered scalac options
40+
val newOptions = options.withScalacOptions(filteredScalacOptions)
41+
// Create new MiniSetup with filtered options
42+
setup.withOptions(newOptions)
43+
}
44+
}

src/main/scala/higherkindness/rules_scala/workers/zinc/compile/ZincRunner.scala

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ import net.sourceforge.argparse4j.impl.Arguments as Arg
1818
import net.sourceforge.argparse4j.inf.{ArgumentParserException, Namespace}
1919
import sbt.internal.inc.classpath.ClassLoaderCache
2020
import sbt.internal.inc.caching.ClasspathCache
21-
import sbt.internal.inc.{Analysis, AnalyzingCompiler, CompileFailed, FilteredInfos, FilteredRelations, IncrementalCompilerImpl, Locate, PlainVirtualFile, PlainVirtualFileConverter, ZincUtil}
21+
import sbt.internal.inc.{Analysis, AnalyzingCompiler, CompileFailed, FilteredInfos, FilteredRelations, FilteredSetup, IncrementalCompilerImpl, Locate, PlainVirtualFile, PlainVirtualFileConverter, ZincUtil}
2222
import scala.jdk.CollectionConverters.*
2323
import scala.util.Try
2424
import scala.util.control.NonFatal
@@ -212,17 +212,31 @@ object ZincRunner extends WorkerMain[ZincRunnerWorkerConfig] {
212212
isWorker,
213213
)
214214

215+
// Check if we should include the -sourceroot flag in the compiler options
216+
// We only include it for Scala 3 and later versions, as it is not supported
217+
// in Scala 2.x versions.
218+
// We include this so that the TASTy file generated by the Scala compiler
219+
// will be deterministic across machines and directories Bazel uses for
220+
// multiplexed sandbox execution.
221+
val shouldIncludeSourceRoot = !scalaInstance.actualVersion.startsWith("0.") &&
222+
scalaInstance.actualVersion.startsWith("3")
223+
224+
val scalacOptions =
225+
workRequest.plugins.view.map(p => s"-Xplugin:$p").toArray ++
226+
workRequest.compilerOptions ++
227+
workRequest.compilerOptionsReferencingPaths.toArray ++
228+
(if (shouldIncludeSourceRoot)
229+
Array("-sourceroot", task.workDir.toAbsolutePath().toString)
230+
else
231+
Array.empty[String])
232+
215233
val compileOptions =
216234
CompileOptions.create
217235
.withSources(sources.view.map(source => PlainVirtualFile(source.toAbsolutePath().normalize())).toArray)
218236
.withClasspath((classesOutputDir +: deps.view.map(_.classpath)).map(path => PlainVirtualFile(path)).toArray)
219237
.withClassesDirectory(classesOutputDir)
220238
.withJavacOptions(workRequest.javaCompilerOptions)
221-
.withScalacOptions(
222-
workRequest.plugins.view.map(p => s"-Xplugin:$p").toArray ++
223-
workRequest.compilerOptions ++
224-
workRequest.compilerOptionsReferencingPaths.toArray,
225-
)
239+
.withScalacOptions(scalacOptions)
226240

227241
val compilers = {
228242
val scalaCompiler = ZincUtil
@@ -335,14 +349,17 @@ object ZincRunner extends WorkerMain[ZincRunnerWorkerConfig] {
335349
)
336350
}
337351

352+
// Filter out non-deterministic --sourceroot paths from the setup
353+
val filteredSetup = FilteredSetup.getFilteredSetup(compileResult.setup)
354+
338355
val analysisStoreText = AnalysisUtil.getAnalysisStore(
339356
new File(pathString.substring(0, pathString.length() - 3) + ".text.gz"),
340357
true,
341358
readWriteMappers,
342359
)
343360

344-
analysisStoreText.set(AnalysisContents.create(resultAnalysis, compileResult.setup))
345-
analysisStore.set(AnalysisContents.create(resultAnalysis, compileResult.setup))
361+
analysisStoreText.set(AnalysisContents.create(resultAnalysis, filteredSetup))
362+
analysisStore.set(AnalysisContents.create(resultAnalysis, filteredSetup))
346363

347364
// create used deps
348365
val usedDeps =

0 commit comments

Comments
 (0)