mirror of https://github.com/sbt/sbt.git
implement VirtualAxis
Fixes https://github.com/sbt/sbt-projectmatrix/issues/13 Fixes https://github.com/sbt/sbt-projectmatrix/issues/14 This adds the notion of VirutalAxis that allows the matrix to define strong or weak axis.
This commit is contained in:
parent
b054de52e6
commit
88fd75bc72
|
|
@ -107,31 +107,50 @@ This will create subproject `coreNative2_11`.
|
|||
The rows can also be used for parallel cross-library building.
|
||||
For example, if you want to build against Config 1.2 and Config 1.3, you can do something like this:
|
||||
|
||||
In `project/ConfigAxis.scala`:
|
||||
|
||||
```scala
|
||||
import sbt._
|
||||
|
||||
case class ConfigAxis(idSuffix: String, directorySuffix: String) extends VirtualAxis.WeakAxis {
|
||||
}
|
||||
```
|
||||
|
||||
In `build.sbt`:
|
||||
|
||||
```scala
|
||||
ThisBuild / organization := "com.example"
|
||||
ThisBuild / version := "0.1.0-SNAPSHOT"
|
||||
|
||||
lazy val core = (projectMatrix in file("core"))
|
||||
lazy val config12 = ConfigAxis("Config1_2", "config1.2")
|
||||
lazy val config13 = ConfigAxis("Config1_3", "config1.3")
|
||||
|
||||
lazy val scala212 = "2.12.10"
|
||||
lazy val scala211 = "2.11.12"
|
||||
|
||||
lazy val app = (projectMatrix in file("app"))
|
||||
.settings(
|
||||
name := "core"
|
||||
name := "app"
|
||||
)
|
||||
.crossLibrary(
|
||||
scalaVersions = Seq("2.12.8", "2.11.12"),
|
||||
suffix = "Config1.2",
|
||||
settings = Seq(
|
||||
.customRow(
|
||||
scalaVersions = Seq(scala212, scala211),
|
||||
axisValues = Seq(config12, VirtualAxis.jvm),
|
||||
_.settings(
|
||||
moduleName := name.value + "_config1.2",
|
||||
libraryDependencies += "com.typesafe" % "config" % "1.2.1"
|
||||
)
|
||||
)
|
||||
.crossLibrary(
|
||||
scalaVersions = Seq("2.12.8"),
|
||||
suffix = "Config1.3",
|
||||
settings = Seq(
|
||||
.customRow(
|
||||
scalaVersions = Seq(scala212, scala211),
|
||||
axisValues = Seq(config13, VirtualAxis.jvm),
|
||||
_.settings(
|
||||
moduleName := name.value + "_config1.3",
|
||||
libraryDependencies += "com.typesafe" % "config" % "1.3.3"
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
This will create `coreConfig1_22_11`, `coreConfig1_22_12`, and `coreConfig1_32_12` respectively producing `core_config1.3_2.12`, `core_config1.2_2.11`, and `core_config1.2_2.12` artifacts.
|
||||
This will create `appConfig1_22_11`, `appConfig1_22_12`, and `appConfig1_32_12` respectively producing `app_config1.3_2.12`, `app_config1.2_2.11`, and `app_config1.2_2.12` artifacts.
|
||||
|
||||
### referncing the generated subprojects
|
||||
|
||||
|
|
@ -140,7 +159,7 @@ You might want to reference to one of the projects within `build.sbt`.
|
|||
```scala
|
||||
lazy val core12 = core.jvm("2.12.8")
|
||||
|
||||
// lazy val core12 = core.crossLib("Config1.2")("2.12.8")
|
||||
lazy val appConfig12_212 = app.finder(config13, VirtualAxis.jvm)("2.12.8")
|
||||
```
|
||||
|
||||
In the above `core12` returns `Project` type.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
package sbt
|
||||
|
||||
import sbt.librarymanagement.CrossVersion.partialVersion
|
||||
|
||||
/** Virtual Axis represents a parameter to a project matrix row. */
|
||||
sealed abstract class VirtualAxis {
|
||||
def directorySuffix: String
|
||||
|
||||
def idSuffix: String
|
||||
|
||||
/* The order to sort the suffixes if there were multiple axes. */
|
||||
def suffixOrder: Int = 50
|
||||
}
|
||||
|
||||
object VirtualAxis {
|
||||
/**
|
||||
* WeakAxis allows a row to depend on another row with Zero value.
|
||||
* For example, Scala version can be Zero for Java project, and it's ok.
|
||||
*/
|
||||
abstract class WeakAxis extends VirtualAxis
|
||||
|
||||
/** StrongAxis requires a row to depend on another row with the same selected value. */
|
||||
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)
|
||||
}
|
||||
lhs.forall(isCompatible(_, rhs)) && rhs.forall(isCompatible(_, lhs))
|
||||
}
|
||||
|
||||
case class ScalaVersionAxis(scalaVersion: String, value: String) extends WeakAxis {
|
||||
override def idSuffix: String = directorySuffix.replaceAll("""\W+""", "_")
|
||||
override val suffixOrder: Int = 100
|
||||
override def directorySuffix: String = value
|
||||
|
||||
// use only the scalaVersion field for equality
|
||||
override def equals(obj: Any): Boolean = {
|
||||
if (obj.isInstanceOf[AnyRef] && (this eq obj.asInstanceOf[AnyRef])) true
|
||||
else if (!obj.isInstanceOf[ScalaVersionAxis]) false
|
||||
else {
|
||||
val o = obj.asInstanceOf[ScalaVersionAxis]
|
||||
this.scalaVersion == o.scalaVersion
|
||||
}
|
||||
}
|
||||
override def hashCode: Int = {
|
||||
37 * (17 + "sbt.ScalaVersionAxis".hashCode()) + scalaVersion.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
case class PlatformAxis(value: String, idSuffix: String, directorySuffix: String) extends StrongAxis {
|
||||
override val suffixOrder: Int = 80
|
||||
}
|
||||
|
||||
def scalaPartialVersion(scalaVersion: String): ScalaVersionAxis =
|
||||
partialVersion(scalaVersion) match {
|
||||
case Some((m, n)) => scalaVersionAxis(scalaVersion, s"$m.$n")
|
||||
case _ => scalaVersionAxis(scalaVersion, scalaVersion)
|
||||
}
|
||||
def scalaVersionAxis(scalaVersion: String, value: String) =
|
||||
ScalaVersionAxis(scalaVersion, value)
|
||||
|
||||
val jvm: PlatformAxis = PlatformAxis("jvm", "JVM", "jvm")
|
||||
val js: PlatformAxis = PlatformAxis("js", "JS", "js")
|
||||
val native: PlatformAxis = PlatformAxis("native", "Native", "native")
|
||||
}
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
package sbt
|
||||
package internal
|
||||
|
||||
import java.util.Locale
|
||||
import scala.collection.immutable.ListMap
|
||||
import scala.collection.mutable
|
||||
import Keys._
|
||||
import sbt.librarymanagement.CrossVersion.partialVersion
|
||||
import scala.util.Try
|
||||
import sbt.internal.inc.ReflectUtilities
|
||||
|
||||
/**
|
||||
* A project matrix is an implementation of a composite project
|
||||
|
|
@ -46,23 +48,54 @@ sealed trait ProjectMatrix extends CompositeProject {
|
|||
def settings(ss: Def.SettingsDefinition*): ProjectMatrix
|
||||
|
||||
/**
|
||||
* Sets the [[AutoPlugin]]s of this project.
|
||||
* A [[AutoPlugin]] is a common label that is used by plugins to determine what settings, if any, to enable on a project.
|
||||
* Sets the [[sbt.AutoPlugin]]s of this project.
|
||||
* An [[sbt.AutoPlugin]] is a common label that is used by plugins to determine what settings, if any, to enable on a project.
|
||||
*/
|
||||
def enablePlugins(ns: Plugins*): ProjectMatrix
|
||||
|
||||
/** Disable the given plugins on this project. */
|
||||
def disablePlugins(ps: AutoPlugin*): ProjectMatrix
|
||||
|
||||
def custom(
|
||||
idSuffix: String,
|
||||
directorySuffix: String,
|
||||
scalaVersions: Seq[String],
|
||||
process: Project => Project
|
||||
|
||||
/**
|
||||
* If autoScalaLibrary is false, add non-Scala row.
|
||||
* Otherwise, add custom rows for each scalaVersions.
|
||||
*/
|
||||
def customRow(
|
||||
autoScalaLibrary: Boolean,
|
||||
scalaVersions: Seq[String],
|
||||
axisValues: Seq[VirtualAxis],
|
||||
process: Project => Project
|
||||
): ProjectMatrix
|
||||
|
||||
def customRow(
|
||||
scalaVersions: Seq[String],
|
||||
axisValues: Seq[VirtualAxis],
|
||||
process: Project => Project
|
||||
): ProjectMatrix
|
||||
|
||||
def customRow(
|
||||
autoScalaLibrary: Boolean,
|
||||
axisValues: Seq[VirtualAxis],
|
||||
process: Project => Project
|
||||
): ProjectMatrix
|
||||
|
||||
def customRow(
|
||||
scalaVersions: Seq[String],
|
||||
axisValues: Seq[VirtualAxis],
|
||||
settings: Seq[Setting[_]]
|
||||
): ProjectMatrix
|
||||
|
||||
def customRow(
|
||||
autoScalaLibrary: Boolean,
|
||||
axisValues: Seq[VirtualAxis],
|
||||
settings: Seq[Setting[_]]
|
||||
): ProjectMatrix
|
||||
|
||||
def jvmPlatform(scalaVersions: Seq[String]): ProjectMatrix
|
||||
def jvmPlatform(autoScalaLibrary: Boolean): ProjectMatrix
|
||||
def jvmPlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix
|
||||
def jvmPlatform(autoScalaLibrary: Boolean, scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix
|
||||
def jvm: ProjectFinder
|
||||
|
||||
def jsPlatform(scalaVersions: Seq[String]): ProjectMatrix
|
||||
|
|
@ -73,10 +106,14 @@ sealed trait ProjectMatrix extends CompositeProject {
|
|||
def nativePlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix
|
||||
def native: ProjectFinder
|
||||
|
||||
def crossLibrary(scalaVersions: Seq[String], suffix: String, settings: Seq[Setting[_]]): ProjectMatrix
|
||||
def crossLib(suffix: String): ProjectFinder
|
||||
|
||||
def projectRefs: Seq[ProjectReference]
|
||||
|
||||
def filterProjects(axisValues: Seq[VirtualAxis]): Seq[Project]
|
||||
def filterProjects(autoScalaLibrary: Boolean, axisValues: Seq[VirtualAxis]): Seq[Project]
|
||||
def finder(axisValues: VirtualAxis*): ProjectFinder
|
||||
|
||||
// resolve to the closest match for the given row
|
||||
private[sbt] def resolveMatch(thatRow: ProjectMatrix.ProjectRow): ProjectReference
|
||||
}
|
||||
|
||||
/** Represents a reference to a project matrix with an optional configuration string.
|
||||
|
|
@ -87,6 +124,7 @@ sealed trait MatrixClasspathDep[MR <: ProjectMatrixReference] {
|
|||
|
||||
trait ProjectFinder {
|
||||
def apply(scalaVersion: String): Project
|
||||
def apply(autoScalaLibrary: Boolean): Project
|
||||
def get: Seq[Project]
|
||||
}
|
||||
|
||||
|
|
@ -100,14 +138,27 @@ object ProjectMatrix {
|
|||
val nativeIdSuffix: String = "Native"
|
||||
val nativeDirectorySuffix: String = "-native"
|
||||
|
||||
/** A row in the project matrix, typically representing a platform.
|
||||
private[sbt] val allMatrices: mutable.Map[String, ProjectMatrix] = mutable.Map.empty
|
||||
|
||||
/** A row in the project matrix, typically representing a platform + Scala version.
|
||||
*/
|
||||
final class ProjectRow(
|
||||
val idSuffix: String,
|
||||
val directorySuffix: String,
|
||||
val scalaVersions: Seq[String],
|
||||
val autoScalaLibrary: Boolean,
|
||||
val axisValues: Seq[VirtualAxis],
|
||||
val process: Project => Project
|
||||
) {}
|
||||
) {
|
||||
def scalaVersionOpt: Option[String] =
|
||||
if (autoScalaLibrary)
|
||||
(axisValues collect {
|
||||
case sv: VirtualAxis.ScalaVersionAxis => sv.scalaVersion
|
||||
}).headOption
|
||||
else None
|
||||
|
||||
def isMatch(that: ProjectRow): Boolean =
|
||||
VirtualAxis.isMatch(this.axisValues, that.axisValues)
|
||||
|
||||
override def toString: String = s"ProjectRow($autoScalaLibrary, $axisValues)"
|
||||
}
|
||||
|
||||
final case class MatrixClasspathDependency(
|
||||
matrix: ProjectMatrixReference,
|
||||
|
|
@ -125,23 +176,40 @@ object ProjectMatrix {
|
|||
val configurations: Seq[Configuration],
|
||||
val plugins: Plugins
|
||||
) extends ProjectMatrix { self =>
|
||||
lazy val projectMatrix: ListMap[(ProjectRow, String), Project] = {
|
||||
lazy val resolvedMappings: ListMap[ProjectRow, Project] = resolveMappings
|
||||
private def resolveProjectIds: Map[ProjectRow, String] = {
|
||||
Map((for {
|
||||
r <- rows
|
||||
} yield {
|
||||
val axes = r.axisValues.sortBy(_.suffixOrder)
|
||||
val idSuffix = axes.map(_.idSuffix).mkString("")
|
||||
val childId = self.id + idSuffix
|
||||
r -> childId
|
||||
}): _*)
|
||||
}
|
||||
|
||||
private def resolveMappings: ListMap[ProjectRow, Project] = {
|
||||
val projectIds = resolveProjectIds
|
||||
|
||||
ListMap((for {
|
||||
r <- rows
|
||||
svs = if (r.scalaVersions.nonEmpty) r.scalaVersions
|
||||
else if (scalaVersions.nonEmpty) scalaVersions
|
||||
else sys.error(s"project matrix $id must specify scalaVersions.")
|
||||
sv <- svs
|
||||
} yield {
|
||||
val idSuffix = r.idSuffix + scalaVersionIdSuffix(sv)
|
||||
val svDirSuffix = r.directorySuffix + "-" + scalaVersionDirSuffix(sv)
|
||||
val childId = self.id + idSuffix
|
||||
val deps = dependencies map {
|
||||
case MatrixClasspathDependency(matrix: LocalProjectMatrix, configuration) =>
|
||||
ClasspathDependency(LocalProject(matrix.id + idSuffix), configuration)
|
||||
}
|
||||
val axes = r.axisValues.sortBy(_.suffixOrder)
|
||||
val svDirSuffix = axes.map(_.directorySuffix).mkString("-")
|
||||
val nonScalaDirSuffix = (axes filter {
|
||||
case _: VirtualAxis.ScalaVersionAxis => false
|
||||
case _ => true
|
||||
}).map(_.directorySuffix).mkString("-")
|
||||
|
||||
val platform = (axes collect {
|
||||
case pa: VirtualAxis.PlatformAxis => pa
|
||||
}).headOption.getOrElse(sys.error(s"platform axis is missing in $axes"))
|
||||
val childId = projectIds(r)
|
||||
val deps = dependencies map { resolveMatrixDependency(_, r) }
|
||||
val aggs = aggregate map {
|
||||
case ref: LocalProjectMatrix => LocalProject(ref.id + idSuffix)
|
||||
case ref: LocalProjectMatrix =>
|
||||
val other = lookupMatrix(ref)
|
||||
resolveMatrixAggregate(other, r)
|
||||
}
|
||||
val p = Project(childId, new sbt.File(childId).getAbsoluteFile)
|
||||
.dependsOn(deps: _*)
|
||||
|
|
@ -149,21 +217,50 @@ object ProjectMatrix {
|
|||
.setPlugins(plugins)
|
||||
.configs(configurations: _*)
|
||||
.settings(
|
||||
name := self.id,
|
||||
Keys.scalaVersion := sv,
|
||||
name := self.id
|
||||
)
|
||||
.settings(
|
||||
r.scalaVersionOpt.toList map { sv =>
|
||||
Keys.scalaVersion := sv
|
||||
}
|
||||
)
|
||||
.settings(
|
||||
target := base.getAbsoluteFile / "target" / svDirSuffix.dropWhile(_ == '-'),
|
||||
crossTarget := Keys.target.value,
|
||||
sourceDirectory := base.getAbsoluteFile / "src",
|
||||
inConfig(Compile)(makeSources(r.directorySuffix, svDirSuffix)),
|
||||
inConfig(Test)(makeSources(r.directorySuffix, svDirSuffix))
|
||||
inConfig(Compile)(makeSources(nonScalaDirSuffix, svDirSuffix)),
|
||||
inConfig(Test)(makeSources(nonScalaDirSuffix, svDirSuffix))
|
||||
)
|
||||
.settings(self.settings)
|
||||
|
||||
(r, sv) -> r.process(p)
|
||||
r -> r.process(p)
|
||||
}): _*)
|
||||
}
|
||||
|
||||
override lazy val componentProjects: Seq[Project] = projectMatrix.values.toList
|
||||
|
||||
override lazy val componentProjects: Seq[Project] = resolvedMappings.values.toList
|
||||
|
||||
private def resolveMatrixAggregate(
|
||||
other: ProjectMatrix,
|
||||
thisRow: ProjectRow,
|
||||
): ProjectReference = other.resolveMatch(thisRow)
|
||||
|
||||
private def resolveMatrixDependency(
|
||||
dep: MatrixClasspathDep[ProjectMatrixReference],
|
||||
thisRow: ProjectRow
|
||||
): ClasspathDep[ProjectReference] =
|
||||
dep match {
|
||||
case MatrixClasspathDependency(matrix0: LocalProjectMatrix, configuration) =>
|
||||
val other = lookupMatrix(matrix0)
|
||||
ClasspathDependency(other.resolveMatch(thisRow), configuration)
|
||||
}
|
||||
|
||||
// resolve to the closest match for the given row
|
||||
private[sbt] def resolveMatch(thatRow: ProjectRow): ProjectReference =
|
||||
rows.find(r => r.isMatch(thatRow)) match {
|
||||
case Some(r) => LocalProject(resolveProjectIds(r))
|
||||
case _ => sys.error(s"no rows were found in $id matching $thatRow: $rows")
|
||||
}
|
||||
|
||||
private def makeSources(dirSuffix: String, svDirSuffix: String): Setting[_] = {
|
||||
unmanagedSourceDirectories ++= Seq(
|
||||
|
|
@ -172,16 +269,6 @@ object ProjectMatrix {
|
|||
)
|
||||
}
|
||||
|
||||
private def scalaVersionIdSuffix(sv: String): String = {
|
||||
scalaVersionDirSuffix(sv).toLowerCase(Locale.ENGLISH).replaceAll("""\W+""", "_")
|
||||
}
|
||||
|
||||
private def scalaVersionDirSuffix(sv: String): String =
|
||||
partialVersion(sv) match {
|
||||
case Some((m, n)) => s"$m.$n"
|
||||
case _ => sv
|
||||
}
|
||||
|
||||
override def withId(id: String): ProjectMatrix = copy(id = id)
|
||||
|
||||
override def in(dir: sbt.File): ProjectMatrix = copy(base = dir)
|
||||
|
|
@ -209,16 +296,20 @@ object ProjectMatrix {
|
|||
|
||||
override def jvmPlatform(scalaVersions: Seq[String]): ProjectMatrix =
|
||||
jvmPlatform(scalaVersions, Nil)
|
||||
override def jvmPlatform(autoScalaLibrary: Boolean): ProjectMatrix =
|
||||
jvmPlatform(autoScalaLibrary, Nil, Nil)
|
||||
override def jvmPlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix =
|
||||
custom(jvmIdSuffix, jvmDirectorySuffix, scalaVersions, { _.settings(settings) })
|
||||
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 jvm: ProjectFinder = new SuffixBaseProjectFinder(jvmIdSuffix)
|
||||
override def jvm: ProjectFinder = new AxisBaseProjectFinder(Seq(VirtualAxis.jvm))
|
||||
|
||||
override def jsPlatform(scalaVersions: Seq[String]): ProjectMatrix =
|
||||
jsPlatform(scalaVersions, Nil)
|
||||
|
||||
override def jsPlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix =
|
||||
custom(jsIdSuffix, jsDirectorySuffix, scalaVersions,
|
||||
customRow(true, scalaVersions, Seq(VirtualAxis.js),
|
||||
{ _
|
||||
.enablePlugins(scalajsPlugin(this.getClass.getClassLoader).getOrElse(
|
||||
sys.error("""Scala.js plugin was not found. Add the sbt-scalajs plugin into project/plugins.sbt:
|
||||
|
|
@ -235,17 +326,19 @@ object ProjectMatrix {
|
|||
}
|
||||
}
|
||||
|
||||
override def native: ProjectFinder = new SuffixBaseProjectFinder(nativeIdSuffix)
|
||||
override def js: ProjectFinder = new AxisBaseProjectFinder(Seq(VirtualAxis.js))
|
||||
|
||||
override def native: ProjectFinder = new AxisBaseProjectFinder(Seq(VirtualAxis.native))
|
||||
|
||||
override def nativePlatform(scalaVersions: Seq[String]): ProjectMatrix =
|
||||
nativePlatform(scalaVersions, Nil)
|
||||
|
||||
override def nativePlatform(scalaVersions: Seq[String], settings: Seq[Setting[_]]): ProjectMatrix =
|
||||
custom(nativeIdSuffix, nativeDirectorySuffix, scalaVersions,
|
||||
customRow(true, scalaVersions, Seq(VirtualAxis.native),
|
||||
{ _
|
||||
.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-natiev" % "x.y.z")
|
||||
| addSbtPlugin("org.scala-native" % "sbt-scala-native" % "x.y.z")
|
||||
|""".stripMargin)
|
||||
))
|
||||
.settings(settings)
|
||||
|
|
@ -258,39 +351,71 @@ object ProjectMatrix {
|
|||
}
|
||||
}
|
||||
|
||||
override def js: ProjectFinder = new SuffixBaseProjectFinder(jsIdSuffix)
|
||||
|
||||
override def crossLibrary(scalaVersions: Seq[String], suffix: String, settings: Seq[Setting[_]]): ProjectMatrix =
|
||||
custom(suffix.replaceAllLiterally(".", "_"),
|
||||
"-" + suffix.toLowerCase,
|
||||
scalaVersions,
|
||||
{ _.settings(
|
||||
Seq(moduleName := name.value + "_" + suffix.toLowerCase) ++ settings
|
||||
) })
|
||||
|
||||
override def crossLib(suffix: String): ProjectFinder =
|
||||
new SuffixBaseProjectFinder(suffix.replaceAllLiterally(".", "_"))
|
||||
|
||||
override def projectRefs: Seq[ProjectReference] =
|
||||
componentProjects map { case p => (p: ProjectReference) }
|
||||
|
||||
private final class SuffixBaseProjectFinder(idSuffix: String) extends ProjectFinder {
|
||||
def get: Seq[Project] = projectMatrix.toSeq collect {
|
||||
case ((r, sv), v) if r.idSuffix == idSuffix => v
|
||||
override def filterProjects(axisValues: Seq[VirtualAxis]): Seq[Project] =
|
||||
resolvedMappings.toSeq collect {
|
||||
case (r, p) if axisValues.forall(v => r.axisValues.contains(v)) => p
|
||||
}
|
||||
override def filterProjects(autoScalaLibrary: Boolean, axisValues: Seq[VirtualAxis]): Seq[Project] =
|
||||
resolvedMappings.toSeq collect {
|
||||
case (r, p) if r.autoScalaLibrary == autoScalaLibrary && axisValues.forall(v => r.axisValues.contains(v)) => p
|
||||
}
|
||||
|
||||
private final class AxisBaseProjectFinder(axisValues: Seq[VirtualAxis]) extends ProjectFinder {
|
||||
def get: Seq[Project] = filterProjects(axisValues)
|
||||
def apply(sv: String): Project =
|
||||
(projectMatrix.toSeq collectFirst {
|
||||
case ((r, `sv`), v) if r.idSuffix == idSuffix => v
|
||||
}).getOrElse(sys.error(s"$sv was not found"))
|
||||
filterProjects(true, axisValues ++ Seq(VirtualAxis.scalaPartialVersion(sv))).headOption
|
||||
.getOrElse(sys.error(s"project matching $axisValues and $sv was not found"))
|
||||
def apply(autoScalaLibrary: Boolean): Project =
|
||||
filterProjects(autoScalaLibrary, axisValues).headOption
|
||||
.getOrElse(sys.error(s"project matching $axisValues and $autoScalaLibrary was not found"))
|
||||
}
|
||||
|
||||
override def custom(
|
||||
idSuffix: String,
|
||||
directorySuffix: String,
|
||||
scalaVersions: Seq[String],
|
||||
process: Project => Project
|
||||
override def customRow(
|
||||
scalaVersions: Seq[String],
|
||||
axisValues: Seq[VirtualAxis],
|
||||
settings: Seq[Setting[_]]
|
||||
): ProjectMatrix = customRow(true, scalaVersions, axisValues, { _.settings(settings) })
|
||||
|
||||
override def customRow(
|
||||
autoScalaLibrary: Boolean,
|
||||
axisValues: Seq[VirtualAxis],
|
||||
settings: Seq[Setting[_]]
|
||||
): ProjectMatrix = customRow(autoScalaLibrary, Nil, axisValues, { _.settings(settings) })
|
||||
|
||||
override def customRow(
|
||||
scalaVersions: Seq[String],
|
||||
axisValues: Seq[VirtualAxis],
|
||||
process: Project => Project
|
||||
): ProjectMatrix = customRow(true, scalaVersions, axisValues, process)
|
||||
|
||||
override def customRow(
|
||||
autoScalaLibrary: Boolean,
|
||||
scalaVersions: Seq[String],
|
||||
axisValues: Seq[VirtualAxis],
|
||||
process: Project => Project
|
||||
): ProjectMatrix =
|
||||
copy(rows = rows :+ new ProjectRow(idSuffix, directorySuffix, scalaVersions, process))
|
||||
if (autoScalaLibrary) {
|
||||
scalaVersions.foldLeft(this: ProjectMatrix) { (acc, sv) =>
|
||||
acc.customRow(autoScalaLibrary, axisValues ++ Seq(VirtualAxis.scalaPartialVersion(sv)), process)
|
||||
}
|
||||
} else {
|
||||
customRow(autoScalaLibrary, 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)
|
||||
}
|
||||
|
||||
override def finder(axisValues: VirtualAxis*): ProjectFinder =
|
||||
new AxisBaseProjectFinder(axisValues.toSeq)
|
||||
|
||||
def copy(
|
||||
id: String = id,
|
||||
|
|
@ -302,8 +427,8 @@ object ProjectMatrix {
|
|||
settings: Seq[Setting[_]] = settings,
|
||||
configurations: Seq[Configuration] = configurations,
|
||||
plugins: Plugins = plugins
|
||||
): ProjectMatrix =
|
||||
unresolved(
|
||||
): ProjectMatrix = {
|
||||
val matrix = unresolved(
|
||||
id,
|
||||
base,
|
||||
scalaVersions,
|
||||
|
|
@ -314,10 +439,16 @@ object ProjectMatrix {
|
|||
configurations,
|
||||
plugins
|
||||
)
|
||||
allMatrices(id) = matrix
|
||||
matrix
|
||||
}
|
||||
}
|
||||
|
||||
// called by macro
|
||||
def apply(id: String, base: sbt.File): ProjectMatrix = {
|
||||
unresolved(id, base, Nil, Nil, Nil, Nil, Nil, Nil, Plugins.Empty)
|
||||
val matrix = unresolved(id, base, Nil, Nil, Nil, Nil, Nil, Nil, Plugins.Empty)
|
||||
allMatrices(id) = matrix
|
||||
matrix
|
||||
}
|
||||
|
||||
private[sbt] def unresolved(
|
||||
|
|
@ -343,6 +474,10 @@ object ProjectMatrix {
|
|||
plugins
|
||||
)
|
||||
|
||||
def lookupMatrix(local: LocalProjectMatrix): ProjectMatrix = {
|
||||
allMatrices.getOrElse(local.id, sys.error(s"${local.id} was not found"))
|
||||
}
|
||||
|
||||
implicit def projectMatrixToLocalProjectMatrix(m: ProjectMatrix): LocalProjectMatrix =
|
||||
LocalProjectMatrix(m.id)
|
||||
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
package sbt
|
||||
package internal
|
||||
|
||||
/** Identifies a project matrix. */
|
||||
sealed trait ProjectMatrixReference
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
package sbtprojectmatrix
|
||||
|
||||
import sbt._
|
||||
import internal._
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import scala.language.experimental.macros
|
||||
|
||||
|
|
|
|||
|
|
@ -1,35 +0,0 @@
|
|||
ThisBuild / organization := "com.example"
|
||||
ThisBuild / version := "0.1.0-SNAPSHOT"
|
||||
ThisBuild / publishMavenStyle := true
|
||||
|
||||
ThisBuild / ivyPaths := {
|
||||
val base = (ThisBuild / baseDirectory).value
|
||||
IvyPaths(base, Some(base / "ivy-cache"))
|
||||
}
|
||||
publish / skip := true
|
||||
|
||||
lazy val core = (projectMatrix in file("core"))
|
||||
.settings(
|
||||
name := "core",
|
||||
ivyPaths := (ThisBuild / ivyPaths).value
|
||||
)
|
||||
.crossLibrary(
|
||||
scalaVersions = Seq("2.12.8", "2.11.12"),
|
||||
suffix = "Config1.2",
|
||||
settings = Seq(
|
||||
libraryDependencies += "com.typesafe" % "config" % "1.2.1"
|
||||
)
|
||||
)
|
||||
.crossLibrary(
|
||||
scalaVersions = Seq("2.12.8"),
|
||||
suffix = "Config1.3",
|
||||
settings = Seq(
|
||||
libraryDependencies += "com.typesafe" % "config" % "1.3.3"
|
||||
)
|
||||
)
|
||||
|
||||
// to reference project ref
|
||||
lazy val coreConfig1_3 = core.crossLib("Config1.3")("2.12.8")
|
||||
.settings(
|
||||
publishMavenStyle := true
|
||||
)
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
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)
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
> publishLocal
|
||||
|
||||
$ exists ivy-cache/local/com.example/core_config1.2_2.11/0.1.0-SNAPSHOT/poms/core_config1.2_2.11.pom
|
||||
$ exists ivy-cache/local/com.example/core_config1.2_2.12/0.1.0-SNAPSHOT/poms/core_config1.2_2.12.pom
|
||||
$ exists ivy-cache/local/com.example/core_config1.3_2.12/0.1.0-SNAPSHOT/poms/core_config1.3_2.12.pom
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package example
|
||||
|
||||
object B {
|
||||
def b: Int = A.a
|
||||
}
|
||||
|
|
@ -8,26 +8,39 @@ ThisBuild / ivyPaths := {
|
|||
}
|
||||
publish / skip := true
|
||||
|
||||
lazy val config12 = ConfigAxis("Config1_2", "config1.2")
|
||||
lazy val config13 = ConfigAxis("Config1_3", "config1.3")
|
||||
|
||||
lazy val scala212 = "2.12.10"
|
||||
lazy val scala211 = "2.11.12"
|
||||
|
||||
lazy val core = (projectMatrix in file("core"))
|
||||
.jvmPlatform(scalaVersions = Seq(scala212, scala211))
|
||||
|
||||
lazy val app = (projectMatrix in file("app"))
|
||||
.dependsOn(core)
|
||||
.settings(
|
||||
name := "core",
|
||||
name := "app",
|
||||
ivyPaths := (ThisBuild / ivyPaths).value
|
||||
)
|
||||
.custom(
|
||||
idSuffix = "Config1_2",
|
||||
directorySuffix = "-config1.2",
|
||||
scalaVersions = Seq("2.12.8", "2.11.12"),
|
||||
.customRow(
|
||||
scalaVersions = Seq(scala212, scala211),
|
||||
axisValues = Seq(config12, VirtualAxis.jvm),
|
||||
_.settings(
|
||||
moduleName := name.value + "_config1.2",
|
||||
libraryDependencies += "com.typesafe" % "config" % "1.2.1"
|
||||
)
|
||||
)
|
||||
.custom(
|
||||
idSuffix = "Config1_3",
|
||||
directorySuffix = "-config1.3",
|
||||
scalaVersions = Seq("2.12.8", "2.11.12"),
|
||||
.customRow(
|
||||
scalaVersions = Seq(scala212, scala211),
|
||||
axisValues = Seq(config13, VirtualAxis.jvm),
|
||||
_.settings(
|
||||
moduleName := name.value + "_config1.3",
|
||||
libraryDependencies += "com.typesafe" % "config" % "1.3.3"
|
||||
)
|
||||
)
|
||||
|
||||
lazy val appConfig12_212 = app.finder(config13, VirtualAxis.jvm)(scala212)
|
||||
.settings(
|
||||
publishMavenStyle := true
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package example
|
||||
|
||||
object A {
|
||||
def a: Int = 1
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import sbt._
|
||||
|
||||
case class ConfigAxis(idSuffix: String, directorySuffix: String) extends VirtualAxis.WeakAxis {
|
||||
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
> publishLocal
|
||||
|
||||
$ exists ivy-cache/local/com.example/core_config1.2_2.11/0.1.0-SNAPSHOT/poms/core_config1.2_2.11.pom
|
||||
$ exists ivy-cache/local/com.example/core_config1.2_2.12/0.1.0-SNAPSHOT/poms/core_config1.2_2.12.pom
|
||||
$ exists ivy-cache/local/com.example/core_config1.3_2.11/0.1.0-SNAPSHOT/poms/core_config1.3_2.11.pom
|
||||
$ exists ivy-cache/local/com.example/core_config1.3_2.12/0.1.0-SNAPSHOT/poms/core_config1.3_2.12.pom
|
||||
$ exists ivy-cache/local/com.example/app_config1.2_2.11/0.1.0-SNAPSHOT/poms/app_config1.2_2.11.pom
|
||||
$ exists ivy-cache/local/com.example/app_config1.2_2.12/0.1.0-SNAPSHOT/poms/app_config1.2_2.12.pom
|
||||
$ exists ivy-cache/local/com.example/app_config1.3_2.11/0.1.0-SNAPSHOT/poms/app_config1.3_2.11.pom
|
||||
$ exists ivy-cache/local/com.example/app_config1.3_2.12/0.1.0-SNAPSHOT/poms/app_config1.3_2.12.pom
|
||||
|
|
|
|||
|
|
@ -1,9 +1,17 @@
|
|||
lazy val check = taskKey[Unit]("")
|
||||
|
||||
// lazy val root = (project in file("."))
|
||||
// .aggregate(core.projectRefs ++ app.projectRefs: _*)
|
||||
// .settings(
|
||||
// )
|
||||
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(scalaVersions = Seq("2.12.8"))
|
||||
|
||||
lazy val core = (projectMatrix in file("core"))
|
||||
.settings(
|
||||
|
|
@ -13,9 +21,12 @@ lazy val core = (projectMatrix in file("core"))
|
|||
)
|
||||
.jvmPlatform(scalaVersions = Seq("2.12.8", "2.11.12"))
|
||||
|
||||
lazy val app = (projectMatrix in file("app"))
|
||||
.dependsOn(core)
|
||||
lazy val intf = (projectMatrix in file("intf"))
|
||||
.settings(
|
||||
name := "app"
|
||||
check := {
|
||||
assert(moduleName.value == "intf", s"moduleName is ${moduleName.value}")
|
||||
},
|
||||
)
|
||||
.jvmPlatform(scalaVersions = Seq("2.12.8"))
|
||||
.jvmPlatform(autoScalaLibrary = false)
|
||||
|
||||
lazy val core212 = core.jvm("2.12.8")
|
||||
|
|
|
|||
Loading…
Reference in New Issue