From b42f3938a5835952a70610ef6ee6ac997dafef79 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sat, 22 Aug 2020 15:13:47 -0400 Subject: [PATCH 1/2] implement secondary match --- src/main/scala/sbt/VirtualAxis.scala | 52 +++++++++++++++---- .../scala/sbt/internal/ProjectMatrix.scala | 6 ++- .../projectMatrix/jvm-sandwich/build.sbt | 17 ++++++ .../jvm-sandwich/project/build.properties | 1 + .../jvm-sandwich/project/plugins.sbt | 6 +++ src/sbt-test/projectMatrix/jvm-sandwich/test | 2 + 6 files changed, 74 insertions(+), 10 deletions(-) create mode 100644 src/sbt-test/projectMatrix/jvm-sandwich/build.sbt create mode 100644 src/sbt-test/projectMatrix/jvm-sandwich/project/build.properties create mode 100644 src/sbt-test/projectMatrix/jvm-sandwich/project/plugins.sbt create mode 100644 src/sbt-test/projectMatrix/jvm-sandwich/test diff --git a/src/main/scala/sbt/VirtualAxis.scala b/src/main/scala/sbt/VirtualAxis.scala index 2b2648909..7d831682b 100644 --- a/src/main/scala/sbt/VirtualAxis.scala +++ b/src/main/scala/sbt/VirtualAxis.scala @@ -23,16 +23,50 @@ object VirtualAxis { abstract class StrongAxis extends VirtualAxis - def isMatch(lhs: Seq[VirtualAxis], rhs: Seq[VirtualAxis]): Boolean = { - def isCompatible(v: VirtualAxis, stack: Seq[VirtualAxis]): Boolean = - v match { - case v: WeakAxis => - val clazz = v.getClass - stack.contains(v) || !stack.exists(_.getClass == clazz) - case v: StrongAxis => - stack.contains(v) + def isMatch(lhs: Seq[VirtualAxis], rhs: Seq[VirtualAxis]): Boolean = + lhs.forall(isStronglyCompatible(_, rhs)) && rhs.forall(isStronglyCompatible(_, lhs)) + + private[sbt] def isStronglyCompatible(v: VirtualAxis, stack: Seq[VirtualAxis]): Boolean = + v match { + case v: WeakAxis => + val clazz = v.getClass + stack.contains(v) || !stack.exists(_.getClass == clazz) + case v: StrongAxis => + stack.contains(v) + } + + def isSecondaryMatch(lhs: Seq[VirtualAxis], rhs: Seq[VirtualAxis]): Boolean = + lhs.forall(isSecondaryCompatible(_, rhs)) && rhs.forall(isSecondaryCompatible(_, lhs)) + + def isSecondaryCompatible(v: VirtualAxis, stack: Seq[VirtualAxis]): Boolean = + v match { + case v: ScalaVersionAxis => + val thatSVOpt = (stack collect { + case x: ScalaVersionAxis => x + }).headOption + thatSVOpt match { + case Some(ScalaVersionAxis(sv, _)) => + (v.scalaVersion == sv) || + isScala2Scala3Sandwich(partialVersion(v.scalaVersion), partialVersion(sv)) + case _ => true + } + case _ => + isStronglyCompatible(v, stack) + } + + private[sbt] def isScala2Scala3Sandwich(sbv1: Option[(Long, Long)], sbv2: Option[(Long, Long)]): Boolean = { + def str(x: Option[(Long, Long)]): String = + x match { + case Some((a, b)) => s"$a.$b" + case _ => "0.0" } - lhs.forall(isCompatible(_, rhs)) && rhs.forall(isCompatible(_, lhs)) + isScala2Scala3Sandwich(str(sbv1), str(sbv2)) + } + + private[sbt] def isScala2Scala3Sandwich(sbv1: String, sbv2: String): Boolean = { + def compare(a: String, b: String): Boolean = + a == "2.13" && (b.startsWith("0.") || b.startsWith("3.0")) + compare(sbv1, sbv2) || compare(sbv2, sbv1) } case class ScalaVersionAxis(scalaVersion: String, value: String) extends WeakAxis { diff --git a/src/main/scala/sbt/internal/ProjectMatrix.scala b/src/main/scala/sbt/internal/ProjectMatrix.scala index d4e43afc2..50304ddff 100644 --- a/src/main/scala/sbt/internal/ProjectMatrix.scala +++ b/src/main/scala/sbt/internal/ProjectMatrix.scala @@ -163,6 +163,9 @@ object ProjectMatrix { def isMatch(that: ProjectRow): Boolean = VirtualAxis.isMatch(this.axisValues, that.axisValues) + def isSecondaryMatch(that: ProjectRow): Boolean = + VirtualAxis.isSecondaryMatch(this.axisValues, that.axisValues) + override def toString: String = s"ProjectRow($autoScalaLibrary, $axisValues)" } @@ -275,7 +278,8 @@ object ProjectMatrix { // resolve to the closest match for the given row private[sbt] def resolveMatch(thatRow: ProjectRow): ProjectReference = - rows.find(r => r.isMatch(thatRow)) match { + (rows.find(r => r.isMatch(thatRow)) orElse + rows.find(r => r.isSecondaryMatch(thatRow))) match { case Some(r) => LocalProject(resolveProjectIds(r)) case _ => sys.error(s"no rows were found in $id matching $thatRow: $rows") } diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/build.sbt b/src/sbt-test/projectMatrix/jvm-sandwich/build.sbt new file mode 100644 index 000000000..eb3fb0f85 --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/build.sbt @@ -0,0 +1,17 @@ +val dottyVersion = "0.23.0" +ThisBuild / resolvers += "scala-integration" at "https://scala-ci.typesafe.com/artifactory/scala-integration/" +// TODO use 2.13.4 when it's out +lazy val scala213 = "2.13.4-bin-aeee8f0" + +lazy val fooApp = (projectMatrix in file("foo-app")) + .dependsOn(fooCore) + .settings( + name := "app", + ) + .jvmPlatform(scalaVersions = Seq(dottyVersion)) + +lazy val fooCore = (projectMatrix in file("foo-core")) + .settings( + name := "core", + ) + .jvmPlatform(scalaVersions = Seq("2.13.3", "2.12.12")) diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/project/build.properties b/src/sbt-test/projectMatrix/jvm-sandwich/project/build.properties new file mode 100644 index 000000000..0837f7a13 --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.3.13 diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/project/plugins.sbt b/src/sbt-test/projectMatrix/jvm-sandwich/project/plugins.sbt new file mode 100644 index 000000000..c129c032b --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/project/plugins.sbt @@ -0,0 +1,6 @@ +sys.props.get("plugin.version") match { + case Some(x) => addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % x) + case _ => sys.error("""|The system property 'plugin.version' is not defined. + |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) +} +addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.4.1") diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/test b/src/sbt-test/projectMatrix/jvm-sandwich/test new file mode 100644 index 000000000..33560c709 --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/test @@ -0,0 +1,2 @@ +> fooAppJVM0_23/compile + From ba8d3c7edc325e419923d1cdac9dafa051a569ff Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Sun, 23 Aug 2020 06:00:09 -0400 Subject: [PATCH 2/2] Backport Scala 2.13-3.x inter project dependency Ref https://github.com/sbt/sbt/pull/5767 --- .../scala/sbt/internal/ProjectMatrix.scala | 40 ++++++++++++++++- .../jvm-sandwich/bar-app/D.scala | 5 +++ .../jvm-sandwich/bar-core/C.scala | 5 +++ .../jvm-sandwich/baz-app/F.scala | 5 +++ .../jvm-sandwich/baz-core/E.scala | 5 +++ .../projectMatrix/jvm-sandwich/build.sbt | 43 +++++++++++++++++-- .../jvm-sandwich/foo-app/B.scala | 5 +++ .../jvm-sandwich/foo-core/A.scala | 5 +++ src/sbt-test/projectMatrix/jvm-sandwich/test | 3 ++ 9 files changed, 112 insertions(+), 4 deletions(-) create mode 100644 src/sbt-test/projectMatrix/jvm-sandwich/bar-app/D.scala create mode 100644 src/sbt-test/projectMatrix/jvm-sandwich/bar-core/C.scala create mode 100644 src/sbt-test/projectMatrix/jvm-sandwich/baz-app/F.scala create mode 100644 src/sbt-test/projectMatrix/jvm-sandwich/baz-core/E.scala create mode 100644 src/sbt-test/projectMatrix/jvm-sandwich/foo-app/B.scala create mode 100644 src/sbt-test/projectMatrix/jvm-sandwich/foo-core/A.scala diff --git a/src/main/scala/sbt/internal/ProjectMatrix.scala b/src/main/scala/sbt/internal/ProjectMatrix.scala index 50304ddff..ddfcc5127 100644 --- a/src/main/scala/sbt/internal/ProjectMatrix.scala +++ b/src/main/scala/sbt/internal/ProjectMatrix.scala @@ -249,7 +249,8 @@ object ProjectMatrix { crossTarget := Keys.target.value, sourceDirectory := base.getAbsoluteFile / "src", inConfig(Compile)(makeSources(nonScalaDirSuffix, svDirSuffix)), - inConfig(Test)(makeSources(nonScalaDirSuffix, svDirSuffix)) + inConfig(Test)(makeSources(nonScalaDirSuffix, svDirSuffix)), + projectDependencies := projectDependenciesTask.value, ) .settings(self.settings) .configure(transforms: _*) @@ -258,6 +259,43 @@ object ProjectMatrix { }): _*) } + // backport of https://github.com/sbt/sbt/pull/5767 + def projectDependenciesTask: Def.Initialize[Task[Seq[ModuleID]]] = + Def.task { + val orig = projectDependencies.value + val sbv = scalaBinaryVersion.value + val ref = thisProjectRef.value + val data = settingsData.value + val deps = buildDependencies.value + val sbtV = VersionNumber(sbtVersion.value) + + if (sbtV._1.getOrElse(0L) == 1 && (sbtV._2.getOrElse(0L) < 4)) { + deps.classpath(ref) flatMap { dep => + val depProjIdOpt = (dep.project / projectID).get(data) + val depSVOpt = (dep.project / scalaVersion).get(data) + val depSBVOpt = (dep.project / scalaBinaryVersion).get(data) + val depCrossOpt = (dep.project / crossVersion).get(data) + (depProjIdOpt, depSVOpt, depSBVOpt, depCrossOpt) match { + case (Some(depProjId), Some(depSV), Some(depSBV), Some(depCross)) => + if (sbv == depSBV || depCross != CrossVersion.binary) + Some( + depProjId.withConfigurations(dep.configuration).withExplicitArtifacts(Vector.empty) + ) + else if (VirtualAxis.isScala2Scala3Sandwich(sbv, depSBV) && depCross == CrossVersion.binary) + Some( + depProjId + .withCrossVersion(CrossVersion.constant(depSBV)) + .withConfigurations(dep.configuration) + .withExplicitArtifacts(Vector.empty) + ) + else sys.error(s"scalaBinaryVersion mismatch: expected $sbv but found ${depSBV}") + case _ => None + } + } + } else { + orig + } + } override lazy val componentProjects: Seq[Project] = resolvedMappings.values.toList diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/bar-app/D.scala b/src/sbt-test/projectMatrix/jvm-sandwich/bar-app/D.scala new file mode 100644 index 000000000..b937ae06c --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/bar-app/D.scala @@ -0,0 +1,5 @@ +package example + +object D { + val x = C.x +} diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/bar-core/C.scala b/src/sbt-test/projectMatrix/jvm-sandwich/bar-core/C.scala new file mode 100644 index 000000000..4d4fcc6df --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/bar-core/C.scala @@ -0,0 +1,5 @@ +package example + +object C { + val x = 1 +} diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/baz-app/F.scala b/src/sbt-test/projectMatrix/jvm-sandwich/baz-app/F.scala new file mode 100644 index 000000000..5035ba457 --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/baz-app/F.scala @@ -0,0 +1,5 @@ +package example + +object F { + val x = E.x +} diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/baz-core/E.scala b/src/sbt-test/projectMatrix/jvm-sandwich/baz-core/E.scala new file mode 100644 index 000000000..cdac7bd76 --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/baz-core/E.scala @@ -0,0 +1,5 @@ +package example + +object E { + val x = 1 +} diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/build.sbt b/src/sbt-test/projectMatrix/jvm-sandwich/build.sbt index eb3fb0f85..9a34ee49b 100644 --- a/src/sbt-test/projectMatrix/jvm-sandwich/build.sbt +++ b/src/sbt-test/projectMatrix/jvm-sandwich/build.sbt @@ -1,3 +1,5 @@ +lazy val check = taskKey[Unit]("") + val dottyVersion = "0.23.0" ThisBuild / resolvers += "scala-integration" at "https://scala-ci.typesafe.com/artifactory/scala-integration/" // TODO use 2.13.4 when it's out @@ -6,12 +8,47 @@ lazy val scala213 = "2.13.4-bin-aeee8f0" lazy val fooApp = (projectMatrix in file("foo-app")) .dependsOn(fooCore) .settings( - name := "app", + name := "foo app", ) .jvmPlatform(scalaVersions = Seq(dottyVersion)) lazy val fooCore = (projectMatrix in file("foo-core")) .settings( - name := "core", + name := "foo core", ) - .jvmPlatform(scalaVersions = Seq("2.13.3", "2.12.12")) + .jvmPlatform(scalaVersions = Seq(scala213, "2.12.12")) + +lazy val barApp = (projectMatrix in file("bar-app")) + .dependsOn(barCore) + .settings( + name := "bar app", + ) + .jvmPlatform(scalaVersions = Seq(scala213)) + +lazy val barCore = (projectMatrix in file("bar-core")) + .settings( + name := "bar core", + ) + .jvmPlatform(scalaVersions = Seq(dottyVersion)) + +// choose 2.13 when bazCore offers both 2.13 and Dotty +lazy val bazApp = (projectMatrix in file("baz-app")) + .dependsOn(bazCore) + .settings( + name := "baz app", + check := { + val cp = (Compile / fullClasspath).value + .map(_.data.getName) + + assert(cp.contains("baz-core_2.13-0.1.0-SNAPSHOT.jar"), s"$cp") + assert(!cp.contains("baz-core_0.23-0.1.0-SNAPSHOT.jar"), s"$cp") + }, + ) + .jvmPlatform(scalaVersions = Seq(scala213)) + +lazy val bazCore = (projectMatrix in file("baz-core")) + .settings( + name := "baz core", + exportJars := true, + ) + .jvmPlatform(scalaVersions = Seq(scala213, dottyVersion)) diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/foo-app/B.scala b/src/sbt-test/projectMatrix/jvm-sandwich/foo-app/B.scala new file mode 100644 index 000000000..ed82c07d1 --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/foo-app/B.scala @@ -0,0 +1,5 @@ +package example + +object B { + val x = A.x +} diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/foo-core/A.scala b/src/sbt-test/projectMatrix/jvm-sandwich/foo-core/A.scala new file mode 100644 index 000000000..be4b82a9f --- /dev/null +++ b/src/sbt-test/projectMatrix/jvm-sandwich/foo-core/A.scala @@ -0,0 +1,5 @@ +package example + +object A { + val x = 1 +} diff --git a/src/sbt-test/projectMatrix/jvm-sandwich/test b/src/sbt-test/projectMatrix/jvm-sandwich/test index 33560c709..62f41e9d4 100644 --- a/src/sbt-test/projectMatrix/jvm-sandwich/test +++ b/src/sbt-test/projectMatrix/jvm-sandwich/test @@ -1,2 +1,5 @@ > fooAppJVM0_23/compile +> barAppJVM2_13/compile + +> bazAppJVM2_13/check