Skip to content

Commit 9646f65

Browse files
authored
Add plugin to copy binary files from the scala 2 artefacts (#22480)
First part of #22043 Supersedes #22399
2 parents 798987a + c8f6c4a commit 9646f65

3 files changed

+149
-77
lines changed

project/Build.scala

+3
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ import sbt.Package.ManifestAttributes
2121
import sbt.PublishBinPlugin.autoImport._
2222
import dotty.tools.sbtplugin.RepublishPlugin
2323
import dotty.tools.sbtplugin.RepublishPlugin.autoImport._
24+
import dotty.tools.sbtplugin.ScalaLibraryPlugin
25+
2426
import sbt.plugins.SbtPlugin
2527
import sbt.ScriptedPlugin.autoImport._
2628
import xerial.sbt.Sonatype.autoImport._
@@ -1210,6 +1212,7 @@ object Build {
12101212
* This version of the library is not (yet) TASTy/binary compatible with the Scala 2 compiled library.
12111213
*/
12121214
lazy val `scala2-library-bootstrapped` = project.in(file("scala2-library-bootstrapped")).
1215+
enablePlugins(ScalaLibraryPlugin).
12131216
withCommonSettings(Bootstrapped).
12141217
dependsOn(dottyCompiler(Bootstrapped) % "provided; compile->runtime; test->test").
12151218
settings(scala2LibraryBootstrappedSettings).

project/Scala2LibraryBootstrappedMiMaFilters.scala

+38-77
Original file line numberDiff line numberDiff line change
@@ -4,83 +4,44 @@ import com.typesafe.tools.mima.core._
44
object Scala2LibraryBootstrappedMiMaFilters {
55

66
val BackwardsBreakingChanges: Map[String, Seq[ProblemFilter]] = Map(
7-
Build.stdlibBootstrappedVersion -> {
8-
Seq(
9-
// Files that are not compiled in the bootstrapped library
10-
ProblemFilters.exclude[MissingClassProblem]("scala.AnyVal"),
11-
12-
// Scala language features
13-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.language.<clinit>"),
14-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.language#experimental.<clinit>"),
15-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.util.Properties.<clinit>"),
16-
ProblemFilters.exclude[FinalClassProblem]("scala.language$experimental$"),
17-
ProblemFilters.exclude[FinalClassProblem]("scala.languageFeature$*$"),
18-
19-
// Issue: https://github.com/scala/scala3/issues/22495
20-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.ArrayOps.scala$collection$ArrayOps$$elemTag$extension"),
21-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.ArrayOps.iterateUntilEmpty$extension"),
22-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.isLineBreak$extension"),
23-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.isLineBreak2$extension"),
24-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.linesSeparated$extension"),
25-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.escape$extension"),
26-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.toBooleanImpl$extension"),
27-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.unwrapArg$extension"),
28-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.iterateUntilEmpty$extension"),
29-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuple2Zipped.coll1$extension"),
30-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuple2Zipped.coll2$extension"),
31-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuple3Zipped.coll1$extension"),
32-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuple3Zipped.coll2$extension"),
33-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuple3Zipped.coll3$extension"),
34-
35-
// Companion module class
36-
ProblemFilters.exclude[FinalClassProblem]("scala.*$"),
37-
38-
// Scala 2 intrinsic macros
39-
ProblemFilters.exclude[FinalMethodProblem]("scala.StringContext.s"),
40-
41-
// Specialization?
42-
ProblemFilters.exclude[MissingFieldProblem]("scala.Tuple1._1"), // field _1 in class scala.Tuple1 does not have a correspondent in current version
43-
ProblemFilters.exclude[MissingFieldProblem]("scala.Tuple2._1"), // field _1 in class scala.Tuple2 does not have a correspondent in current version
44-
ProblemFilters.exclude[MissingFieldProblem]("scala.Tuple2._2"), // field _2 in class scala.Tuple2 does not have a correspondent in current version
45-
46-
// Scala 2 specialization
47-
ProblemFilters.exclude[MissingClassProblem]("scala.*$sp"),
48-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.*$sp"),
49-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.*#*#sp.$init$"),
50-
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.DoubleStepper"),
51-
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.immutable.DoubleVectorStepper"),
52-
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.immutable.IntVectorStepper"),
53-
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.immutable.LongVectorStepper"),
54-
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.IntStepper"),
55-
ProblemFilters.exclude[MissingTypesProblem]("scala.collection.LongStepper"),
56-
ProblemFilters.exclude[MissingTypesProblem]("scala.jdk.DoubleAccumulator"),
57-
ProblemFilters.exclude[MissingTypesProblem]("scala.jdk.FunctionWrappers$*"),
58-
ProblemFilters.exclude[MissingTypesProblem]("scala.jdk.IntAccumulator"),
59-
ProblemFilters.exclude[MissingTypesProblem]("scala.jdk.LongAccumulator"),
60-
ProblemFilters.exclude[FinalClassProblem]("scala.collection.ArrayOps$ReverseIterator"),
61-
ProblemFilters.exclude[FinalClassProblem]("scala.Tuple1"),
62-
ProblemFilters.exclude[FinalClassProblem]("scala.Tuple2"),
63-
64-
// other
65-
ProblemFilters.exclude[FinalMethodProblem]("scala.Enumeration.ValueOrdering"),
66-
ProblemFilters.exclude[FinalMethodProblem]("scala.Enumeration.ValueSet"),
67-
ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.NoPositioner"),
68-
ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.RelaxedPosition"),
69-
ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.RelaxedPositioner"),
70-
ProblemFilters.exclude[MissingFieldProblem]("scala.collection.ArrayOps#ReverseIterator.xs"),
71-
ProblemFilters.exclude[MissingFieldProblem]("scala.runtime.NonLocalReturnControl.value"),
72-
73-
// Missing outer pointers in private classes (not a problem)
74-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.LinearSeqIterator#LazyCell.this"),
75-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.mutable.PriorityQueue#ResizableArrayAccess.this"),
76-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.concurrent.BatchingExecutor#AbstractBatch.this"),
77-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.concurrent.Channel#LinkedList.this"),
78-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.IterableOnceOps#Maximized.this"),
79-
80-
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.util.Sorting.scala$util$Sorting$$mergeSort$default$5"),
81-
82-
)
83-
}
7+
Build.stdlibBootstrappedVersion -> Seq(
8+
// Scala language features (not really a problem)
9+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.language.<clinit>"),
10+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.language#experimental.<clinit>"),
11+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.util.Properties.<clinit>"),
12+
13+
// Companion module class (not really a problem)
14+
ProblemFilters.exclude[FinalClassProblem]("scala.*$"),
15+
ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.NoPositioner"),
16+
ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.RelaxedPosition"),
17+
ProblemFilters.exclude[FinalMethodProblem]("scala.io.Source.RelaxedPositioner"),
18+
ProblemFilters.exclude[FinalMethodProblem]("scala.Enumeration.ValueOrdering"),
19+
ProblemFilters.exclude[FinalMethodProblem]("scala.Enumeration.ValueSet"),
20+
ProblemFilters.exclude[FinalMethodProblem]("scala.StringContext.s"),
21+
22+
// Issue: https://github.com/scala/scala3/issues/22495
23+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.ArrayOps.scala$collection$ArrayOps$$elemTag$extension"),
24+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.ArrayOps.iterateUntilEmpty$extension"),
25+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.isLineBreak$extension"),
26+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.isLineBreak2$extension"),
27+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.linesSeparated$extension"),
28+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.escape$extension"),
29+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.toBooleanImpl$extension"),
30+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.unwrapArg$extension"),
31+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.StringOps.iterateUntilEmpty$extension"),
32+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuple2Zipped.coll1$extension"),
33+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuple2Zipped.coll2$extension"),
34+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuple3Zipped.coll1$extension"),
35+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuple3Zipped.coll2$extension"),
36+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.runtime.Tuple3Zipped.coll3$extension"),
37+
38+
// Issue: Scala 3 doesn't always outer pointers (not really a problem here)
39+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.IterableOnceOps#Maximized.this"),
40+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.LinearSeqIterator#LazyCell.this"),
41+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.collection.mutable.PriorityQueue#ResizableArrayAccess.this"),
42+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.concurrent.BatchingExecutor#AbstractBatch.this"),
43+
ProblemFilters.exclude[DirectMissingMethodProblem]("scala.concurrent.Channel#LinkedList.this"),
44+
)
8445
)
8546

8647
val ForwardsBreakingChanges: Map[String, Seq[ProblemFilter]] = Map(

project/ScalaLibraryPlugin.scala

+108
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package dotty.tools.sbtplugin
2+
3+
import sbt.*
4+
import sbt.Keys.*
5+
import scala.jdk.CollectionConverters.*
6+
import java.nio.file.Files
7+
8+
object ScalaLibraryPlugin extends AutoPlugin {
9+
10+
override def trigger = noTrigger
11+
12+
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")
14+
15+
override def projectSettings = Seq (
16+
fetchScala2ClassFiles := {
17+
val stream = streams.value
18+
val cache = stream.cacheDirectory
19+
val target = cache / "scala-library-classes"
20+
val report = update.value
21+
22+
val scalaLibraryBinaryJar = report.select(
23+
configuration = configurationFilter(),
24+
module = (_: ModuleID).name == "scala-library",
25+
artifact = artifactFilter(`type` = "jar")).headOption.getOrElse {
26+
sys.error(s"Could not fetch scala-library binary JAR")
27+
}
28+
29+
if (!target.exists()) {
30+
IO.createDirectory(target)
31+
}
32+
33+
(FileFunction.cached(cache / "fetch-scala-library-classes", FilesInfo.lastModified, FilesInfo.exists) { _ =>
34+
stream.log.info(s"Unpacking scala-library binaries to persistent directory: ${target.getAbsolutePath}")
35+
IO.unzip(scalaLibraryBinaryJar, target)
36+
(target ** "*.class").get.toSet
37+
} (Set(scalaLibraryBinaryJar)), target)
38+
39+
},
40+
(Compile / compile) := {
41+
val stream = streams.value
42+
val target = (Compile / classDirectory).value
43+
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+
}
51+
}
52+
53+
val overwrittenBinaries = Files.walk((Compile / classDirectory).value.toPath())
54+
.iterator()
55+
.asScala
56+
.map(_.toFile)
57+
.map(_.relativeTo((Compile / classDirectory).value).get)
58+
.toSet
59+
val diff = files.filterNot(_.relativeTo(reference).exists(overwrittenBinaries))
60+
61+
IO.copy(diff.map { file =>
62+
file -> (Compile / classDirectory).value / file.relativeTo(reference).get.getPath
63+
})
64+
65+
analysis
66+
}
67+
)
68+
69+
private lazy val filesToCopy = Set(
70+
"scala/Tuple1.class",
71+
"scala/Tuple2.class",
72+
"scala/collection/DoubleStepper.class",
73+
"scala/collection/IntStepper.class",
74+
"scala/collection/LongStepper.class",
75+
"scala/collection/immutable/DoubleVectorStepper.class",
76+
"scala/collection/immutable/IntVectorStepper.class",
77+
"scala/collection/immutable/LongVectorStepper.class",
78+
"scala/jdk/DoubleAccumulator.class",
79+
"scala/jdk/IntAccumulator.class",
80+
"scala/jdk/LongAccumulator.class",
81+
"scala/jdk/FunctionWrappers$FromJavaDoubleBinaryOperator.class",
82+
"scala/jdk/FunctionWrappers$FromJavaBooleanSupplier.class",
83+
"scala/jdk/FunctionWrappers$FromJavaDoubleConsumer.class",
84+
"scala/jdk/FunctionWrappers$FromJavaDoublePredicate.class",
85+
"scala/jdk/FunctionWrappers$FromJavaDoubleSupplier.class",
86+
"scala/jdk/FunctionWrappers$FromJavaDoubleToIntFunction.class",
87+
"scala/jdk/FunctionWrappers$FromJavaDoubleToLongFunction.class",
88+
"scala/jdk/FunctionWrappers$FromJavaIntBinaryOperator.class",
89+
"scala/jdk/FunctionWrappers$FromJavaDoubleUnaryOperator.class",
90+
"scala/jdk/FunctionWrappers$FromJavaIntPredicate.class",
91+
"scala/jdk/FunctionWrappers$FromJavaIntConsumer.class",
92+
"scala/jdk/FunctionWrappers$FromJavaIntSupplier.class",
93+
"scala/jdk/FunctionWrappers$FromJavaIntToDoubleFunction.class",
94+
"scala/jdk/FunctionWrappers$FromJavaIntToLongFunction.class",
95+
"scala/jdk/FunctionWrappers$FromJavaIntUnaryOperator.class",
96+
"scala/jdk/FunctionWrappers$FromJavaLongBinaryOperator.class",
97+
"scala/jdk/FunctionWrappers$FromJavaLongConsumer.class",
98+
"scala/jdk/FunctionWrappers$FromJavaLongPredicate.class",
99+
"scala/jdk/FunctionWrappers$FromJavaLongSupplier.class",
100+
"scala/jdk/FunctionWrappers$FromJavaLongToDoubleFunction.class",
101+
"scala/jdk/FunctionWrappers$FromJavaLongToIntFunction.class",
102+
"scala/jdk/FunctionWrappers$FromJavaLongUnaryOperator.class",
103+
"scala/collection/ArrayOps$ReverseIterator.class",
104+
"scala/runtime/NonLocalReturnControl.class",
105+
"scala/util/Sorting.class", "scala/util/Sorting$.class", // Contains @specialized annotation
106+
)
107+
108+
}

0 commit comments

Comments
 (0)