Skip to content
This repository was archived by the owner on Aug 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ lazy val root = (project in file("."))
.enablePlugins(SbtPlugin)
.settings(
name := "sbt-projectmatrix",
pluginCrossBuild / sbtVersion := "1.2.8",
scriptedSbt := "1.9.6",
scalacOptions := Seq("-deprecation", "-unchecked"),
pluginCrossBuild / sbtVersion := "1.5.8",
scriptedSbt := "1.10.11",
scalacOptions := Seq("-deprecation", "-unchecked", "-Xsource:3"),
scriptedLaunchOpts := { scriptedLaunchOpts.value ++
Seq("-Xmx1024M", "-Dplugin.version=" + version.value)
},
Expand Down
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.10.5
sbt.version=1.10.11
215 changes: 151 additions & 64 deletions src/main/scala/sbt/internal/ProjectMatrix.scala
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ sealed trait ProjectMatrix extends CompositeProject {
* 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

def customRow(
autoScalaLibrary: Boolean,
scalaVersions: Seq[String],
Expand Down Expand Up @@ -108,20 +114,42 @@ sealed trait ProjectMatrix extends CompositeProject {
settings: Seq[Setting[_]]
): ProjectMatrix

def jvmPlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[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[Setting[_]]): ProjectMatrix
def jvmPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], settings: Seq[Setting[_]]): ProjectMatrix
def jvmPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], configure: Project => Project): ProjectMatrix
def jvmPlatform(autoScalaLibrary: Boolean, scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix
def jvm: ProjectFinder

def jsPlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Setting[_]]): ProjectMatrix
def jsPlatform(crossVersion: CrossVersion, scalaVersions: Seq[String]): ProjectMatrix
def jsPlatform(scalaVersions: Seq[String]): ProjectMatrix
def jsPlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix
def jsPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], settings: Seq[Setting[_]]): ProjectMatrix
def jsPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], configure: Project => Project): ProjectMatrix
def js: ProjectFinder

def nativePlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Setting[_]]): ProjectMatrix
def nativePlatform(crossVersion: CrossVersion, scalaVersions: Seq[String]): ProjectMatrix
def nativePlatform(scalaVersions: Seq[String]): ProjectMatrix
def nativePlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix
def nativePlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], settings: Seq[Setting[_]]): ProjectMatrix
Expand Down Expand Up @@ -185,6 +213,15 @@ 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)"
}

Expand Down Expand Up @@ -220,18 +257,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

Expand Down Expand Up @@ -385,46 +413,71 @@ object ProjectMatrix {

def setPlugins(ns: Plugins): ProjectMatrix = copy(plugins = ns)

override def jvmPlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Setting[_]]): ProjectMatrix =
customRow(autoScalaLibrary, Some(crossVersion), scalaVersions, VirtualAxis.jvm +: axisValues) {
case project => project.settings(settings)
}
override def jvmPlatform(autoScalaLibrary: Boolean, scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(autoScalaLibrary, crossVersion = None, scalaVersions, Seq(VirtualAxis.jvm)) {
case project => project.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[Setting[_]]): ProjectMatrix =
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, VirtualAxis.jvm +: axisValues) {
case project => project.settings(settings)
}
override def jvmPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], configure: Project => Project): ProjectMatrix =
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, VirtualAxis.jvm +: axisValues)(configure)
override def jvmPlatform(scalaVersions: Seq[String]): ProjectMatrix =
jvmPlatform(scalaVersions, Nil)
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[Setting[_]]): ProjectMatrix =
jvmPlatform(true, scalaVersions, settings)
override def jvmPlatform(autoScalaLibrary: Boolean, scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(autoScalaLibrary, scalaVersions, Seq(VirtualAxis.jvm), { _.settings(settings) })

override def jvmPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(true, scalaVersions, VirtualAxis.jvm +: axisValues, {_.settings(settings)})

override def jvmPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], configure: Project => Project): ProjectMatrix =
customRow(true, scalaVersions, VirtualAxis.jvm +: axisValues, configure)
jvmPlatform(autoScalaLibrary = true, scalaVersions, settings)

override def jvm: ProjectFinder = new AxisBaseProjectFinder(Seq(VirtualAxis.jvm))

override def jsPlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Setting[_]]): ProjectMatrix =
customRow(autoScalaLibrary, Some(crossVersion), scalaVersions, VirtualAxis.js +: axisValues) {
case project => enableScalaJSPlugin(project).settings(settings)
}
override def jsPlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, Seq(VirtualAxis.js)) {
case project => enableScalaJSPlugin(project).settings(settings)
}
override def jsPlatform(crossVersion: CrossVersion, scalaVersions: Seq[String]): ProjectMatrix =
jsPlatform(autoScalaLibrary = true, crossVersion, scalaVersions, Nil, Nil)
override def jsPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, VirtualAxis.js +: axisValues) {
case project => enableScalaJSPlugin(project).settings(settings)
}
override def jsPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], configure: Project => Project): ProjectMatrix =
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, VirtualAxis.js +: axisValues) {
case project => configure(enableScalaJSPlugin(project))
}
override def jsPlatform(scalaVersions: Seq[String]): ProjectMatrix =
jsPlatform(scalaVersions, Nil)

private def enableScalaJSPlugin(project: Project): Project =
private def enableScalaJSPlugin(project: Project): Project =
project.enablePlugins(scalajsPlugin(this.getClass.getClassLoader).getOrElse(
sys.error("""Scala.js plugin was not found. Add the sbt-scalajs plugin into project/plugins.sbt:
| addSbtPlugin("org.scala-js" % "sbt-scalajs" % "x.y.z")
|""".stripMargin)
))


override def jsPlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(true, scalaVersions, Seq(VirtualAxis.js),
project => enableScalaJSPlugin(project).settings(settings))

