mirror of https://github.com/sbt/sbt.git
intitial import
This commit is contained in:
parent
0307478990
commit
42ff91f4cc
|
|
@ -0,0 +1,20 @@
|
|||
dist: trusty
|
||||
group: stable
|
||||
|
||||
language: scala
|
||||
jdk: oraclejdk8
|
||||
|
||||
script: sbt scripted
|
||||
|
||||
# Undo _JAVA_OPTIONS environment variable
|
||||
before_script:
|
||||
- unset _JAVA_OPTIONS
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.ivy2/cache
|
||||
- $HOME/.sbt
|
||||
|
||||
before_cache:
|
||||
- find $HOME/.ivy2/cache -name "ivydata-*.properties" -delete
|
||||
- find $HOME/.sbt -name "*.lock" -delete
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
sbt-projectmatrix
|
||||
=================
|
||||
|
||||
cross building using subprojects.
|
||||
|
||||
This is an experimental plugin that implements better cross building.
|
||||
|
||||
setup
|
||||
-----
|
||||
|
||||
**Requirements**: Requires sbt 1.2.0-M1 or above.
|
||||
|
||||
In `project/plugins.sbt`:
|
||||
|
||||
```scala
|
||||
addSbtPlugin("com.eed3si9n" % "sbt-projectmatrix" % "0.1.0")
|
||||
```
|
||||
|
||||
usage
|
||||
-----
|
||||
|
||||
To use `projectMatrix`:
|
||||
|
||||
```scala
|
||||
lazy val core = (projectMatrix in file("core"))
|
||||
.scalaVersions("2.12.6", "2.11.12")
|
||||
.settings(
|
||||
name := "core"
|
||||
)
|
||||
.jvmPlatform()
|
||||
|
||||
lazy val app = (projectMatrix in file("app"))
|
||||
.dependsOn(core)
|
||||
.scalaVersions("2.12.6")
|
||||
.settings(
|
||||
name := "app"
|
||||
)
|
||||
.jvmPlatform()
|
||||
```
|
||||
|
||||
This sets up basic project matrices one supporting both 2.11 and 2.12, and the other supporting only 2.12.
|
||||
|
||||
license
|
||||
-------
|
||||
|
||||
MIT License
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
ThisBuild / organization := "com.eed3si9n"
|
||||
ThisBuild / version := "0.1.0-SNAPSHOT"
|
||||
ThisBuild / description := "sbt plugin to define project matrix for cross building"
|
||||
ThisBuild / licenses := Seq("MIT License" -> url("https://github.com/sbt/sbt-projectmatrix/blob/master/LICENSE"))
|
||||
|
||||
lazy val root = (project in file("."))
|
||||
.enablePlugins(SbtPlugin)
|
||||
.settings(
|
||||
sbtPlugin := true,
|
||||
name := "sbt-projectmatrix",
|
||||
scalacOptions := Seq("-deprecation", "-unchecked"),
|
||||
publishMavenStyle := false,
|
||||
bintrayOrganization in bintray := None,
|
||||
bintrayRepository := "sbt-plugins",
|
||||
scriptedLaunchOpts := { scriptedLaunchOpts.value ++
|
||||
Seq("-Xmx1024M", "-Dplugin.version=" + version.value)
|
||||
},
|
||||
scriptedBufferLog := false,
|
||||
)
|
||||
|
|
@ -0,0 +1 @@
|
|||
sbt.version=1.2.0-M1
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
addSbtPlugin("org.foundweekends" % "sbt-bintray" % "0.5.4")
|
||||
addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.1.1")
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
package sbt
|
||||
|
||||
import java.util.Locale
|
||||
import scala.collection.immutable.ListMap
|
||||
import Keys._
|
||||
import sbt.librarymanagement.CrossVersion.partialVersion
|
||||
|
||||
/**
|
||||
* A project matrix is an implementation of a composite project
|
||||
* that represents cross building across some axis (such as platform)
|
||||
* and Scala version.
|
||||
*
|
||||
* {{{
|
||||
* lazy val core = (projectMatrix in file("core"))
|
||||
* .scalaVersions("2.12.6", "2.11.12")
|
||||
* .settings(
|
||||
* name := "core"
|
||||
* )
|
||||
* .jvmPlatform()
|
||||
* }}}
|
||||
*/
|
||||
sealed trait ProjectMatrix extends CompositeProject {
|
||||
def scalaVersions(sv: String*): ProjectMatrix
|
||||
|
||||
def id: String
|
||||
|
||||
/** The base directory for the project matrix.*/
|
||||
def base: sbt.File
|
||||
|
||||
def withId(id: String): ProjectMatrix
|
||||
|
||||
/** Sets the base directory for this project matrix.*/
|
||||
def in(dir: sbt.File): ProjectMatrix
|
||||
|
||||
/** Adds new configurations directly to this project. To override an existing configuration, use `overrideConfigs`. */
|
||||
def configs(cs: Configuration*): ProjectMatrix
|
||||
|
||||
/** Adds classpath dependencies on internal or external projects. */
|
||||
def dependsOn(deps: MatrixClasspathDep[ProjectMatrixReference]*): ProjectMatrix
|
||||
|
||||
/**
|
||||
* Adds projects to be aggregated. When a user requests a task to run on this project from the command line,
|
||||
* the task will also be run in aggregated projects.
|
||||
*/
|
||||
def aggregate(refs: ProjectMatrixReference*): ProjectMatrix
|
||||
|
||||
/** Appends settings to the current settings sequence for this project. */
|
||||
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.
|
||||
*/
|
||||
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
|
||||
): ProjectMatrix
|
||||
|
||||
def jvmPlatform(settings: Setting[_]*): ProjectMatrix
|
||||
|
||||
def jvm: ProjectFinder
|
||||
|
||||
def projectRefs: Seq[ProjectReference]
|
||||
}
|
||||
|
||||
/** Represents a reference to a project matrix with an optional configuration string.
|
||||
*/
|
||||
sealed trait MatrixClasspathDep[MR <: ProjectMatrixReference] {
|
||||
def matrix: MR; def configuration: Option[String]
|
||||
}
|
||||
|
||||
trait ProjectFinder {
|
||||
def apply(scalaVersion: String): Project
|
||||
def get: Seq[Project]
|
||||
}
|
||||
|
||||
object ProjectMatrix {
|
||||
import sbt.io.syntax._
|
||||
|
||||
val jvmIdSuffix: String = "JVM"
|
||||
val jvmDirectorySuffix: String = "-jvm"
|
||||
|
||||
/** A row in the project matrix, typically representing a platform.
|
||||
*/
|
||||
final class ProjectRow(
|
||||
val idSuffix: String,
|
||||
val directorySuffix: String,
|
||||
val scalaVersions: Seq[String],
|
||||
val process: Project => Project
|
||||
) {}
|
||||
|
||||
final case class MatrixClasspathDependency(
|
||||
matrix: ProjectMatrixReference,
|
||||
configuration: Option[String]
|
||||
) extends MatrixClasspathDep[ProjectMatrixReference]
|
||||
|
||||
private final class ProjectMatrixDef(
|
||||
val id: String,
|
||||
val base: sbt.File,
|
||||
val scalaVersions: Seq[String],
|
||||
val rows: Seq[ProjectRow],
|
||||
val aggregate: Seq[ProjectMatrixReference],
|
||||
val dependencies: Seq[MatrixClasspathDep[ProjectMatrixReference]],
|
||||
val settings: Seq[Def.Setting[_]],
|
||||
val configurations: Seq[Configuration],
|
||||
val plugins: Plugins
|
||||
) extends ProjectMatrix { self =>
|
||||
lazy val projectMatrix: ListMap[(ProjectRow, String), Project] = {
|
||||
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 aggs = aggregate map {
|
||||
case ref: LocalProjectMatrix => LocalProject(ref.id + idSuffix)
|
||||
}
|
||||
val p = Project(childId, new sbt.File(childId).getAbsoluteFile)
|
||||
.dependsOn(deps: _*)
|
||||
.aggregate(aggs: _*)
|
||||
.setPlugins(plugins)
|
||||
.configs(configurations: _*)
|
||||
.settings(
|
||||
Keys.scalaVersion := sv,
|
||||
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))
|
||||
)
|
||||
.settings(self.settings)
|
||||
|
||||
(r, sv) -> r.process(p)
|
||||
}): _*)
|
||||
}
|
||||
|
||||
override lazy val componentProjects: Seq[Project] = projectMatrix.values.toList
|
||||
|
||||
private def makeSources(dirSuffix: String, svDirSuffix: String): Setting[_] = {
|
||||
unmanagedSourceDirectories ++= Seq(
|
||||
scalaSource.value.getParentFile / s"scala${dirSuffix}",
|
||||
scalaSource.value.getParentFile / s"scala$svDirSuffix"
|
||||
)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
override def configs(cs: Configuration*): ProjectMatrix =
|
||||
copy(configurations = configurations ++ cs)
|
||||
|
||||
override def scalaVersions(sv: String*): ProjectMatrix =
|
||||
copy(scalaVersions = sv)
|
||||
|
||||
override def aggregate(refs: ProjectMatrixReference*): ProjectMatrix =
|
||||
copy(aggregate = (aggregate: Seq[ProjectMatrixReference]) ++ refs)
|
||||
|
||||
override def dependsOn(deps: MatrixClasspathDep[ProjectMatrixReference]*): ProjectMatrix =
|
||||
copy(dependencies = dependencies ++ deps)
|
||||
|
||||
/** Appends settings to the current settings sequence for this project. */
|
||||
override def settings(ss: Def.SettingsDefinition*): ProjectMatrix =
|
||||
copy(settings = (settings: Seq[Def.Setting[_]]) ++ Def.settings(ss: _*))
|
||||
|
||||
override def enablePlugins(ns: Plugins*): ProjectMatrix =
|
||||
setPlugins(ns.foldLeft(plugins)(Plugins.and))
|
||||
|
||||
override def disablePlugins(ps: AutoPlugin*): ProjectMatrix =
|
||||
setPlugins(Plugins.and(plugins, Plugins.And(ps.map(p => Plugins.Exclude(p)).toList)))
|
||||
|
||||
def setPlugins(ns: Plugins): ProjectMatrix = copy(plugins = ns)
|
||||
|
||||
override def jvmPlatform(settings: Setting[_]*): ProjectMatrix =
|
||||
custom(jvmIdSuffix, jvmDirectorySuffix, Nil, { _.settings(settings) })
|
||||
|
||||
override def jvm: ProjectFinder = new ProjectFinder {
|
||||
def get: Seq[Project] = projectMatrix.toSeq collect {
|
||||
case ((r, sv), v) if r.idSuffix == jvmIdSuffix => v
|
||||
}
|
||||
def apply(sv: String): Project =
|
||||
(projectMatrix.toSeq collect {
|
||||
case ((r, `sv`), v) if r.idSuffix == jvmIdSuffix => v
|
||||
}).headOption.getOrElse(sys.error(s"$sv was not found"))
|
||||
}
|
||||
|
||||
override def projectRefs: Seq[ProjectReference] =
|
||||
componentProjects map { case p => (p: ProjectReference) }
|
||||
|
||||
override def custom(
|
||||
idSuffix: String,
|
||||
directorySuffix: String,
|
||||
scalaVersions: Seq[String],
|
||||
process: Project => Project
|
||||
): ProjectMatrix =
|
||||
copy(rows = rows :+ new ProjectRow(idSuffix, directorySuffix, scalaVersions, process))
|
||||
|
||||
def copy(
|
||||
id: String = id,
|
||||
base: sbt.File = base,
|
||||
scalaVersions: Seq[String] = scalaVersions,
|
||||
rows: Seq[ProjectRow] = rows,
|
||||
aggregate: Seq[ProjectMatrixReference] = aggregate,
|
||||
dependencies: Seq[MatrixClasspathDep[ProjectMatrixReference]] = dependencies,
|
||||
settings: Seq[Setting[_]] = settings,
|
||||
configurations: Seq[Configuration] = configurations,
|
||||
plugins: Plugins = plugins
|
||||
): ProjectMatrix =
|
||||
unresolved(
|
||||
id,
|
||||
base,
|
||||
scalaVersions,
|
||||
rows,
|
||||
aggregate,
|
||||
dependencies,
|
||||
settings,
|
||||
configurations,
|
||||
plugins
|
||||
)
|
||||
}
|
||||
|
||||
def apply(id: String, base: sbt.File): ProjectMatrix = {
|
||||
unresolved(id, base, Nil, Nil, Nil, Nil, Nil, Nil, Plugins.Empty)
|
||||
}
|
||||
|
||||
private[sbt] def unresolved(
|
||||
id: String,
|
||||
base: sbt.File,
|
||||
scalaVersions: Seq[String],
|
||||
rows: Seq[ProjectRow],
|
||||
aggregate: Seq[ProjectMatrixReference],
|
||||
dependencies: Seq[MatrixClasspathDep[ProjectMatrixReference]],
|
||||
settings: Seq[Def.Setting[_]],
|
||||
configurations: Seq[Configuration],
|
||||
plugins: Plugins
|
||||
): ProjectMatrix =
|
||||
new ProjectMatrixDef(
|
||||
id,
|
||||
base,
|
||||
scalaVersions,
|
||||
rows,
|
||||
aggregate,
|
||||
dependencies,
|
||||
settings,
|
||||
configurations,
|
||||
plugins
|
||||
)
|
||||
|
||||
implicit def projectMatrixToLocalProjectMatrix(m: ProjectMatrix): LocalProjectMatrix =
|
||||
LocalProjectMatrix(m.id)
|
||||
|
||||
import scala.reflect.macros._
|
||||
|
||||
def projectMatrixMacroImpl(c: blackbox.Context): c.Expr[ProjectMatrix] = {
|
||||
import c.universe._
|
||||
val enclosingValName = std.KeyMacro.definingValName(
|
||||
c,
|
||||
methodName =>
|
||||
s"""$methodName must be directly assigned to a val, such as `val x = $methodName`. Alternatively, you can use `sbt.ProjectMatrix.apply`"""
|
||||
)
|
||||
val name = c.Expr[String](Literal(Constant(enclosingValName)))
|
||||
reify { ProjectMatrix(name.splice, new sbt.File(name.splice)) }
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package sbt
|
||||
|
||||
/** Identifies a project matrix. */
|
||||
sealed trait ProjectMatrixReference
|
||||
|
||||
/** Identifies a project in the current build context. */
|
||||
final case class LocalProjectMatrix(id: String) extends ProjectMatrixReference
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
package sbtprojectmatrix
|
||||
|
||||
import sbt._
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import scala.language.experimental.macros
|
||||
|
||||
object ProjectMatrixPlugin extends AutoPlugin {
|
||||
override val requires = sbt.plugins.CorePlugin
|
||||
override val trigger = allRequirements
|
||||
object autoImport {
|
||||
def projectMatrix: ProjectMatrix = macro ProjectMatrix.projectMatrixMacroImpl
|
||||
|
||||
implicit def matrixClasspathDependency[T](
|
||||
m: T
|
||||
)(implicit ev: T => ProjectMatrixReference): ProjectMatrix.MatrixClasspathDependency =
|
||||
ProjectMatrix.MatrixClasspathDependency(m, None)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
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"))
|
||||
.scalaVersions("2.12.6", "2.11.12")
|
||||
.settings(
|
||||
name := "core",
|
||||
ivyPaths := (ThisBuild / ivyPaths).value
|
||||
)
|
||||
.custom(
|
||||
idSuffix = "config1_2_",
|
||||
directorySuffix = "-config1.2",
|
||||
scalaVersions = Nil,
|
||||
_.settings(
|
||||
moduleName := name.value + "_config1.2",
|
||||
libraryDependencies += "com.typesafe" % "config" % "1.2.1"
|
||||
)
|
||||
)
|
||||
.custom(
|
||||
idSuffix = "config1_3_",
|
||||
directorySuffix = "-config1.3",
|
||||
scalaVersions = Nil,
|
||||
_.settings(
|
||||
moduleName := name.value + "_config1.3",
|
||||
libraryDependencies += "com.typesafe" % "config" % "1.3.3"
|
||||
)
|
||||
)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
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)
|
||||
}
|
||||
|
|
@ -0,0 +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
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// lazy val root = (project in file("."))
|
||||
// .aggregate(core.projectRefs ++ app.projectRefs: _*)
|
||||
// .settings(
|
||||
// )
|
||||
|
||||
lazy val core = (projectMatrix in file("core"))
|
||||
.scalaVersions("2.12.6", "2.11.12")
|
||||
.settings(
|
||||
name := "core"
|
||||
)
|
||||
.jvmPlatform()
|
||||
|
||||
lazy val app = (projectMatrix in file("app"))
|
||||
.dependsOn(core)
|
||||
.scalaVersions("2.12.6")
|
||||
.settings(
|
||||
name := "app"
|
||||
)
|
||||
.jvmPlatform()
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
package a
|
||||
|
||||
class Core {
|
||||
}
|
||||
|
||||
object Core extends Core
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
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)
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
> compile
|
||||
|
||||
$ exists core/target/jvm-2.12/classes/a/Core.class
|
||||
$ exists core/target/jvm-2.11/classes/a/Core.class
|
||||
Loading…
Reference in New Issue