summaryrefslogtreecommitdiff
path: root/project
diff options
context:
space:
mode:
Diffstat (limited to 'project')
-rw-r--r--project/BuildSettings.scala2
-rw-r--r--project/GenerateAnyVals.scala492
-rw-r--r--project/JarJar.scala2
-rw-r--r--project/MiMa.scala15
-rw-r--r--project/Osgi.scala42
-rw-r--r--project/ParserUtil.scala2
-rw-r--r--project/PartestUtil.scala19
-rw-r--r--project/Quiet.scala4
-rw-r--r--project/ScalaOptionParser.scala22
-rw-r--r--project/ScalaTool.scala4
-rw-r--r--project/ScriptCommands.scala129
-rw-r--r--project/VersionUtil.scala62
-rw-r--r--project/build.properties2
-rw-r--r--project/build.sbt2
-rw-r--r--project/plugins.sbt6
15 files changed, 711 insertions, 94 deletions
diff --git a/project/BuildSettings.scala b/project/BuildSettings.scala
index 76cd888a2d..8456f91f86 100644
--- a/project/BuildSettings.scala
+++ b/project/BuildSettings.scala
@@ -1,3 +1,5 @@
+package scala.build
+
import sbt._
/** This object defines keys that should be visible with an unqualified name in all .sbt files and the command line */
diff --git a/project/GenerateAnyVals.scala b/project/GenerateAnyVals.scala
new file mode 100644
index 0000000000..f349bfd16b
--- /dev/null
+++ b/project/GenerateAnyVals.scala
@@ -0,0 +1,492 @@
+package scala.build
+
+/** Code generation of the AnyVal types and their companions. */
+trait GenerateAnyValReps {
+ self: GenerateAnyVals =>
+
+ sealed abstract class AnyValNum(name: String, repr: Option[String], javaEquiv: String)
+ extends AnyValRep(name,repr,javaEquiv) {
+
+ case class Op(op : String, doc : String)
+
+ private def companionCoercions(tos: AnyValRep*) = {
+ tos.toList map (to =>
+ s"implicit def @javaequiv@2${to.javaEquiv}(x: @name@): ${to.name} = x.to${to.name}"
+ )
+ }
+ def coercionComment =
+"""/** Language mandated coercions from @name@ to "wider" types. */
+import scala.language.implicitConversions"""
+
+ def implicitCoercions: List[String] = {
+ val coercions = this match {
+ case B => companionCoercions(S, I, L, F, D)
+ case S | C => companionCoercions(I, L, F, D)
+ case I => companionCoercions(L, F, D)
+ case L => companionCoercions(F, D)
+ case F => companionCoercions(D)
+ case _ => Nil
+ }
+ if (coercions.isEmpty) Nil
+ else coercionComment.lines.toList ++ coercions
+ }
+
+ def isCardinal: Boolean = isIntegerType(this)
+ def unaryOps = {
+ val ops = List(
+ Op("+", "/** Returns this value, unmodified. */"),
+ Op("-", "/** Returns the negation of this value. */"))
+
+ if(isCardinal)
+ Op("~", "/**\n" +
+ " * Returns the bitwise negation of this value.\n" +
+ " * @example {{{\n" +
+ " * ~5 == -6\n" +
+ " * // in binary: ~00000101 ==\n" +
+ " * // 11111010\n" +
+ " * }}}\n" +
+ " */") :: ops
+ else ops
+ }
+
+ def bitwiseOps =
+ if (isCardinal)
+ List(
+ Op("|", "/**\n" +
+ " * Returns the bitwise OR of this value and `x`.\n" +
+ " * @example {{{\n" +
+ " * (0xf0 | 0xaa) == 0xfa\n" +
+ " * // in binary: 11110000\n" +
+ " * // | 10101010\n" +
+ " * // --------\n" +
+ " * // 11111010\n" +
+ " * }}}\n" +
+ " */"),
+ Op("&", "/**\n" +
+ " * Returns the bitwise AND of this value and `x`.\n" +
+ " * @example {{{\n" +
+ " * (0xf0 & 0xaa) == 0xa0\n" +
+ " * // in binary: 11110000\n" +
+ " * // & 10101010\n" +
+ " * // --------\n" +
+ " * // 10100000\n" +
+ " * }}}\n" +
+ " */"),
+ Op("^", "/**\n" +
+ " * Returns the bitwise XOR of this value and `x`.\n" +
+ " * @example {{{\n" +
+ " * (0xf0 ^ 0xaa) == 0x5a\n" +
+ " * // in binary: 11110000\n" +
+ " * // ^ 10101010\n" +
+ " * // --------\n" +
+ " * // 01011010\n" +
+ " * }}}\n" +
+ " */"))
+ else Nil
+
+ def shiftOps =
+ if (isCardinal)
+ List(
+ Op("<<", "/**\n" +
+ " * Returns this value bit-shifted left by the specified number of bits,\n" +
+ " * filling in the new right bits with zeroes.\n" +
+ " * @example {{{ 6 << 3 == 48 // in binary: 0110 << 3 == 0110000 }}}\n" +
+ " */"),
+
+ Op(">>>", "/**\n" +
+ " * Returns this value bit-shifted right by the specified number of bits,\n" +
+ " * filling the new left bits with zeroes.\n" +
+ " * @example {{{ 21 >>> 3 == 2 // in binary: 010101 >>> 3 == 010 }}}\n" +
+ " * @example {{{\n" +
+ " * -21 >>> 3 == 536870909\n" +
+ " * // in binary: 11111111 11111111 11111111 11101011 >>> 3 ==\n" +
+ " * // 00011111 11111111 11111111 11111101\n" +
+ " * }}}\n" +
+ " */"),
+
+ Op(">>", "/**\n" +
+ " * Returns this value bit-shifted right by the specified number of bits,\n" +
+ " * filling in the left bits with the same value as the left-most bit of this.\n" +
+ " * The effect of this is to retain the sign of the value.\n" +
+ " * @example {{{\n" +
+ " * -21 >> 3 == -3\n" +
+ " * // in binary: 11111111 11111111 11111111 11101011 >> 3 ==\n" +
+ " * // 11111111 11111111 11111111 11111101\n" +
+ " * }}}\n" +
+ " */"))
+ else Nil
+
+ def comparisonOps = List(
+ Op("==", "/** Returns `true` if this value is equal to x, `false` otherwise. */"),
+ Op("!=", "/** Returns `true` if this value is not equal to x, `false` otherwise. */"),
+ Op("<", "/** Returns `true` if this value is less than x, `false` otherwise. */"),
+ Op("<=", "/** Returns `true` if this value is less than or equal to x, `false` otherwise. */"),
+ Op(">", "/** Returns `true` if this value is greater than x, `false` otherwise. */"),
+ Op(">=", "/** Returns `true` if this value is greater than or equal to x, `false` otherwise. */"))
+
+ def otherOps = List(
+ Op("+", "/** Returns the sum of this value and `x`. */"),
+ Op("-", "/** Returns the difference of this value and `x`. */"),
+ Op("*", "/** Returns the product of this value and `x`. */"),
+ Op("/", "/** Returns the quotient of this value and `x`. */"),
+ Op("%", "/** Returns the remainder of the division of this value by `x`. */"))
+
+ // Given two numeric value types S and T , the operation type of S and T is defined as follows:
+ // If both S and T are subrange types then the operation type of S and T is Int.
+ // Otherwise the operation type of S and T is the larger of the two types wrt ranking.
+ // Given two numeric values v and w the operation type of v and w is the operation type
+ // of their run-time types.
+ def opType(that: AnyValNum): AnyValNum = {
+ val rank = IndexedSeq(I, L, F, D)
+ (rank indexOf this, rank indexOf that) match {
+ case (-1, -1) => I
+ case (r1, r2) => rank apply (r1 max r2)
+ }
+ }
+
+ def mkCoercions = numeric map (x => "def to%s: %s".format(x, x))
+ def mkUnaryOps = unaryOps map (x => "%s\n def unary_%s : %s".format(x.doc, x.op, this opType I))
+ def mkStringOps = List("def +(x: String): String")
+ def mkShiftOps = (
+ for (op <- shiftOps ; arg <- List(I, L)) yield
+ "%s\n def %s(x: %s): %s".format(op.doc, op.op, arg, this opType I)
+ )
+
+ def clumps: List[List[String]] = {
+ val xs1 = List(mkCoercions, mkUnaryOps, mkStringOps, mkShiftOps) map (xs => if (xs.isEmpty) xs else xs :+ "")
+ val xs2 = List(
+ mkBinOpsGroup(comparisonOps, numeric, _ => Z),
+ mkBinOpsGroup(bitwiseOps, cardinal, this opType _),
+ mkBinOpsGroup(otherOps, numeric, this opType _)
+ )
+ xs1 ++ xs2
+ }
+ def classLines = (clumps :+ commonClassLines).foldLeft(List[String]()) {
+ case (res, Nil) => res
+ case (res, lines) =>
+ val xs = lines map {
+ case "" => ""
+ case s => interpolate(s)
+ }
+ res ++ xs
+ }
+ def objectLines = {
+ val comp = if (isCardinal) cardinalCompanion else floatingCompanion
+ interpolate(comp + allCompanions + "\n" + nonUnitCompanions).trim.lines.toList ++ (implicitCoercions map interpolate)
+ }
+
+ /** Makes a set of binary operations based on the given set of ops, args, and resultFn.
+ *
+ * @param ops list of function names e.g. List(">>", "%")
+ * @param args list of types which should appear as arguments
+ * @param resultFn function which calculates return type based on arg type
+ * @return list of function definitions
+ */
+ def mkBinOpsGroup(ops: List[Op], args: List[AnyValNum], resultFn: AnyValNum => AnyValRep): List[String] = (
+ ops flatMap (op =>
+ args.map(arg =>
+ "%s\n def %s(x: %s): %s".format(op.doc, op.op, arg, resultFn(arg))) :+ ""
+ )
+ ).toList
+ }
+
+ sealed abstract class AnyValRep(val name: String, val repr: Option[String], val javaEquiv: String) {
+ def classLines: List[String]
+ def objectLines: List[String]
+ def commonClassLines = List(
+ "// Provide a more specific return type for Scaladoc",
+ "override def getClass(): Class[@name@] = ???"
+ )
+
+ def lcname = name.toLowerCase
+ def boxedSimpleName = this match {
+ case C => "Character"
+ case I => "Integer"
+ case _ => name
+ }
+ def boxedName = this match {
+ case U => "scala.runtime.BoxedUnit"
+ case _ => "java.lang." + boxedSimpleName
+ }
+ def zeroRep = this match {
+ case L => "0L"
+ case F => "0.0f"
+ case D => "0.0d"
+ case _ => "0"
+ }
+
+ def representation = repr.map(", a " + _).getOrElse("")
+
+ def indent(s: String) = if (s == "") "" else " " + s
+ def indentN(s: String) = s.lines map indent mkString "\n"
+
+ def boxUnboxInterpolations = Map(
+ "@boxRunTimeDoc@" -> """
+ * Runtime implementation determined by `scala.runtime.BoxesRunTime.boxTo%s`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]].
+ *""".format(boxedSimpleName),
+ "@unboxRunTimeDoc@" -> """
+ * Runtime implementation determined by `scala.runtime.BoxesRunTime.unboxTo%s`. See [[https://github.com/scala/scala src/library/scala/runtime/BoxesRunTime.java]].
+ *""".format(name),
+ "@unboxDoc@" -> "the %s resulting from calling %sValue() on `x`".format(name, lcname),
+ "@boxImpl@" -> "???",
+ "@unboxImpl@" -> "???"
+ )
+ def interpolations = Map(
+ "@name@" -> name,
+ "@representation@" -> representation,
+ "@javaequiv@" -> javaEquiv,
+ "@boxed@" -> boxedName,
+ "@lcname@" -> lcname,
+ "@zero@" -> zeroRep
+ ) ++ boxUnboxInterpolations
+
+ def interpolate(s: String): String = interpolations.foldLeft(s) {
+ case (str, (key, value)) => str.replaceAll(key, value)
+ }
+ def classDoc = interpolate(classDocTemplate)
+ def objectDoc = ""
+ def mkImports = ""
+
+ def mkClass = assemble("final abstract class " + name + " private extends AnyVal", classLines)
+ def mkObject = assemble("object " + name + " extends AnyValCompanion", objectLines)
+ def make() = List[String](
+ headerTemplate,
+ mkImports,
+ classDoc,
+ mkClass,
+ objectDoc,
+ mkObject
+ ) mkString ""
+
+ def assemble(decl: String, lines: List[String]): String = {
+ val body = if (lines.isEmpty) " { }\n\n" else lines map indent mkString (" {\n", "\n", "\n}\n")
+
+ decl + body + "\n"
+ }
+ override def toString = name
+ }
+}
+
+trait GenerateAnyValTemplates {
+ def headerTemplate = """/* __ *\
+** ________ ___ / / ___ Scala API **
+** / __/ __// _ | / / / _ | (c) 2002-2013, LAMP/EPFL **
+** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
+** /____/\___/_/ |_/____/_/ | | **
+** |/ **
+\* */
+
+// DO NOT EDIT, CHANGES WILL BE LOST
+// This auto-generated code can be modified in "project/GenerateAnyVals.scala".
+// Afterwards, running "sbt generateSources" regenerates this source file.
+
+package scala
+
+"""
+
+ def classDocTemplate = ("""
+/** `@name@`@representation@ (equivalent to Java's `@javaequiv@` primitive type) is a
+ * subtype of [[scala.AnyVal]]. Instances of `@name@` are not
+ * represented by an object in the underlying runtime system.
+ *
+ * There is an implicit conversion from [[scala.@name@]] => [[scala.runtime.Rich@name@]]
+ * which provides useful non-primitive operations.
+ */
+""".trim + "\n")
+
+ def allCompanions = """
+/** Transform a value type into a boxed reference type.
+ *@boxRunTimeDoc@
+ * @param x the @name@ to be boxed
+ * @return a @boxed@ offering `x` as its underlying value.
+ */
+def box(x: @name@): @boxed@ = @boxImpl@
+
+/** Transform a boxed type into a value type. Note that this
+ * method is not typesafe: it accepts any Object, but will throw
+ * an exception if the argument is not a @boxed@.
+ *@unboxRunTimeDoc@
+ * @param x the @boxed@ to be unboxed.
+ * @throws ClassCastException if the argument is not a @boxed@
+ * @return @unboxDoc@
+ */
+def unbox(x: java.lang.Object): @name@ = @unboxImpl@
+
+/** The String representation of the scala.@name@ companion object. */
+override def toString = "object scala.@name@"
+"""
+
+ def nonUnitCompanions = "" // todo
+
+ def cardinalCompanion = """
+/** The smallest value representable as a @name@. */
+final val MinValue = @boxed@.MIN_VALUE
+
+/** The largest value representable as a @name@. */
+final val MaxValue = @boxed@.MAX_VALUE
+"""
+
+ def floatingCompanion = """
+/** The smallest positive value greater than @zero@ which is
+ * representable as a @name@.
+ */
+final val MinPositiveValue = @boxed@.MIN_VALUE
+final val NaN = @boxed@.NaN
+final val PositiveInfinity = @boxed@.POSITIVE_INFINITY
+final val NegativeInfinity = @boxed@.NEGATIVE_INFINITY
+
+/** The negative number with the greatest (finite) absolute value which is representable
+ * by a @name@. Note that it differs from [[java.lang.@name@.MIN_VALUE]], which
+ * is the smallest positive value representable by a @name@. In Scala that number
+ * is called @name@.MinPositiveValue.
+ */
+final val MinValue = -@boxed@.MAX_VALUE
+
+/** The largest finite positive number representable as a @name@. */
+final val MaxValue = @boxed@.MAX_VALUE
+"""
+}
+
+class GenerateAnyVals extends GenerateAnyValReps with GenerateAnyValTemplates {
+ object B extends AnyValNum("Byte", Some("8-bit signed integer"), "byte")
+ object S extends AnyValNum("Short", Some("16-bit signed integer"), "short")
+ object C extends AnyValNum("Char", Some("16-bit unsigned integer"), "char")
+ object I extends AnyValNum("Int", Some("32-bit signed integer"), "int")
+ object L extends AnyValNum("Long", Some("64-bit signed integer"), "long")
+ object F extends AnyValNum("Float", Some("32-bit IEEE-754 floating point number"), "float")
+ object D extends AnyValNum("Double", Some("64-bit IEEE-754 floating point number"), "double")
+ object Z extends AnyValRep("Boolean", None, "boolean") {
+ def classLines = """
+/** Negates a Boolean expression.
+ *
+ * - `!a` results in `false` if and only if `a` evaluates to `true` and
+ * - `!a` results in `true` if and only if `a` evaluates to `false`.
+ *
+ * @return the negated expression
+ */
+def unary_! : Boolean
+
+/** Compares two Boolean expressions and returns `true` if they evaluate to the same value.
+ *
+ * `a == b` returns `true` if and only if
+ * - `a` and `b` are `true` or
+ * - `a` and `b` are `false`.
+ */
+def ==(x: Boolean): Boolean
+
+/**
+ * Compares two Boolean expressions and returns `true` if they evaluate to a different value.
+ *
+ * `a != b` returns `true` if and only if
+ * - `a` is `true` and `b` is `false` or
+ * - `a` is `false` and `b` is `true`.
+ */
+def !=(x: Boolean): Boolean
+
+/** Compares two Boolean expressions and returns `true` if one or both of them evaluate to true.
+ *
+ * `a || b` returns `true` if and only if
+ * - `a` is `true` or
+ * - `b` is `true` or
+ * - `a` and `b` are `true`.
+ *
+ * @note This method uses 'short-circuit' evaluation and
+ * behaves as if it was declared as `def ||(x: => Boolean): Boolean`.
+ * If `a` evaluates to `true`, `true` is returned without evaluating `b`.
+ */
+def ||(x: Boolean): Boolean
+
+/** Compares two Boolean expressions and returns `true` if both of them evaluate to true.
+ *
+ * `a && b` returns `true` if and only if
+ * - `a` and `b` are `true`.
+ *
+ * @note This method uses 'short-circuit' evaluation and
+ * behaves as if it was declared as `def &&(x: => Boolean): Boolean`.
+ * If `a` evaluates to `false`, `false` is returned without evaluating `b`.
+ */
+def &&(x: Boolean): Boolean
+
+// Compiler won't build with these seemingly more accurate signatures
+// def ||(x: => Boolean): Boolean
+// def &&(x: => Boolean): Boolean
+
+/** Compares two Boolean expressions and returns `true` if one or both of them evaluate to true.
+ *
+ * `a | b` returns `true` if and only if
+ * - `a` is `true` or
+ * - `b` is `true` or
+ * - `a` and `b` are `true`.
+ *
+ * @note This method evaluates both `a` and `b`, even if the result is already determined after evaluating `a`.
+ */
+def |(x: Boolean): Boolean
+
+/** Compares two Boolean expressions and returns `true` if both of them evaluate to true.
+ *
+ * `a & b` returns `true` if and only if
+ * - `a` and `b` are `true`.
+ *
+ * @note This method evaluates both `a` and `b`, even if the result is already determined after evaluating `a`.
+ */
+def &(x: Boolean): Boolean
+
+/** Compares two Boolean expressions and returns `true` if they evaluate to a different value.
+ *
+ * `a ^ b` returns `true` if and only if
+ * - `a` is `true` and `b` is `false` or
+ * - `a` is `false` and `b` is `true`.
+ */
+def ^(x: Boolean): Boolean
+
+// Provide a more specific return type for Scaladoc
+override def getClass(): Class[Boolean] = ???
+ """.trim.lines.toList
+
+ def objectLines = interpolate(allCompanions + "\n" + nonUnitCompanions).lines.toList
+ }
+ object U extends AnyValRep("Unit", None, "void") {
+ override def classDoc = """
+/** `Unit` is a subtype of [[scala.AnyVal]]. There is only one value of type
+ * `Unit`, `()`, and it is not represented by any object in the underlying
+ * runtime system. A method with return type `Unit` is analogous to a Java
+ * method which is declared `void`.
+ */
+"""
+ def classLines = List(
+ "// Provide a more specific return type for Scaladoc",
+ "override def getClass(): Class[Unit] = ???"
+ )
+ def objectLines = interpolate(allCompanions).lines.toList
+
+ override def boxUnboxInterpolations = Map(
+ "@boxRunTimeDoc@" -> "",
+ "@unboxRunTimeDoc@" -> "",
+ "@unboxDoc@" -> "the Unit value ()",
+ "@boxImpl@" -> "scala.runtime.BoxedUnit.UNIT",
+ "@unboxImpl@" -> "x.asInstanceOf[scala.runtime.BoxedUnit]"
+ )
+ }
+
+ def isSubrangeType = Set(B, S, C)
+ def isIntegerType = Set(B, S, C, I, L)
+ def isFloatingType = Set(F, D)
+ def isWideType = Set(L, D)
+
+ def cardinal = numeric filter isIntegerType
+ def numeric = List(B, S, C, I, L, F, D)
+ def values = List(U, Z) ++ numeric
+
+ def make() = values map (x => (x.name, x.make()))
+}
+
+object GenerateAnyVals {
+ def run(outDir: java.io.File) {
+ val av = new GenerateAnyVals
+
+ av.make() foreach { case (name, code ) =>
+ val file = new java.io.File(outDir, name + ".scala")
+ sbt.IO.write(file, code, java.nio.charset.Charset.forName("UTF-8"), false)
+ }
+ }
+}
diff --git a/project/JarJar.scala b/project/JarJar.scala
index 918060c9ee..3cb9e4cfff 100644
--- a/project/JarJar.scala
+++ b/project/JarJar.scala
@@ -1,3 +1,5 @@
+package scala.build
+
import org.pantsbuild.jarjar
import org.pantsbuild.jarjar._
import org.pantsbuild.jarjar.util._
diff --git a/project/MiMa.scala b/project/MiMa.scala
index 66442fc725..fb9bb175ab 100644
--- a/project/MiMa.scala
+++ b/project/MiMa.scala
@@ -1,10 +1,12 @@
+package scala.build
+
// It would be nice to use sbt-mima-plugin here, but the plugin is missing
// at least two features we need:
// * ability to run MiMa twice, swapping `curr` and `prev`, to detect
// both forwards and backwards incompatibilities (possibly fixed as of
// https://github.com/typesafehub/migration-manager/commit/2844ffa48b6d2255aa64bd687703aec21dadd55e)
// * ability to pass a filter file (https://github.com/typesafehub/migration-manager/issues/102)
-// So we invoke the MiMa CLI directly; it's also what the Ant build did.
+// So we invoke the MiMa CLI directly.
import sbt._
import sbt.Keys._
@@ -24,13 +26,12 @@ object MiMa {
def runOnce(prev: java.io.File, curr: java.io.File, isForward: Boolean): Unit = {
val direction = if (isForward) "forward" else "backward"
log.info(s"Checking $direction binary compatibility")
- log.debug(s"prev = $prev, curr = $curr")
+ log.info(s"prev = $prev, curr = $curr")
runMima(
prev = if (isForward) curr else prev,
curr = if (isForward) prev else curr,
// TODO: it would be nicer if each subproject had its own whitelist, but for now
- // for compatibility with how Ant did things, there's just one at the root.
- // once Ant is gone we'd be free to split it up.
+ // there's just one at the root. with the Ant build gone, we would be free now to split it.
filter = (baseDirectory in ThisBuild).value / s"bincompat-$direction.whitelist.conf",
log)
}
@@ -49,7 +50,11 @@ object MiMa {
"--prev", prev.getAbsolutePath,
"--curr", curr.getAbsolutePath,
"--filters", filter.getAbsolutePath,
- "--generate-filters"
+ "--generate-filters",
+ // !!! Command line MiMa (which we call rathan the sbt Plugin for reasons alluded to in f2d0f1e85) incorrectly
+ // defaults to no checking (!) if this isn't specified. Fixed in https://github.com/typesafehub/migration-manager/pull/138
+ // TODO: Try out the new "--direction both" mode of MiMa
+ "--direction", "backwards"
)
val exitCode = TrapExit(com.typesafe.tools.mima.cli.Main.main(args), log)
if (exitCode != 0)
diff --git a/project/Osgi.scala b/project/Osgi.scala
index c5d4734cab..b05751958a 100644
--- a/project/Osgi.scala
+++ b/project/Osgi.scala
@@ -1,17 +1,19 @@
-import aQute.lib.osgi.Builder
-import aQute.lib.osgi.Constants._
+package scala.build
+
+import aQute.bnd.osgi.Builder
+import aQute.bnd.osgi.Constants._
import java.util.Properties
import java.util.jar.Attributes
import sbt._
import sbt.Keys._
-import scala.collection.JavaConversions._
+import collection.JavaConverters._
import VersionUtil.versionProperties
/** OSGi packaging for the Scala build, distilled from sbt-osgi. We do not use sbt-osgi because it
* depends on a newer version of BND which gives slightly different output (probably OK to upgrade
- * in the future but for now it would make comparing the sbt and ant build output harder) and does
- * not allow a crucial bit of configuration that we need: Setting the classpath for BND. In sbt-osgi
- * this is always `fullClasspath in Compile` whereas we want `products in Compile in packageBin`. */
+ * in the future, now that the Ant build has been removed) and does not allow a crucial bit of
+ * configuration that we need: Setting the classpath for BND. In sbt-osgi this is always
+ * `fullClasspath in Compile` whereas we want `products in Compile in packageBin`. */
object Osgi {
val bundle = TaskKey[File]("osgiBundle", "Create an OSGi bundle.")
val bundleName = SettingKey[String]("osgiBundleName", "The Bundle-Name for the manifest.")
@@ -31,16 +33,17 @@ object Osgi {
"Export-Package" -> "*;version=${ver};-split-package:=merge-first",
"Import-Package" -> "scala.*;version=\"${range;[==,=+);${ver}}\",*",
"Bundle-Version" -> v,
- "Bundle-RequiredExecutionEnvironment" -> "JavaSE-1.6, JavaSE-1.7",
+ "Bundle-RequiredExecutionEnvironment" -> "JavaSE-1.8",
"-eclipse" -> "false"
)
},
jarlist := false,
- bundle <<= Def.task {
- bundleTask(headers.value.toMap, jarlist.value, (products in Compile in packageBin).value,
- (artifactPath in (Compile, packageBin)).value, Nil, streams.value)
- },
- packagedArtifact in (Compile, packageBin) <<= (artifact in (Compile, packageBin), bundle).identityMap,
+ bundle := Def.task {
+ val cp = (products in Compile in packageBin).value
+ bundleTask(headers.value.toMap, jarlist.value, cp,
+ (artifactPath in (Compile, packageBin)).value, cp, streams.value)
+ }.value,
+ packagedArtifact in (Compile, packageBin) := (((artifact in (Compile, packageBin)).value, bundle.value)),
// Also create OSGi source bundles:
packageOptions in (Compile, packageSrc) += Package.ManifestAttributes(
"Bundle-Name" -> (description.value + " Sources"),
@@ -56,18 +59,23 @@ object Osgi {
val builder = new Builder
builder.setClasspath(fullClasspath.toArray)
headers foreach { case (k, v) => builder.setProperty(k, v) }
- val includeRes = resourceDirectories.filter(_.exists).map(_.getAbsolutePath).mkString(",")
+
+ // https://github.com/scala/scala-dev/issues/254
+ // Must be careful not to include scala-asm.jar within scala-compiler.jar!
+ def resourceDirectoryRef(f: File) = (if (f.isDirectory) "" else "@") + f.getAbsolutePath
+
+ val includeRes = resourceDirectories.filter(_.exists).map(resourceDirectoryRef).mkString(",")
if(!includeRes.isEmpty) builder.setProperty(INCLUDERESOURCE, includeRes)
- builder.getProperties.foreach { case (k, v) => log.debug(s"bnd: $k: $v") }
+ builder.getProperties.asScala.foreach { case (k, v) => log.debug(s"bnd: $k: $v") }
// builder.build is not thread-safe because it uses a static SimpleDateFormat. This ensures
// that all calls to builder.build are serialized.
val jar = synchronized { builder.build }
- builder.getWarnings.foreach(s => log.warn(s"bnd: $s"))
- builder.getErrors.foreach(s => log.error(s"bnd: $s"))
+ builder.getWarnings.asScala.foreach(s => log.warn(s"bnd: $s"))
+ builder.getErrors.asScala.foreach(s => log.error(s"bnd: $s"))
IO.createDirectory(artifactPath.getParentFile)
if (jarlist) {
val entries = jar.getManifest.getEntries
- for ((name, resource) <- jar.getResources if name.endsWith(".class")) {
+ for ((name, resource) <- jar.getResources.asScala if name.endsWith(".class")) {
entries.put(name, new Attributes)
}
}
diff --git a/project/ParserUtil.scala b/project/ParserUtil.scala
index cdaf8831a5..bbd9129dbe 100644
--- a/project/ParserUtil.scala
+++ b/project/ParserUtil.scala
@@ -1,3 +1,5 @@
+package scala.build
+
import sbt._
import sbt.complete.Parser._
import sbt.complete.Parsers._
diff --git a/project/PartestUtil.scala b/project/PartestUtil.scala
index 0bbbc3dc69..127dcafefa 100644
--- a/project/PartestUtil.scala
+++ b/project/PartestUtil.scala
@@ -1,3 +1,5 @@
+package scala.build
+
import sbt._
import sbt.complete._, Parser._, Parsers._
@@ -28,14 +30,14 @@ object PartestUtil {
def partestParser(globalBase: File, testBase: File): Parser[String] = {
val knownUnaryOptions = List(
"--pos", "--neg", "--run", "--jvm", "--res", "--ant", "--scalap", "--specialized",
- "--scalacheck", "--instrumented", "--presentation", "--failed", "--update-check",
+ "--instrumented", "--presentation", "--failed", "--update-check",
"--show-diff", "--show-log", "--verbose", "--terse", "--debug", "--version", "--self-test", "--help")
val srcPathOption = "--srcpath"
val grepOption = "--grep"
- // HACK: if we parse `--srpath scaladoc`, we overwrite this var. The parser for test file paths
+ // HACK: if we parse `--srcpath scaladoc`, we overwrite this var. The parser for test file paths
// then lazily creates the examples based on the current value.
- // TODO is there a cleaner way to do this with SBT's parser infrastructure?
+ // TODO is there a cleaner way to do this with sbt's parser infrastructure?
var srcPath = "files"
var _testFiles: TestFiles = null
def testFiles = {
@@ -64,9 +66,9 @@ object PartestUtil {
}
val matchingFileName = try {
val filter = GlobFilter("*" + x + "*")
- testFiles.allTestCases.filter(x => filter.accept(x._1.name))
+ testFiles.allTestCases.filter(x => filter.accept(x._1.asFile.getPath))
} catch {
- case t: Throwable => Nil
+ case _: Throwable => Nil
}
(matchingFileContent ++ matchingFileName).map(_._2).distinct.sorted
}
@@ -86,7 +88,10 @@ object PartestUtil {
srcPath = path
opt + " " + path
}
- val P = oneOf(knownUnaryOptions.map(x => token(x))) | SrcPath | TestPathParser | Grep
- (Space ~> repsep(P, oneOrMore(Space))).map(_.mkString(" ")).?.map(_.getOrElse("")) <~ OptSpace
+
+ val ScalacOptsParser = (token("-Dpartest.scalac_opts=") ~ token(NotSpace)) map { case opt ~ v => opt + v }
+
+ val P = oneOf(knownUnaryOptions.map(x => token(x))) | SrcPath | TestPathParser | Grep | ScalacOptsParser
+ (Space ~> repsep(P, oneOrMore(Space))).map(_.mkString(" ")).?.map(_.getOrElse(""))
}
}
diff --git a/project/Quiet.scala b/project/Quiet.scala
index 84d01d5544..8ae08ad5a6 100644
--- a/project/Quiet.scala
+++ b/project/Quiet.scala
@@ -1,8 +1,10 @@
+package scala.build
+
import sbt._
import Keys._
object Quiet {
- // Workaround SBT issue described:
+ // Workaround sbt issue described:
//
// https://github.com/scala/scala-dev/issues/100
def silenceScalaBinaryVersionWarning = ivyConfiguration := {
diff --git a/project/ScalaOptionParser.scala b/project/ScalaOptionParser.scala
index b907045cb4..0208921959 100644
--- a/project/ScalaOptionParser.scala
+++ b/project/ScalaOptionParser.scala
@@ -1,3 +1,5 @@
+package scala.build
+
import ParserUtil._
import sbt._
import sbt.complete.Parser._
@@ -5,7 +7,7 @@ import sbt.complete.Parsers._
import sbt.complete._
object ScalaOptionParser {
- /** A SBT parser for the Scala command line runners (scala, scalac, etc) */
+ /** An sbt parser for the Scala command line runners (scala, scalac, etc) */
def scalaParser(entryPoint: String, globalBase: File): Parser[String] = {
def BooleanSetting(name: String): Parser[String] =
token(name)
@@ -79,30 +81,28 @@ object ScalaOptionParser {
P <~ token(OptSpace)
}
- // TODO retrieve this data programatically, ala https://github.com/scala/scala-tool-support/blob/master/bash-completion/src/main/scala/BashCompletion.scala
+ // TODO retrieve this data programmatically, ala https://github.com/scala/scala-tool-support/blob/master/bash-completion/src/main/scala/BashCompletion.scala
private def booleanSettingNames = List("-X", "-Xcheckinit", "-Xdev", "-Xdisable-assertions", "-Xexperimental", "-Xfatal-warnings", "-Xfull-lubs", "-Xfuture", "-Xlog-free-terms", "-Xlog-free-types", "-Xlog-implicit-conversions", "-Xlog-implicits", "-Xlog-reflective-calls",
"-Xno-forwarders", "-Xno-patmat-analysis", "-Xno-uescape", "-Xnojline", "-Xprint-pos", "-Xprint-types", "-Xprompt", "-Xresident", "-Xshow-phases", "-Xstrict-inference", "-Xverify", "-Y",
- "-Ybreak-cycles", "-Yclosure-elim", "-Yconst-opt", "-Ydead-code", "-Ydebug", "-Ycompact-trees", "-Ydisable-unreachable-prevention", "-YdisableFlatCpCaching", "-Ydoc-debug",
- "-Yeta-expand-keeps-star", "-Yide-debug", "-Yinfer-argument-types", "-Yinfer-by-name", "-Yinfer-debug", "-Yinline", "-Yinline-handlers",
- "-Yinline-warnings", "-Yissue-debug", "-Ylog-classpath", "-Ymacro-debug-lite", "-Ymacro-debug-verbose", "-Ymacro-no-expand",
- "-Yno-completion", "-Yno-generic-signatures", "-Yno-imports", "-Yno-load-impl-class", "-Yno-predef", "-Ynooptimise",
+ "-Ybreak-cycles", "-Ydebug", "-Ycompact-trees", "-YdisableFlatCpCaching", "-Ydoc-debug",
+ "-Yide-debug", "-Yinfer-argument-types",
+ "-Yissue-debug", "-Ylog-classpath", "-Ymacro-debug-lite", "-Ymacro-debug-verbose", "-Ymacro-no-expand",
+ "-Yno-completion", "-Yno-generic-signatures", "-Yno-imports", "-Yno-predef",
"-Yoverride-objects", "-Yoverride-vars", "-Ypatmat-debug", "-Yno-adapted-args", "-Ypartial-unification", "-Ypos-debug", "-Ypresentation-debug",
"-Ypresentation-strict", "-Ypresentation-verbose", "-Yquasiquote-debug", "-Yrangepos", "-Yreify-copypaste", "-Yreify-debug", "-Yrepl-class-based",
"-Yrepl-sync", "-Yshow-member-pos", "-Yshow-symkinds", "-Yshow-symowners", "-Yshow-syms", "-Yshow-trees", "-Yshow-trees-compact", "-Yshow-trees-stringified", "-Ytyper-debug",
"-Ywarn-adapted-args", "-Ywarn-dead-code", "-Ywarn-inaccessible", "-Ywarn-infer-any", "-Ywarn-nullary-override", "-Ywarn-nullary-unit", "-Ywarn-numeric-widen", "-Ywarn-unused", "-Ywarn-unused-import", "-Ywarn-value-discard",
"-deprecation", "-explaintypes", "-feature", "-help", "-no-specialization", "-nobootcp", "-nowarn", "-optimise", "-print", "-unchecked", "-uniqid", "-usejavacp", "-usemanifestcp", "-verbose", "-version")
private def stringSettingNames = List("-Xgenerate-phase-graph", "-Xmain-class", "-Xpluginsdir", "-Xshow-class", "-Xshow-object", "-Xsource-reader", "-Ydump-classes", "-Ygen-asmp",
- "-Ygen-javap", "-Ypresentation-log", "-Ypresentation-replay", "-Yrepl-outdir", "-d", "-dependencyfile", "-encoding", "-Xscript")
+ "-Ypresentation-log", "-Ypresentation-replay", "-Yrepl-outdir", "-d", "-dependencyfile", "-encoding", "-Xscript")
private def pathSettingNames = List("-bootclasspath", "-classpath", "-extdirs", "-javabootclasspath", "-javaextdirs", "-sourcepath", "-toolcp")
- private val phases = List("all", "parser", "namer", "packageobjects", "typer", "patmat", "superaccessors", "extmethods", "pickler", "refchecks", "uncurry", "tailcalls", "specialize", "explicitouter", "erasure", "posterasure", "lazyvals", "lambdalift", "constructors", "flatten", "mixin", "cleanup", "delambdafy", "icode", "jvm", "terminal")
+ private val phases = List("all", "parser", "namer", "packageobjects", "typer", "patmat", "superaccessors", "extmethods", "pickler", "refchecks", "uncurry", "tailcalls", "specialize", "explicitouter", "erasure", "posterasure", "fields", "lambdalift", "constructors", "flatten", "mixin", "cleanup", "delambdafy", "icode", "jvm", "terminal")
private val phaseSettings = List("-Xprint-icode", "-Ystop-after", "-Yskip", "-Yshow", "-Ystop-before", "-Ybrowse", "-Ylog", "-Ycheck", "-Xprint")
private def multiStringSettingNames = List("-Xmacro-settings", "-Xplugin", "-Xplugin-disable", "-Xplugin-require")
private def intSettingNames = List("-Xmax-classfile-name", "-Xelide-below", "-Ypatmat-exhaust-depth", "-Ypresentation-delay", "-Yrecursion")
private def choiceSettingNames = Map[String, List[String]](
- "-Ybackend" -> List("GenASM", "GenBCode"),
"-YclasspathImpl" -> List("flat", "recursive"),
"-Ydelambdafy" -> List("inline", "method"),
- "-Ylinearizer" -> List("dfs", "dump", "normal", "rpo"),
"-Ymacro-expand" -> List("discard", "none"),
"-Yresolve-term-conflict" -> List("error", "object", "package"),
"-g" -> List("line", "none", "notailcails", "source", "vars"),
@@ -110,7 +110,7 @@ object ScalaOptionParser {
private def multiChoiceSettingNames = Map[String, List[String]](
"-Xlint" -> List("adapted-args", "nullary-unit", "inaccessible", "nullary-override", "infer-any", "missing-interpolator", "doc-detached", "private-shadow", "type-parameter-shadow", "poly-implicit-overload", "option-implicit", "delayedinit-select", "by-name-right-associative", "package-object-classes", "unsound-match", "stars-align"),
"-language" -> List("help", "_", "dynamics", "postfixOps", "reflectiveCalls", "implicitConversions", "higherKinds", "existentials", "experimental.macros"),
- "-Yopt" -> List("l:none", "l:default", "l:method", "l:project", "l:classpath", "unreachable-code", "simplify-jumps", "empty-line-numbers", "empty-labels", "compact-locals", "nullness-tracking", "closure-elimination", "inline-project", "inline-global"),
+ "-opt" -> List("l:none", "l:default", "l:method", "l:project", "l:classpath", "unreachable-code", "simplify-jumps", "empty-line-numbers", "empty-labels", "compact-locals", "nullness-tracking", "closure-elimination", "inline-project", "inline-global"),
"-Ystatistics" -> List("parser", "typer", "patmat", "erasure", "cleanup", "jvm")
)
private def scalaVersionSettings = List("-Xmigration", "-Xsource")
diff --git a/project/ScalaTool.scala b/project/ScalaTool.scala
index 5e3f20b1ba..ace547c640 100644
--- a/project/ScalaTool.scala
+++ b/project/ScalaTool.scala
@@ -1,11 +1,11 @@
+package scala.build
+
import sbt._
import org.apache.commons.lang3.SystemUtils
import org.apache.commons.lang3.StringUtils.replaceEach
/**
* A class that generates a shell or batch script to execute a Scala program.
- *
- * This is a simplified copy of Ant task (see scala.tools.ant.ScalaTool).
*/
case class ScalaTool(mainClass: String,
classpath: List[String],
diff --git a/project/ScriptCommands.scala b/project/ScriptCommands.scala
index efeac95e6d..f6b700f007 100644
--- a/project/ScriptCommands.scala
+++ b/project/ScriptCommands.scala
@@ -1,32 +1,117 @@
+package scala.build
+
import sbt._
import Keys._
import BuildSettings.autoImport._
/** Custom commands for use by the Jenkins scripts. This keeps the surface area and call syntax small. */
object ScriptCommands {
- def all = Seq(setupPublishCore, setupValidateTest)
-
- /** Set up the environment for `validate/publish-core`. The argument is the Artifactory snapshot repository URL. */
- def setupPublishCore = Command.single("setupPublishCore") { case (state, url) =>
- Project.extract(state).append(Seq(
- baseVersionSuffix in Global := "SHA-SNAPSHOT",
- // Append build.timestamp to Artifactory URL to get consistent build numbers (see https://github.com/sbt/sbt/issues/2088):
- publishTo in Global := Some("scala-pr" at url.replaceAll("/$", "") + ";build.timestamp=" + System.currentTimeMillis),
- publishArtifact in (Compile, packageDoc) in ThisBuild := false,
- scalacOptions in Compile in ThisBuild += "-optimise",
- logLevel in ThisBuild := Level.Info,
- logLevel in update in ThisBuild := Level.Warn
- ), state)
- }
+ def all = Seq(
+ setupPublishCore,
+ setupValidateTest,
+ setupBootstrapStarr, setupBootstrapLocker, setupBootstrapQuick, setupBootstrapPublish
+ )
+
+ /** Set up the environment for `validate/publish-core`.
+ * The optional argument is the Artifactory snapshot repository URL. */
+ def setupPublishCore = setup("setupPublishCore") { args =>
+ Seq(
+ baseVersionSuffix in Global := "SHA-SNAPSHOT"
+ ) ++ (args match {
+ case Seq(url) => publishTarget(url)
+ case Nil => Nil
+ }) ++ noDocs ++ enableOptimizer
+ }
+
+ /** Set up the environment for `validate/test`.
+ * The optional argument is the Artifactory snapshot repository URL. */
+ def setupValidateTest = setup("setupValidateTest") { args =>
+ Seq(
+ testOptions in IntegrationTest in LocalProject("test") ++= Seq(Tests.Argument("--show-log"), Tests.Argument("--show-diff"))
+ ) ++ (args match {
+ case Seq(url) => Seq(resolvers in Global += "scala-pr" at url)
+ case Nil => Nil
+ }) ++ enableOptimizer
+ }
+
+ /** Set up the environment for building STARR in `validate/bootstrap`. The arguments are:
+ * - Repository URL for publishing
+ * - Version number to publish */
+ def setupBootstrapStarr = setup("setupBootstrapStarr") { case Seq(url, ver) =>
+ Seq(
+ baseVersion in Global := ver,
+ baseVersionSuffix in Global := "SPLIT"
+ ) ++ publishTarget(url) ++ noDocs ++ enableOptimizer
+ }
+
+ /** Set up the environment for building locker in `validate/bootstrap`. The arguments are:
+ * - Repository URL for publishing locker and resolving STARR
+ * - Version number to publish */
+ def setupBootstrapLocker = setup("setupBootstrapLocker") { case Seq(url, ver) =>
+ Seq(
+ baseVersion in Global := ver,
+ baseVersionSuffix in Global := "SPLIT",
+ resolvers in Global += "scala-pr" at url
+ ) ++ publishTarget(url) ++ noDocs ++ enableOptimizer
+ }
+
+ /** Set up the environment for building quick in `validate/bootstrap`. The arguments are:
+ * - Repository URL for publishing
+ * - Version number to publish */
+ def setupBootstrapQuick = setup("setupBootstrapQuick") { case Seq(url, ver) =>
+ Seq(
+ baseVersion in Global := ver,
+ baseVersionSuffix in Global := "SPLIT",
+ resolvers in Global += "scala-pr" at url,
+ testOptions in IntegrationTest in LocalProject("test") ++= Seq(Tests.Argument("--show-log"), Tests.Argument("--show-diff"))
+ ) ++ publishTarget(url) ++ enableOptimizer
+ }
- /** Set up the environment for `validate/test`. The argument is the Artifactory snapshot repository URL. */
- def setupValidateTest = Command.single("setupValidateTest") { case (state, url) =>
- //TODO When ant is gone, pass starr version as an argument to this command instead of using version.properties
- Project.extract(state).append(Seq(
+ /** Set up the environment for publishing in `validate/bootstrap`. The arguments are:
+ * - Temporary bootstrap repository URL for resolving modules
+ * - Version number to publish
+ * All artifacts are published to Sonatype. */
+ def setupBootstrapPublish = setup("setupBootstrapPublish") { case Seq(url, ver) =>
+ // Define a copy of the setting key here in case the plugin is not part of the build
+ val pgpPassphrase = SettingKey[Option[Array[Char]]]("pgp-passphrase", "The passphrase associated with the secret used to sign artifacts.", KeyRanks.BSetting)
+ Seq(
+ baseVersion in Global := ver,
+ baseVersionSuffix in Global := "SPLIT",
resolvers in Global += "scala-pr" at url,
- scalacOptions in Compile in ThisBuild += "-optimise",
- logLevel in ThisBuild := Level.Info,
- logLevel in update in ThisBuild := Level.Warn
- ), state)
+ publishTo in Global := Some("sonatype-releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2"),
+ credentials in Global += Credentials(Path.userHome / ".credentials-sonatype"),
+ pgpPassphrase in Global := Some(Array.empty)
+ ) ++ enableOptimizer
+ }
+
+ private[this] def setup(name: String)(f: Seq[String] => Seq[Setting[_]]) =
+ Command.args(name, name) { case (state, seq) => Project.extract(state).append(f(seq) ++ resetLogLevels, state) }
+
+ private[this] val resetLogLevels = Seq(
+ logLevel in ThisBuild := Level.Info,
+ logLevel in update in ThisBuild := Level.Warn
+ )
+
+ private[this] val enableOptimizer = Seq(
+ scalacOptions in Compile in ThisBuild += "-opt:l:classpath"
+ )
+
+ private[this] val noDocs = Seq(
+ publishArtifact in (Compile, packageDoc) in ThisBuild := false
+ )
+
+ private[this] def publishTarget(url: String) = {
+ // Append build.timestamp to Artifactory URL to get consistent build numbers (see https://github.com/sbt/sbt/issues/2088):
+ val url2 = if(url.startsWith("file:")) url else url.replaceAll("/$", "") + ";build.timestamp=" + System.currentTimeMillis
+ Seq(publishTo in Global := Some("scala-pr-publish" at url2))
+ }
+
+ /** Like `Def.sequential` but accumulate all results */
+ def sequence[B](tasks: List[Def.Initialize[Task[B]]]): Def.Initialize[Task[List[B]]] = tasks match {
+ case Nil => Def.task { Nil }
+ case x :: xs => Def.taskDyn {
+ val v = x.value
+ sequence(xs).apply((t: Task[List[B]]) => t.map(l => v :: l))
+ }
}
}
diff --git a/project/VersionUtil.scala b/project/VersionUtil.scala
index 4705bbb6ce..ebc2488345 100644
--- a/project/VersionUtil.scala
+++ b/project/VersionUtil.scala
@@ -1,3 +1,5 @@
+package scala.build
+
import sbt._
import Keys._
import java.util.Properties
@@ -8,8 +10,10 @@ import BuildSettings.autoImport._
object VersionUtil {
lazy val copyrightString = settingKey[String]("Copyright string.")
lazy val versionProperties = settingKey[Versions]("Version properties.")
- lazy val generateVersionPropertiesFile = taskKey[File]("Generating version properties file.")
- lazy val generateBuildCharacterPropertiesFile = taskKey[File]("Generating buildcharacter.properties file.")
+ lazy val buildCharacterPropertiesFile = settingKey[File]("The file which gets generated by generateBuildCharacterPropertiesFile")
+ lazy val generateVersionPropertiesFile = taskKey[File]("Generate version properties file.")
+ lazy val generateBuildCharacterPropertiesFile = taskKey[File]("Generate buildcharacter.properties file.")
+ lazy val extractBuildCharacterPropertiesFile = taskKey[File]("Extract buildcharacter.properties file from bootstrap scala-compiler.")
lazy val globalVersionSettings = Seq[Setting[_]](
// Set the version properties globally (they are the same for all projects)
@@ -18,21 +22,23 @@ object VersionUtil {
)
lazy val generatePropertiesFileSettings = Seq[Setting[_]](
- copyrightString := "Copyright 2002-2016, LAMP/EPFL",
+ copyrightString := "Copyright 2002-2016, LAMP/EPFL and Lightbend, Inc.",
resourceGenerators in Compile += generateVersionPropertiesFile.map(file => Seq(file)).taskValue,
generateVersionPropertiesFile := generateVersionPropertiesFileImpl.value
)
lazy val generateBuildCharacterFileSettings = Seq[Setting[_]](
+ buildCharacterPropertiesFile := ((baseDirectory in ThisBuild).value / "buildcharacter.properties"),
generateBuildCharacterPropertiesFile := generateBuildCharacterPropertiesFileImpl.value
)
- case class Versions(canonicalVersion: String, mavenVersion: String, osgiVersion: String, commitSha: String, commitDate: String, isRelease: Boolean) {
+ case class Versions(canonicalVersion: String, mavenBase: String, mavenSuffix: String, osgiVersion: String, commitSha: String, commitDate: String, isRelease: Boolean) {
val githubTree =
if(isRelease) "v" + mavenVersion
else if(commitSha != "unknown") commitSha
else "master"
+ def mavenVersion: String = mavenBase + mavenSuffix
override def toString = s"Canonical: $canonicalVersion, Maven: $mavenVersion, OSGi: $osgiVersion, github: $githubTree"
def toMap: Map[String, String] = Map(
@@ -45,23 +51,24 @@ object VersionUtil {
/** Compute the canonical, Maven and OSGi version number from `baseVersion` and `baseVersionSuffix`.
* Examples of the generated versions:
*
- * ("2.11.8", "SNAPSHOT" ) -> ("2.11.8-20151215-133023-7559aed3c5", "2.11.8-SNAPSHOT", "2.11.8.v20151215-133023-7559aed3c5")
- * ("2.11.8", "SHA-SNAPSHOT") -> ("2.11.8-20151215-133023-7559aed3c5", "2.11.8-7559aed3c5-SNAPSHOT", "2.11.8.v20151215-133023-7559aed3c5")
- * ("2.11.8", "" ) -> ("2.11.8", "2.11.8", "2.11.8.v20151215-133023-VFINAL-7559aed3c5")
- * ("2.11.8", "M3" ) -> ("2.11.8-M3", "2.11.8-M3", "2.11.8.v20151215-133023-M3-7559aed3c5")
- * ("2.11.8", "RC4" ) -> ("2.11.8-RC4", "2.11.8-RC4", "2.11.8.v20151215-133023-RC4-7559aed3c5")
- * ("2.11.8-RC4", "SPLIT" ) -> ("2.11.8-RC4", "2.11.8-RC4", "2.11.8.v20151215-133023-RC4-7559aed3c5")
+ * ("2.11.8", "SNAPSHOT" ) -> ("2.11.8-20151215-133023-7559aed", "2.11.8-SNAPSHOT", "2.11.8.v20151215-133023-7559aed")
+ * ("2.11.8", "SHA-SNAPSHOT") -> ("2.11.8-20151215-133023-7559aed", "2.11.8-7559aed-SNAPSHOT", "2.11.8.v20151215-133023-7559aed")
+ * ("2.11.8", "SHA-NIGHTLY" ) -> ("2.11.8-7559aed-nightly", "2.11.8-7559aed-nightly", "2.11.8.v20151215-133023-NIGHTLY-7559aed")
+ * ("2.11.8", "" ) -> ("2.11.8", "2.11.8", "2.11.8.v20151215-133023-VFINAL-7559aed")
+ * ("2.11.8", "M3" ) -> ("2.11.8-M3", "2.11.8-M3", "2.11.8.v20151215-133023-M3-7559aed")
+ * ("2.11.8", "RC4" ) -> ("2.11.8-RC4", "2.11.8-RC4", "2.11.8.v20151215-133023-RC4-7559aed")
+ * ("2.11.8-RC4", "SPLIT" ) -> ("2.11.8-RC4", "2.11.8-RC4", "2.11.8.v20151215-133023-RC4-7559aed")
*
* A `baseVersionSuffix` of "SNAPSHOT" is the default, which is used for local snapshot builds. The PR validation
- * job uses "SHA-SNAPSHOT". An empty suffix is used for releases. All other suffix values are treated as RC /
- * milestone builds. The special suffix value "SPLIT" is used to split the real suffix off from `baseVersion`
- * instead and then apply the usual logic. */
+ * job uses "SHA-SNAPSHOT". A proper version number for a nightly build can be computed with "SHA-nightly". An empty
+ * suffix is used for releases. All other suffix values are treated as RC / milestone builds. The special suffix
+ * value "SPLIT" is used to split the real suffix off from `baseVersion` instead and then apply the usual logic. */
private lazy val versionPropertiesImpl: Def.Initialize[Versions] = Def.setting {
val (base, suffix) = {
val (b, s) = (baseVersion.value, baseVersionSuffix.value)
if(s == "SPLIT") {
- val split = """([\w+\.]+)(-[\w+\.]+)??""".r
+ val split = """([\w+\.]+)(-[\w+\.-]+)??""".r
val split(b2, sOrNull) = b
(b2, Option(sOrNull).map(_.drop(1)).getOrElse(""))
} else (b, s)
@@ -76,16 +83,17 @@ object VersionUtil {
}
val date = executeTool("get-scala-commit-date")
- val sha = executeTool("get-scala-commit-sha").substring(0, 7) // The script produces 10 digits at the moment
-
- val (canonicalV, mavenV, osgiV, release) = suffix match {
- case "SNAPSHOT" => (s"$base-$date-$sha", s"$base-SNAPSHOT", s"$base.v$date-$sha", false)
- case "SHA-SNAPSHOT" => (s"$base-$date-$sha", s"$base-$sha-SNAPSHOT", s"$base.v$date-$sha", false)
- case "" => (s"$base", s"$base", s"$base.v$date-VFINAL-$sha", true)
- case suffix => (s"$base-$suffix", s"$base-$suffix", s"$base.v$date-$suffix-$sha", true)
+ val sha = executeTool("get-scala-commit-sha").substring(0, 7)
+
+ val (canonicalV, mavenSuffix, osgiV, release) = suffix match {
+ case "SNAPSHOT" => (s"$base-$date-$sha", s"-SNAPSHOT", s"$base.v$date-$sha", false)
+ case "SHA-SNAPSHOT" => (s"$base-$date-$sha", s"-$sha-SNAPSHOT", s"$base.v$date-$sha", false)
+ case "SHA-NIGHTLY" => (s"$base-$sha-nightly", s"-$sha-nightly", s"$base.v$date-NIGHTLY-$sha", true)
+ case "" => (s"$base", "", s"$base.v$date-VFINAL-$sha", true)
+ case suffix => (s"$base-$suffix", s"-$suffix", s"$base.v$date-$suffix-$sha", true)
}
- Versions(canonicalV, mavenV, osgiV, sha, date, release)
+ Versions(canonicalV, base, mavenSuffix, osgiV, sha, date, release)
}
private lazy val generateVersionPropertiesFileImpl: Def.Initialize[Task[File]] = Def.task {
@@ -94,7 +102,11 @@ object VersionUtil {
}
private lazy val generateBuildCharacterPropertiesFileImpl: Def.Initialize[Task[File]] = Def.task {
- writeProps(versionProperties.value.toMap, (baseDirectory in ThisBuild).value / "buildcharacter.properties")
+ val v = versionProperties.value
+ writeProps(v.toMap ++ versionProps ++ Map(
+ "maven.version.base" -> v.mavenBase,
+ "maven.version.suffix" -> v.mavenSuffix
+ ), buildCharacterPropertiesFile.value)
}
private def writeProps(m: Map[String, String], propFile: File): File = {
@@ -139,10 +151,10 @@ object VersionUtil {
def bootstrapDep(baseDir: File, path: String, libName: String): ModuleID = {
val sha = IO.read(baseDir / path / s"$libName.jar.desired.sha1").split(' ')(0)
bootstrapOrganization(path) % libName % sha from
- s"https://dl.bintray.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap/$sha/$path/$libName.jar"
+ s"https://repo.lightbend.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap/$sha/$path/$libName.jar"
}
- /** Copy a boostrap dependency JAR that is on the classpath to a file */
+ /** Copy a bootstrap dependency JAR that is on the classpath to a file */
def copyBootstrapJar(cp: Seq[Attributed[File]], baseDir: File, path: String, libName: String): Unit = {
val org = bootstrapOrganization(path)
val resolved = cp.find { a =>
diff --git a/project/build.properties b/project/build.properties
index 35c88bab7d..27e88aa115 100644
--- a/project/build.properties
+++ b/project/build.properties
@@ -1 +1 @@
-sbt.version=0.13.12
+sbt.version=0.13.13
diff --git a/project/build.sbt b/project/build.sbt
new file mode 100644
index 0000000000..a604896ded
--- /dev/null
+++ b/project/build.sbt
@@ -0,0 +1,2 @@
+// Add genprod to the build; It should be moved from `src/build` to `project` now that the Ant build is gone
+sources in Compile += ((baseDirectory).value.getParentFile / "src" / "build" / "genprod.scala")
diff --git a/project/plugins.sbt b/project/plugins.sbt
index 114fae89bc..ca80c88a9e 100644
--- a/project/plugins.sbt
+++ b/project/plugins.sbt
@@ -5,15 +5,15 @@ libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.3.2"
libraryDependencies += "org.pantsbuild" % "jarjar" % "1.6.3"
-libraryDependencies += "biz.aQute" % "bndlib" % "1.50.0"
+libraryDependencies += "biz.aQute.bnd" % "biz.aQute.bnd" % "2.4.1"
enablePlugins(BuildInfoPlugin)
// configure sbt-buildinfo to send the externalDependencyClasspath to the main build, which allows using it for the IntelliJ project config
-lazy val buildClasspath = taskKey[String]("Colon-separated list of entries on the sbt build classpath.")
+lazy val buildClasspath = taskKey[String]("Colon-separated (or semicolon-separated in case of Windows) list of entries on the sbt build classpath.")
-buildClasspath := (externalDependencyClasspath in Compile).value.map(_.data).mkString(":")
+buildClasspath := (externalDependencyClasspath in Compile).value.map(_.data).mkString(java.io.File.pathSeparator)
buildInfoKeys := Seq[BuildInfoKey](buildClasspath)