diff --git a/README.md b/README.md index f461c8f..1a3b742 100644 --- a/README.md +++ b/README.md @@ -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 := "" repoName := "" // the repo under github.com/scala/, only required if different from name organization := "" // only required if different from "org.scala-lang.modules" 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" @@ -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) @@ -43,6 +45,18 @@ OsgiKeys.exportPackage := Seq(s";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) diff --git a/project/build.properties b/project/build.properties index 27e88aa..64317fd 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.13 +sbt.version=0.13.15 diff --git a/src/main/scala/ScalaModulePlugin.scala b/src/main/scala/ScalaModulePlugin.scala index 05eed73..b8b5103 100644 --- a/src/main/scala/ScalaModulePlugin.scala +++ b/src/main/scala/ScalaModulePlugin.scala @@ -3,22 +3,19 @@ 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 { @@ -26,33 +23,65 @@ object ScalaModulePlugin extends Plugin { 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 { @@ -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") @@ -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", @@ -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")), @@ -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,