override def jsPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(true, scalaVersions, VirtualAxis.js +: axisValues,
project => enableScalaJSPlugin(project).settings(settings))

override def jsPlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], configure: Project => Project): ProjectMatrix =
customRow(true, scalaVersions, VirtualAxis.js +: axisValues,
project => configure(enableScalaJSPlugin(project)))

override def defaultAxes(axes: VirtualAxis*): ProjectMatrix =
copy(defAxes = axes.toSeq)

Expand All @@ -439,26 +492,39 @@ object ProjectMatrix {

override def native: ProjectFinder = new AxisBaseProjectFinder(Seq(VirtualAxis.native))

override def nativePlatform(
autoScalaLibrary: Boolean,
crossVersion: CrossVersion,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
settings: Seq[Setting[_]]): ProjectMatrix =
customRow(autoScalaLibrary, Some(crossVersion), scalaVersions, VirtualAxis.native +: axisValues) {
case project => enableScalaNativePlugin(project).settings(settings)
}
override def nativePlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, Seq(VirtualAxis.native)) {
case project => enableScalaNativePlugin(project).settings(settings)
}
override def nativePlatform(crossVersion: CrossVersion, scalaVersions: Seq[String]): ProjectMatrix =
nativePlatform(autoScalaLibrary = true, crossVersion, scalaVersions, Nil, Nil)
override def nativePlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, VirtualAxis.native +: axisValues) {
case project => enableScalaNativePlugin(project).settings(settings)
}
override def nativePlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], configure: Project => Project): ProjectMatrix =
customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, VirtualAxis.native +: axisValues) {
case project => configure(enableScalaNativePlugin(project))
}
override def nativePlatform(scalaVersions: Seq[String]): ProjectMatrix =
nativePlatform(scalaVersions, Nil)

private def enableScalaNativePlugin(project: Project): Project =
private def enableScalaNativePlugin(project: Project): Project =
project.enablePlugins(nativePlugin(this.getClass.getClassLoader).getOrElse(
sys.error("""Scala Native plugin was not found. Add the sbt-scala-native plugin into project/plugins.sbt:
| addSbtPlugin("org.scala-native" % "sbt-scala-native" % "x.y.z")
|""".stripMargin)
))


override def nativePlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(true, scalaVersions, Seq(VirtualAxis.native), project => enableScalaNativePlugin(project).settings(settings))

override def nativePlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], settings: Seq[Setting[_]]): ProjectMatrix =
customRow(true, scalaVersions, VirtualAxis.native +: axisValues, project => enableScalaNativePlugin(project).settings(settings))

override def nativePlatform(scalaVersions: Seq[String], axisValues: Seq[VirtualAxis], configure: Project => Project): ProjectMatrix =
customRow(true, scalaVersions, VirtualAxis.native +: axisValues, project => configure(enableScalaNativePlugin(project)))

def nativePlugin(classLoader: ClassLoader): Try[AutoPlugin] = {
import sbtprojectmatrix.ReflectionUtil._
withContextClassloader(classLoader) { loader =>
Expand Down Expand Up @@ -488,46 +554,67 @@ 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],
settings: Seq[Setting[_]]
): ProjectMatrix = customRow(true, scalaVersions, axisValues, { _.settings(settings) })
axisValues: Seq[VirtualAxis])(process: Project => Project): ProjectMatrix = {
val process1 = crossVersion match {
case Some(cv) => (project: Project) => process(project.settings(Keys.crossVersion := cv))
case None => process
}
if (autoScalaLibrary)
scalaVersions.foldLeft(this: ProjectMatrix) { (acc, sv) =>
val scalaAxis =
if (crossVersion == Some(CrossVersion.full)) 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],
settings: Seq[Setting[_]]
): ProjectMatrix = customRow(autoScalaLibrary, Nil, axisValues, { _.settings(settings) })
process: Project => Project
): ProjectMatrix = {
val newRow: ProjectRow = new ProjectRow(autoScalaLibrary, axisValues, process)
copy(rows = this.rows :+ newRow)
}

override def customRow(
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
process: Project => Project
): ProjectMatrix = customRow(true, scalaVersions, axisValues, process)
settings: Seq[Setting[_]]
): ProjectMatrix = customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, axisValues) {
case project => project.settings(settings)
}

override def customRow(
autoScalaLibrary: Boolean,
axisValues: Seq[VirtualAxis],
settings: Seq[Setting[_]]
): ProjectMatrix = customRow(autoScalaLibrary, crossVersion = None, Nil, axisValues) {
case project => project.settings(settings)
}

override def customRow(
scalaVersions: Seq[String],
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)
}
): ProjectMatrix = customRow(autoScalaLibrary = true, crossVersion = None, scalaVersions, axisValues)(process)

override def customRow(
autoScalaLibrary: Boolean,
scalaVersions: Seq[String],
axisValues: Seq[VirtualAxis],
process: Project => Project
): ProjectMatrix = {
val newRow: ProjectRow = new ProjectRow(autoScalaLibrary, axisValues, process)
copy(rows = this.rows :+ newRow)
}
): ProjectMatrix = customRow(autoScalaLibrary, crossVersion = None, scalaVersions, axisValues)(process)

override def finder(axisValues: VirtualAxis*): ProjectFinder =
new AxisBaseProjectFinder(axisValues.toSeq)
Expand Down
49 changes: 49 additions & 0 deletions src/sbt-test/projectMatrix/full/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
lazy val scala3_LTS = "3.3.5"
lazy val scala3_current = "3.6.4"
lazy val check = taskKey[Unit]("")

ThisBuild / organization := "com.example"
ThisBuild / 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)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package a

class Core {
}

object Core extends Core
Loading