Skip to content

Commit

Permalink
Merge pull request #19 from lrytz/crossVersion2
Browse files Browse the repository at this point in the history
Convert to AutoPlugin, apply Scala version settings to the build
  • Loading branch information
lrytz authored Apr 25, 2017
2 parents 1704ecd + 38b1813 commit 74d8b0b
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 35 deletions.
26 changes: 20 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,19 @@ addSbtPlugin("org.scala-lang.modules" % "scala-module-plugin" % "1.0.6")
Then, in your `build.sbt` add:

```
scalaModuleSettings
import ScalaModulePlugin._
scalaModuleSettings // in a multi-project build, you might want to apply these settings only to the
// main project (example: scala-parallel-collections)
name := "<module name>"
repoName := "<GitHub repo name>" // the repo under github.com/scala/, only required if different from name
organization := "<org>" // only required if different from "org.scala-lang.modules"
version := "<module version>"
// The plugin uses `scalaVersionsByJvm` to set `crossScalaVersions` according to the JVM major version.
// The `scalaVersion` is set to `crossScalaVersions.value.head`.
scalaVersionsByJvm := {
// The plugin uses `scalaVersionsByJvm` to set `crossScalaVersions in ThisBuild` according to the JVM major version.
// The `scalaVersion in ThisBuild` is set to `crossScalaVersions.value.head`.
scalaVersionsByJvm in ThisBuild := {
val v211 = "2.11.11"
val v212 = "2.12.2"
val v213 = "2.13.0-M1"
Expand All @@ -32,8 +35,7 @@ scalaVersionsByJvm := {
6 -> List(v211 -> true),
7 -> List(v211 -> false),
8 -> List(v212 -> true, v213 -> true, v211 -> false),
9 -> List(v212, v213, v211).map(_ -> false)
)
9 -> List(v212, v213, v211).map(_ -> false))
}
mimaPreviousVersion := Some("1.0.3") // enables MiMa (`None` by default, which disables it)
Expand All @@ -43,6 +45,18 @@ OsgiKeys.exportPackage := Seq(s"<exported package>;version=${version.value}")
// Other settings
```

These additional settings are enabled by `scalaModuleSettings`:
- `scalacOptions in (Compile, compile) ++= Seq("-feature", "-deprecation", "-unchecked", "-Xlint")`
- A `projectName.properties` file is generated and packaged
- `fork in Test := true` to work around some classpath clashes with scala-xml
- `publishTo` sonatype, credentials file expected in `~/.ivy2/.credentials`
- POM and OSGi metadata

The following settings are also available:
- `enableOptimizer` adds `-opt:l:classpath` or `-optimize` to `scalacOptions in (Compile, compile)`,
depending on the Scala version
- `disablePublishing` is useful for multi-project builds for projects that should not be published

## Cutting a new release

