Skip to content

Commit 16a6ff0

Browse files
authored
chore: make incremental compilation work with stdlib plugin and enable it in the new stdlib (#23592)
Two main things here: - We changed the `ScalaLibraryPlugin` to be able to work smoothly with the incremental compilation - We enable the plugin in the new stdlib projects. Some resources: - Hijacking the compilation analysis: https://github.com/playframework/play-enhancer/blob/74fd35ff0ed18ec2084405d1a6124898cc22e857/plugin/src/main/scala-sbt-1.0/com/typesafe/play/sbt/enhancer/PlayEnhancer.scala - sbt docs: https://www.scala-sbt.org/1.x/docs/Understanding-Recompilation.html#Bytecode+Enhancers
2 parents bbc089e + a8d1c9d commit 16a6ff0

File tree

2 files changed

+38
-15
lines changed

2 files changed

+38
-15
lines changed

project/Build.scala

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,7 @@ object Build {
14191419

14201420
/* Configuration of the org.scala-lang:scala-library:*.**.**-nonboostrapped project */
14211421
lazy val `scala-library-nonbootstrapped` = project.in(file("library"))
1422+
.enablePlugins(ScalaLibraryPlugin)
14221423
.settings(
14231424
name := "scala-library-nonbootstrapped",
14241425
moduleName := "scala-library",
@@ -1451,6 +1452,7 @@ object Build {
14511452

14521453
/* Configuration of the org.scala-lang:scala-library:*.**.**-boostrapped project */
14531454
lazy val `scala-library-bootstrapped` = project.in(file("library"))
1455+
.enablePlugins(ScalaLibraryPlugin)
14541456
.settings(
14551457
name := "scala-library-bootstrapped",
14561458
moduleName := "scala-library",
@@ -1480,8 +1482,11 @@ object Build {
14801482
publish / skip := true,
14811483
// Project specific target folder. sbt doesn't like having two projects using the same target folder
14821484
target := target.value / "scala-library-bootstrapped",
1485+
// we need to have the `scala-library` artifact in the classpath for `ScalaLibraryPlugin` to work
1486+
// this was the only way to not get the artifact evicted by sbt. Even a custom configuration didn't work
1487+
// NOTE: true is the default value, just making things clearer here
1488+
managedScalaInstance := true,
14831489
// Configure the nonbootstrapped compiler
1484-
managedScalaInstance := false,
14851490
scalaInstance := {
14861491
val externalLibraryDeps = (`scala3-library` / Compile / externalDependencyClasspath).value.map(_.data).toSet
14871492
val externalCompilerDeps = (`scala3-compiler` / Compile / externalDependencyClasspath).value.map(_.data).toSet
@@ -1500,7 +1505,7 @@ object Build {
15001505
val compilerJars = Seq(tastyCore, scala3Interfaces, scala3Compiler) ++ (externalCompilerDeps -- externalLibraryDeps)
15011506

15021507
Defaults.makeScalaInstance(
1503-
scalaVersion.value,
1508+
dottyNonBootstrappedVersion,
15041509
libraryJars = libraryJars,
15051510
allCompilerJars = compilerJars,
15061511
allDocJars = Seq.empty,

project/ScalaLibraryPlugin.scala

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import sbt.*
44
import sbt.Keys.*
55
import scala.jdk.CollectionConverters.*
66
import java.nio.file.Files
7+
import xsbti.VirtualFileRef
8+
import sbt.internal.inc.Stamper
79

810
object ScalaLibraryPlugin extends AutoPlugin {
911

1012
override def trigger = noTrigger
1113

1214
val fetchScala2ClassFiles = taskKey[(Set[File], File)]("Fetch the files to use that were compiled with Scala 2")
13-
//val scala2LibraryVersion = settingKey[String]("Version of the Scala 2 Standard Library")
1415

1516
override def projectSettings = Seq (
1617
fetchScala2ClassFiles := {
@@ -37,17 +38,29 @@ object ScalaLibraryPlugin extends AutoPlugin {
3738
} (Set(scalaLibraryBinaryJar)), target)
3839

3940
},
40-
(Compile / compile) := {
41+
(Compile / manipulateBytecode) := {
4142
val stream = streams.value
4243
val target = (Compile / classDirectory).value
4344
val (files, reference) = fetchScala2ClassFiles.value;
44-
val analysis = (Compile / compile).value
45-
stream.log.info(s"Copying files from Scala 2 Standard Library to $target")
46-
for (file <- files; id <- file.relativeTo(reference).map(_.toString())) {
47-
if (filesToCopy(id)) {
48-
stream.log.debug(s"Copying file '${id}' to ${target / id}")
49-
IO.copyFile(file, target / id)
50-
}
45+
val previous = (Compile / manipulateBytecode).value
46+
val analysis = previous.analysis match {
47+
case analysis: sbt.internal.inc.Analysis => analysis
48+
case _ => sys.error("Unexpected analysis type")
49+
}
50+
51+
var stamps = analysis.stamps
52+
for (file <- files;
53+
id <- file.relativeTo(reference);
54+
if filesToCopy(id.toString()); // Only Override Some Very Specific Files
55+
dest = target / (id.toString);
56+
ref <- dest.relativeTo((LocalRootProject / baseDirectory).value)
57+
) {
58+
// Copy the files to the classDirectory
59+
IO.copyFile(file, dest)
60+
// Update the timestamp in the analysis
61+
stamps = stamps.markProduct(
62+
VirtualFileRef.of(s"$${BASE}/$ref"),
63+
Stamper.forFarmHashP(dest.toPath()))
5164
}
5265

5366
val overwrittenBinaries = Files.walk((Compile / classDirectory).value.toPath())
@@ -56,13 +69,18 @@ object ScalaLibraryPlugin extends AutoPlugin {
5669
.map(_.toFile)
5770
.map(_.relativeTo((Compile / classDirectory).value).get)
5871
.toSet
72+
5973
val diff = files.filterNot(_.relativeTo(reference).exists(overwrittenBinaries))
6074

61-
IO.copy(diff.map { file =>
62-
file -> (Compile / classDirectory).value / file.relativeTo(reference).get.getPath
63-
})
75+
// Copy all the specialized classes in the stdlib
76+
// no need to update any stamps as these classes exist nowhere in the analysis
77+
for (orig <- diff; dest <- orig.relativeTo(reference)) {
78+
IO.copyFile(orig, ((Compile / classDirectory).value / dest.toString()))
79+
}
6480

65-
analysis
81+
previous
82+
.withAnalysis(analysis.copy(stamps = stamps)) // update the analysis with the correct stamps
83+
.withHasModified(true) // mark it as updated for sbt to update its caches
6684
}
6785
)
6886

0 commit comments

Comments
 (0)