Merge pull request #8421 from eed3si9n/wip/matrix-cross

[2.x] projectMatrix crossVerson support
This commit is contained in:
eugene yokota 2025-12-16 23:45:43 -05:00 committed by GitHub
commit 26b5ee457f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 251 additions and 74 deletions

View File

@ -710,6 +710,7 @@ lazy val mainProj = (project in file("main"))
Compile / doc / sources := Nil,
mimaSettings,
mimaBinaryIssueFilters ++= Vector(
exclude[ReversedMissingMethodProblem]("sbt.ProjectMatrix.*"),
),
)
.dependsOn(lmCore, lmIvy, lmCoursierShadedPublishing)

View File

@ -81,6 +81,17 @@ sealed trait ProjectMatrix extends CompositeProject {
*/
def configure(transforms: (Project => Project)*): ProjectMatrix
/**
* If autoScalaLibrary is false, add non-Scala row.
* Otherwise, add custom rows for each scalaVersions.
*/
def customRow(
autoScalaLibrary: Boolean,
crossVersion: Option[CrossVersion],
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis]
)(process: Project => Project): ProjectMatrix
/**
* If autoScalaLibrary is false, add non-Scala row.
* Otherwise, add custom rows for each scalaVersions.
@ -116,8 +127,17 @@ sealed trait ProjectMatrix extends CompositeProject {
settings: Seq[Def.Setting[?]]
): ProjectMatrix
def jvmPlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Def.Setting[?]]
): ProjectMatrix
def jvmPlatform(crossVersion: CrossVersion, scalaVersions: Seq[String]): ProjectMatrix
def jvmPlatform(scalaVersions: Seq[String]): ProjectMatrix
def jvmPlatform(autoScalaLibrary: Boolean): ProjectMatrix
def jvmPlatform(autoScalaLibrary: Boolean, crossVersion: CrossVersion): ProjectMatrix
def jvmPlatform(scalaVersions: Seq[String], settings: Seq[Def.Setting[?]]): ProjectMatrix
def jvmPlatform(
scalaVersions: Seq[String],
@ -136,6 +156,14 @@ sealed trait ProjectMatrix extends CompositeProject {
): ProjectMatrix
def jvm: ProjectFinder
def jsPlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Def.Setting[?]]
): ProjectMatrix
def jsPlatform(crossVersion: CrossVersion, scalaVersions: Seq[String]): ProjectMatrix
def jsPlatform(scalaVersions: Seq[String]): ProjectMatrix
def jsPlatform(scalaVersions: Seq[String], settings: Seq[Def.Setting[?]]): ProjectMatrix
def jsPlatform(
@ -150,6 +178,14 @@ sealed trait ProjectMatrix extends CompositeProject {
): ProjectMatrix
def js: ProjectFinder
def nativePlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Def.Setting[?]]
): ProjectMatrix
def nativePlatform(crossVersion: CrossVersion, scalaVersions: Seq[String]): ProjectMatrix
def nativePlatform(scalaVersions: Seq[String]): ProjectMatrix
def nativePlatform(scalaVersions: Seq[String], settings: Seq[Def.Setting[?]]): ProjectMatrix
def nativePlatform(
@ -223,6 +259,17 @@ object ProjectMatrix {
def isSecondaryMatch(that: ProjectRow): Boolean =
VirtualAxis.isSecondaryMatch(this.axisValues, that.axisValues)
/** Calculate the idSuffix for this row */
def idSuffix(defAxes: Seq[VirtualAxis]): String = axisValues
.sortBy(_.suffixOrder)
.filterNot(isSortOfDefaultAxis(defAxes))
.map(_.idSuffix)
.mkString("")
private def isSortOfDefaultAxis(defAxes: Seq[VirtualAxis])(a: VirtualAxis): Boolean =
defAxes.exists: da =>
VirtualAxis.isPartialVersionEquals(da, a)
override def toString: String = s"ProjectRow($autoScalaLibrary, $axisValues)"
}
@ -259,19 +306,9 @@ object ProjectMatrix {
private def resolveProjectIds: Map[ProjectRow, String] = {
Map((for {
r <- rows
} yield {
val axes = r.axisValues
.sortBy(_.suffixOrder)
.filterNot(isSortOfDefaultAxis)
val idSuffix = axes.map(_.idSuffix).mkString("")
val childId = self.id + idSuffix
r -> childId
})*)
} yield r -> (self.id + r.idSuffix(defAxes)))*)
}
private def isSortOfDefaultAxis(a: VirtualAxis): Boolean =
defAxes exists { da => VirtualAxis.isPartialVersionEquals(da, a) }
private def resolveMappings: ListMap[ProjectRow, Project] = {
val projectIds = resolveProjectIds
val projects =
@ -428,41 +465,72 @@ object ProjectMatrix {
def setPlugins(ns: Plugins): ProjectMatrix = copy(plugins = ns)
override def jvmPlatform(scalaVersions: Seq[String]): ProjectMatrix =
jvmPlatform(scalaVersions, Nil)
override def jvmPlatform(autoScalaLibrary: Boolean): ProjectMatrix =
jvmPlatform(autoScalaLibrary, Nil, Nil)
override def jvmPlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Def.Setting[?]]
): ProjectMatrix =
jvmPlatform(true, scalaVersions, settings)
customRow(autoScalaLibrary, Some(crossVersion), scalaVersions, VirtualAxis.jvm +: axisValues):
p => p.settings(settings)
override def jvmPlatform(
autoScalaLibrary: Boolean,
scalaVersions: Seq[String],
settings: Seq[Def.Setting[?]]
): ProjectMatrix =
customRow(autoScalaLibrary, scalaVersions, Seq(VirtualAxis.jvm), { _.settings(settings) })
customRow(autoScalaLibrary, crossVersion = None, scalaVersions, Seq(VirtualAxis.jvm)): p =>
p.settings(settings)
override def jvmPlatform(
crossVersion: CrossVersion,
scalaVersions: Seq[String]
): ProjectMatrix =
jvmPlatform(autoScalaLibrary = true, crossVersion, scalaVersions, Nil, Nil)
override def jvmPlatform(
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Def.Setting[?]]
): ProjectMatrix =
customRow(true, scalaVersions, VirtualAxis.jvm +: axisValues, { _.settings(settings) })
customRow(
autoScalaLibrary = true,
crossVersion = None,
scalaVersions,
VirtualAxis.jvm +: axisValues
): p =>
p.settings(settings)
override def jvmPlatform(
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
configure: Project => Project
): ProjectMatrix =
customRow(true, scalaVersions, VirtualAxis.jvm +: axisValues, configure)
customRow(
autoScalaLibrary = true,
crossVersion = None,
scalaVersions,
VirtualAxis.jvm +: axisValues
)(configure)
override def jvmPlatform(scalaVersions: Seq[String]): ProjectMatrix =
jvmPlatform(autoScalaLibrary = true, scalaVersions, Nil)
override def jvmPlatform(autoScalaLibrary: Boolean): ProjectMatrix =
jvmPlatform(autoScalaLibrary, Nil, Nil)
override def jvmPlatform(autoScalaLibrary: Boolean, crossVersion: CrossVersion): ProjectMatrix =
jvmPlatform(autoScalaLibrary, crossVersion, Nil, Nil, Nil)
override def jvmPlatform(
scalaVersions: Seq[String],
settings: Seq[Def.Setting[?]]
): ProjectMatrix =
jvmPlatform(autoScalaLibrary = true, scalaVersions, settings)
override def jvm: ProjectFinder = new AxisBaseProjectFinder(Seq(VirtualAxis.jvm))
override def jsPlatform(scalaVersions: Seq[String]): ProjectMatrix =
jsPlatform(scalaVersions, Nil)
private def enableScalaJSPlugin(project: Project): Project =
project.enablePlugins(
scalajsPlugin.getOrElse(
@ -474,16 +542,25 @@ object ProjectMatrix {
)
)
override def jsPlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Def.Setting[?]]
): ProjectMatrix =
customRow(autoScalaLibrary, Some(crossVersion), scalaVersions, VirtualAxis.js +: axisValues):
p => enableScalaJSPlugin(p).settings(settings)
override def jsPlatform(
scalaVersions: Seq[String],
settings: Seq[Def.Setting[?]]
): ProjectMatrix =
customRow(
true,
scalaVersions,
Seq(VirtualAxis.js),
project => enableScalaJSPlugin(project).settings(settings)
)
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, Seq(VirtualAxis.js)):
p => enableScalaJSPlugin(p).settings(settings)
override def jsPlatform(crossVersion: CrossVersion, scalaVersions: Seq[String]): ProjectMatrix =
jsPlatform(autoScalaLibrary = true, crossVersion, scalaVersions, Nil, Nil)
override def jsPlatform(
scalaVersions: Seq[String],
@ -491,11 +568,12 @@ object ProjectMatrix {
settings: Seq[Def.Setting[?]]
): ProjectMatrix =
customRow(
true,
autoScalaLibrary = true,
crossVersion = None,
scalaVersions,
VirtualAxis.js +: axisValues,
project => enableScalaJSPlugin(project).settings(settings)
)
VirtualAxis.js +: axisValues
): p =>
enableScalaJSPlugin(p).settings(settings)
override def jsPlatform(
scalaVersions: Seq[String],
@ -503,11 +581,15 @@ object ProjectMatrix {
configure: Project => Project
): ProjectMatrix =
customRow(
true,
autoScalaLibrary = true,
crossVersion = None,
scalaVersions,
VirtualAxis.js +: axisValues,
project => configure(enableScalaJSPlugin(project))
)
VirtualAxis.js +: axisValues
): p =>
configure(enableScalaJSPlugin(p))
override def jsPlatform(scalaVersions: Seq[String]): ProjectMatrix =
jsPlatform(scalaVersions, Nil)
override def defaultAxes(axes: VirtualAxis*): ProjectMatrix =
copy(defAxes = axes.toSeq)
@ -523,9 +605,6 @@ object ProjectMatrix {
override def native: ProjectFinder = new AxisBaseProjectFinder(Seq(VirtualAxis.native))
override def nativePlatform(scalaVersions: Seq[String]): ProjectMatrix =
nativePlatform(scalaVersions, Nil)
private def enableScalaNativePlugin(project: Project): Project =
project.enablePlugins(
nativePlugin.getOrElse(
@ -537,16 +616,38 @@ object ProjectMatrix {
)
)
override def nativePlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Def.Setting[?]]
): ProjectMatrix =
customRow(
autoScalaLibrary,
Some(crossVersion),
scalaVersions,
VirtualAxis.native +: axisValues
): p =>
enableScalaNativePlugin(p).settings(settings)
override def nativePlatform(
scalaVersions: Seq[String],
settings: Seq[Def.Setting[?]]
): ProjectMatrix =
customRow(
true,
autoScalaLibrary = true,
crossVersion = None,
scalaVersions,
Seq(VirtualAxis.native),
project => enableScalaNativePlugin(project).settings(settings)
)
Seq(VirtualAxis.native)
): p =>
enableScalaNativePlugin(p).settings(settings)
override def nativePlatform(
crossVersion: CrossVersion,
scalaVersions: Seq[String]
): ProjectMatrix =
nativePlatform(autoScalaLibrary = true, crossVersion, scalaVersions, Nil, Nil)
override def nativePlatform(
scalaVersions: Seq[String],
@ -554,11 +655,12 @@ object ProjectMatrix {
settings: Seq[Def.Setting[?]]
): ProjectMatrix =
customRow(
true,
autoScalaLibrary = true,
crossVersion = None,
scalaVersions,
VirtualAxis.native +: axisValues,
project => enableScalaNativePlugin(project).settings(settings)
)
VirtualAxis.native +: axisValues
): p =>
enableScalaNativePlugin(p).settings(settings)
override def nativePlatform(
scalaVersions: Seq[String],
@ -566,11 +668,15 @@ object ProjectMatrix {
configure: Project => Project
): ProjectMatrix =
customRow(
true,
autoScalaLibrary = true,
crossVersion = None,
scalaVersions,
VirtualAxis.native +: axisValues,
project => configure(enableScalaNativePlugin(project))
)
VirtualAxis.native +: axisValues
): p =>
configure(enableScalaNativePlugin(p))
override def nativePlatform(scalaVersions: Seq[String]): ProjectMatrix =
nativePlatform(scalaVersions, Nil)
def nativePlugin: Try[AutoPlugin] = {
import ReflectionUtil.*
@ -606,23 +712,59 @@ object ProjectMatrix {
.getOrElse(sys.error(s"project matching $axisValues and $autoScalaLibrary was not found"))
}
/**
* If autoScalaLibrary is false, add non-Scala row.
* Otherwise, add custom rows for each scalaVersions.
*/
override def customRow(
autoScalaLibrary: Boolean,
crossVersion: Option[CrossVersion],
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis]
)(
process: Project => Project
): ProjectMatrix =
val process1 = crossVersion match
case Some(cv) => (p: Project) => process(p.settings(Keys.crossVersion := cv))
case None => process
if autoScalaLibrary then
scalaVersions.foldLeft(this: ProjectMatrix): (acc, sv) =>
val scalaAxis =
if crossVersion == Some(CrossVersion.full) then VirtualAxis.scalaVersionAxis(sv, sv)
else VirtualAxis.scalaABIVersion(sv)
acc.customRow(autoScalaLibrary, axisValues ++ Seq(scalaAxis), process1)
else customRow(autoScalaLibrary, axisValues ++ Seq(VirtualAxis.jvm), process1)
override def customRow(
autoScalaLibrary: Boolean,
axisValues: Seq[VirtualAxis],
process: Project => Project
): ProjectMatrix =
val newRow: ProjectRow = ProjectRow(autoScalaLibrary, axisValues, process)
copy(rows = this.rows :+ newRow)
override def customRow(
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Def.Setting[?]]
): ProjectMatrix = customRow(true, scalaVersions, axisValues, { _.settings(settings) })
): ProjectMatrix =
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, axisValues): p =>
p.settings(settings)
override def customRow(
autoScalaLibrary: Boolean,
axisValues: Seq[VirtualAxis],
settings: Seq[Def.Setting[?]]
): ProjectMatrix = customRow(autoScalaLibrary, Nil, axisValues, { _.settings(settings) })
): ProjectMatrix =
customRow(autoScalaLibrary, crossVersion = None, Nil, axisValues): (p) =>
p.settings(settings)
override def customRow(
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
process: Project => Project
): ProjectMatrix = customRow(true, scalaVersions, axisValues, process)
): ProjectMatrix =
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, axisValues)(process)
override def customRow(
autoScalaLibrary: Boolean,
@ -630,26 +772,7 @@ object ProjectMatrix {
axisValues: Seq[VirtualAxis],
process: Project => Project
): ProjectMatrix =
if (autoScalaLibrary) {
scalaVersions.foldLeft(this: ProjectMatrix) { (acc, sv) =>
acc.customRow(
autoScalaLibrary,
axisValues ++ Seq(VirtualAxis.scalaABIVersion(sv)),
process
)
}
} else {
customRow(autoScalaLibrary, axisValues ++ Seq(VirtualAxis.jvm), process)
}
override def customRow(
autoScalaLibrary: Boolean,
axisValues: Seq[VirtualAxis],
process: Project => Project
): ProjectMatrix = {
val newRow: ProjectRow = new ProjectRow(autoScalaLibrary, axisValues, process)
copy(rows = this.rows :+ newRow)
}
customRow(autoScalaLibrary, crossVersion = None, scalaVersions, axisValues)(process)
override def finder(axisValues: VirtualAxis*): ProjectFinder =
new AxisBaseProjectFinder(axisValues.toSeq)

View File

@ -0,0 +1,49 @@
lazy val scala3_LTS = "3.3.5"
lazy val scala3_current = "3.7.4"
lazy val check = taskKey[Unit]("")
organization := "com.example"
version := "0.1.0-SNAPSHOT"
lazy val root = (project in file("."))
.aggregate((core.projectRefs ++ app.projectRefs)*)
.settings(
)
lazy val app = (projectMatrix in file("app"))
.aggregate(core, intf)
.dependsOn(core, intf)
.settings(
name := "app",
)
.jvmPlatform(
crossVersion = CrossVersion.full,
scalaVersions = Seq(scala3_LTS, scala3_current),
)
lazy val core = (projectMatrix in file("core"))
.settings(
check := {
assert(moduleName.value == "core", s"moduleName is ${moduleName.value}")
assert(projectMatrixBaseDirectory.value == file("core"))
assert(projectID.value.crossVersion == CrossVersion.full, s"crossVersion is ${projectID.value.crossVersion}")
},
)
.jvmPlatform(
crossVersion = CrossVersion.full,
scalaVersions = Seq(scala3_LTS, scala3_current)
)
lazy val intf = (projectMatrix in file("intf"))
.settings(
check := {
assert(moduleName.value == "intf", s"moduleName is ${moduleName.value}")
assert(projectMatrixBaseDirectory.value == file("intf"))
},
)
.jvmPlatform(
autoScalaLibrary = false,
crossVersion = CrossVersion.disabled,
)
lazy val core_3_LTS = core.jvm(scala3_LTS)

View File

@ -0,0 +1,4 @@
> packageBin
$ exists target/**/app_3.3.5-0.1.0-SNAPSHOT.jar
$ exists target/**/app_3.7.4-0.1.0-SNAPSHOT.jar
> core3_7_4/check