- Sign in to Bintray (https://bintray.com/login) or create an "Open Source" account (https://bintray.com/signup/oss)
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=0.13.13
sbt.version=0.13.15
87 changes: 59 additions & 28 deletions src/main/scala/ScalaModulePlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,85 @@ import Keys._
import com.typesafe.sbt.osgi.{OsgiKeys, SbtOsgi}
import com.typesafe.tools.mima.plugin.{MimaPlugin, MimaKeys}, MimaKeys._

object ScalaModulePlugin extends Plugin {
val repoName = settingKey[String]("The name of the repository under github.com/scala/.")
val mimaPreviousVersion = settingKey[Option[String]]("The version of this module to compare against when running MiMa.")
val scalaVersionsByJvm = settingKey[Map[Int, List[(String, Boolean)]]]("For a Java major version (6, 8, 9), a list of Scala version and a flag indicating whether to use this combination for publishing.")
object ScalaModulePlugin extends AutoPlugin {
val repoName = settingKey[String]("The name of the repository under github.com/scala/.")
val mimaPreviousVersion = settingKey[Option[String]]("The version of this module to compare against when running MiMa.")
val scalaVersionsByJvm = settingKey[Map[Int, List[(String, Boolean)]]]("For a Java major version (6, 8, 9), a list of a Scala version and a flag indicating whether to use this combination for publishing.")

private val canRunMima = taskKey[Boolean]("Decides if MiMa should run.")
private val runMimaIfEnabled = taskKey[Unit]("Run MiMa if mimaPreviousVersion and the module can be resolved against the current scalaBinaryVersion.")
// Settings applied to the entire build when the plugin is loaded.

lazy val scalaModuleSettings: Seq[Setting[_]] = Seq(
repoName := name.value,

mimaPreviousVersion := None,
override def trigger = allRequirements

scalaVersionsByJvm := Map.empty,
override def buildSettings: Seq[Setting[_]] = Seq(
scalaVersionsByJvm := Map.empty,

crossScalaVersions := {
crossScalaVersions in ThisBuild := {
val OneDot = """1\.(\d).*""".r // 1.6, 1.8
val Maj = """(\d+).*""".r // 9
val javaVersion = System.getProperty("java.version") match {
case OneDot(n) => n.toInt
case Maj(n) => n.toInt
case v => throw new RuntimeException(s"Unknown Java version: $v")
}
val isTravisPublishing = Option(System.getenv("TRAVIS_TAG")).getOrElse("").trim.nonEmpty
val scalaVersions = scalaVersionsByJvm.value.getOrElse(javaVersion, Nil) collect {

val isTravis = Option(System.getenv("TRAVIS")).exists(_ == "true") // `contains` doesn't exist in Scala 2.10
val isTravisPublishing = Option(System.getenv("TRAVIS_TAG")).exists(_.trim.nonEmpty)

val byJvm = scalaVersionsByJvm.value
if (byJvm.isEmpty)
throw new RuntimeException(s"Make sure to define `scalaVersionsByJvm in ThisBuild` in `build.sbt` in the root project, using the `ThisBuild` scope.")

val scalaVersions = byJvm.getOrElse(javaVersion, Nil) collect {
case (v, publish) if !isTravisPublishing || publish => v
}
if (scalaVersions.isEmpty) {
if (isTravisPublishing) {
if (isTravis) {
sLog.value.warn(s"No Scala version in `scalaVersionsByJvm` in build.sbt needs to be released on Java major version $javaVersion.")
// Exit successfully, don't fail the (travis) build. This happens for example if `openjdk7`
// is part of the travis configuration for testing, but it's not used for releasing against
// any Scala version.
System.exit(0)
} else
throw new RuntimeException(s"No Scala version for Java major version $javaVersion. Adjust `scalaVersionsByJvm` in build.sbt.")
throw new RuntimeException(s"No Scala version for Java major version $javaVersion. Change your Java version or adjust `scalaVersionsByJvm` in build.sbt.")
}
scalaVersions
},

scalaVersion := crossScalaVersions.value.head,
scalaVersion in ThisBuild := crossScalaVersions.value.head
)

/**
* Enable `-opt:l:classpath` or `-optimize`, depending on the scala version.
*/
lazy val enableOptimizer: Setting[_] = scalacOptions in (Compile, compile) += {
val ScalaMaj = """2\.(\d+)\..*""".r
val ScalaMaj(scalaMaj) = scalaVersion.value
if (scalaMaj.toInt >= 12) "-opt:l:classpath" else "-optimize"
}

/**
* Practical for multi-project builds.
*/
lazy val disablePublishing: Seq[Setting[_]] = Seq(
publishArtifact := false,
// The above is enough for Maven repos but it doesn't prevent publishing of ivy.xml files
publish := {},
publishLocal := {},
publishTo := Some(Resolver.file("devnull", file("/dev/null")))
)

/**
* To be included in the main sbt project of a Scala module.
*/
lazy val scalaModuleSettings: Seq[Setting[_]] = Seq(
repoName := name.value,

organization := "org.scala-lang.modules",
mimaPreviousVersion := None,

// so we don't have to wait for sonatype to synch to maven central when deploying a new module
resolvers += Resolver.sonatypeRepo("releases"),
organization := "org.scala-lang.modules",

// don't use for doc scope, scaladoc warnings are not to be reckoned with
// TODO: turn on for nightlies, but don't enable for PR validation... "-Xfatal-warnings"
scalacOptions in compile ++= Seq("-optimize", "-feature", "-deprecation", "-unchecked", "-Xlint"),
scalacOptions in (Compile, compile) ++= Seq("-feature", "-deprecation", "-unchecked", "-Xlint"),

// Generate $name.properties to store our version as well as the scala version used to build
resourceGenerators in Compile += Def.task {
Expand All @@ -76,8 +105,6 @@ object ScalaModulePlugin extends Plugin {
// alternatively, manage the scala instance as shown at the end of this file (commented)
fork in Test := true,

publishArtifact in Test := false,

// maven publishing
publishTo := Some(
if (version.value.trim.endsWith("SNAPSHOT")) Resolver.sonatypeRepo("snapshots")
Expand Down Expand Up @@ -114,7 +141,7 @@ object ScalaModulePlugin extends Plugin {
) ++ mimaSettings ++ scalaModuleOsgiSettings

// adapted from https://github.com/typesafehub/migration-manager/blob/0.1.6/sbtplugin/src/main/scala/com/typesafe/tools/mima/plugin/SbtMima.scala#L69
def artifactExists(organization: String, name: String, scalaBinaryVersion: String, version: String, ivy: IvySbt, s: TaskStreams): Boolean = {
private def artifactExists(organization: String, name: String, scalaBinaryVersion: String, version: String, ivy: IvySbt, s: TaskStreams): Boolean = {
val moduleId = new ModuleID(organization, s"${name}_$scalaBinaryVersion", version)
val moduleSettings = InlineConfiguration(
"dummy" % "test" % "version",
Expand All @@ -135,7 +162,11 @@ object ScalaModulePlugin extends Plugin {
}
}

lazy val mimaSettings: Seq[Setting[_]] = MimaPlugin.mimaDefaultSettings ++ Seq(
// Internal task keys for the MiMa settings
private val canRunMima = taskKey[Boolean]("Decides if MiMa should run.")
private val runMimaIfEnabled = taskKey[Unit]("Run MiMa if mimaPreviousVersion and the module can be resolved against the current scalaBinaryVersion.")

private lazy val mimaSettings: Seq[Setting[_]] = MimaPlugin.mimaDefaultSettings ++ Seq(
// manual cross-versioning because https://github.com/typesafehub/migration-manager/issues/62
mimaPreviousArtifacts := Set(organization.value % s"${name.value}_${scalaBinaryVersion.value}" % mimaPreviousVersion.value.getOrElse("dummy")),

Expand Down Expand Up @@ -165,9 +196,9 @@ object ScalaModulePlugin extends Plugin {
)

// a setting-transform to turn the regular version into something osgi can deal with
val osgiVersion = version(_.replace('-', '.'))
private val osgiVersion = version(_.replace('-', '.'))

lazy val scalaModuleOsgiSettings = SbtOsgi.osgiSettings ++ Seq(
private lazy val scalaModuleOsgiSettings = SbtOsgi.osgiSettings ++ Seq(
OsgiKeys.bundleSymbolicName := s"${organization.value}.${name.value}",
OsgiKeys.bundleVersion := osgiVersion.value,

Expand Down

0 comments on commit 74d8b0b

Please sign in to comment.