2016-07-07 00:56:31 +02:00
|
|
|
import scala.util.control.NonFatal
|
2014-05-01 18:50:07 +02:00
|
|
|
import sbt._
|
|
|
|
|
import Keys._
|
|
|
|
|
|
|
|
|
|
object Util {
|
2017-03-29 15:43:38 +02:00
|
|
|
val ExclusiveTest: Tags.Tag = Tags.Tag("exclusive-test")
|
|
|
|
|
|
|
|
|
|
val componentID: SettingKey[Option[String]] = settingKey[Option[String]]("")
|
|
|
|
|
val scalaKeywords: TaskKey[Set[String]] = taskKey[Set[String]]("")
|
|
|
|
|
val generateKeywords: TaskKey[File] = taskKey[File]("")
|
2014-05-01 18:50:07 +02:00
|
|
|
|
2014-12-18 05:38:10 +01:00
|
|
|
def noPublishSettings: Seq[Setting[_]] = Seq(publish := {})
|
2014-05-01 18:50:07 +02:00
|
|
|
|
2014-05-28 15:12:55 +02:00
|
|
|
def crossBuild: Seq[Setting[_]] =
|
2014-05-16 22:50:34 +02:00
|
|
|
Seq(
|
|
|
|
|
crossPaths := (scalaBinaryVersion.value match {
|
2016-11-16 15:41:18 +01:00
|
|
|
case "2.10" => false
|
|
|
|
|
case _ => true
|
2014-05-16 22:50:34 +02:00
|
|
|
})
|
|
|
|
|
)
|
2014-05-01 18:50:07 +02:00
|
|
|
|
2017-03-29 15:43:38 +02:00
|
|
|
lazy val javaOnlySettings: Seq[Setting[_]] = Seq(
|
|
|
|
|
// crossPaths := false,
|
|
|
|
|
compileOrder := CompileOrder.JavaThenScala,
|
|
|
|
|
unmanagedSourceDirectories in Compile := Seq((javaSource in Compile).value)
|
|
|
|
|
)
|
|
|
|
|
|
2014-05-01 18:50:07 +02:00
|
|
|
lazy val baseScalacOptions = Seq(
|
|
|
|
|
scalacOptions ++= Seq("-Xelide-below", "0"),
|
2017-03-29 15:43:38 +02:00
|
|
|
scalacOptions ++= (CrossVersion partialVersion scalaVersion.value match {
|
2015-02-03 04:44:02 +01:00
|
|
|
case Some((2, 9)) | Some((2, 8)) => Nil // support 2.9 for some subprojects for the Scala Eclipse IDE
|
2016-06-17 23:15:23 +02:00
|
|
|
case _ => Seq(
|
|
|
|
|
"-encoding", "utf8",
|
|
|
|
|
"-deprecation", "-feature", "-unchecked", "-Xlint",
|
|
|
|
|
"-language:existentials",
|
|
|
|
|
"-language:higherKinds",
|
|
|
|
|
"-language:implicitConversions",
|
|
|
|
|
"-language:postfixOps",
|
|
|
|
|
"-Xfuture",
|
|
|
|
|
"-Yno-adapted-args",
|
|
|
|
|
"-Ywarn-dead-code",
|
2016-07-12 12:48:43 +02:00
|
|
|
"-Ywarn-numeric-widen",
|
2016-07-12 13:45:40 +02:00
|
|
|
"-Ywarn-unused",
|
2016-07-12 12:48:43 +02:00
|
|
|
"-Ywarn-unused-import"
|
2016-06-17 23:15:23 +02:00
|
|
|
)
|
2017-03-29 15:43:38 +02:00
|
|
|
}),
|
|
|
|
|
scalacOptions ++= (CrossVersion partialVersion scalaVersion.value match {
|
2014-10-10 21:42:26 +02:00
|
|
|
case Some((2, 10)) => Seq("-deprecation", "-Xlint")
|
|
|
|
|
case _ => Seq()
|
2017-03-29 15:43:38 +02:00
|
|
|
})
|
2014-05-01 18:50:07 +02:00
|
|
|
)
|
|
|
|
|
|
2017-03-29 15:43:38 +02:00
|
|
|
def projectComponent: Setting[_] = projectID := (componentID.value match {
|
|
|
|
|
case Some(id) => projectID.value extra ("e:component" -> id)
|
|
|
|
|
case None => projectID.value
|
|
|
|
|
})
|
2014-05-01 18:50:07 +02:00
|
|
|
|
|
|
|
|
lazy val apiDefinitions = TaskKey[Seq[File]]("api-definitions")
|
|
|
|
|
|
2015-07-10 11:53:48 +02:00
|
|
|
def generateAPICached(defs: Seq[File], cp: Classpath, out: File, main: Option[String], run: ScalaRun, s: TaskStreams): Seq[File] =
|
2014-05-01 18:50:07 +02:00
|
|
|
{
|
|
|
|
|
def gen() = generateAPI(defs, cp, out, main, run, s)
|
2015-07-10 11:53:48 +02:00
|
|
|
val f = FileFunction.cached(s.cacheDirectory / "gen-api", FilesInfo.hash) { _ => gen().toSet } // TODO: check if output directory changed
|
2014-05-01 18:50:07 +02:00
|
|
|
f(defs.toSet).toSeq
|
|
|
|
|
}
|
|
|
|
|
def generateAPI(defs: Seq[File], cp: Classpath, out: File, main: Option[String], run: ScalaRun, s: TaskStreams): Seq[File] =
|
|
|
|
|
{
|
|
|
|
|
IO.delete(out)
|
|
|
|
|
IO.createDirectory(out)
|
|
|
|
|
val args = "xsbti.api" :: out.getAbsolutePath :: defs.map(_.getAbsolutePath).toList
|
|
|
|
|
val mainClass = main getOrElse "No main class defined for datatype generator"
|
|
|
|
|
toError(run.run(mainClass, cp.files, args, s.log))
|
|
|
|
|
(out ** "*.java").get
|
|
|
|
|
}
|
|
|
|
|
def lastCompilationTime(analysis: sbt.inc.Analysis): Long =
|
|
|
|
|
{
|
|
|
|
|
val lastCompilation = analysis.compilations.allCompilations.lastOption
|
|
|
|
|
lastCompilation.map(_.startTime) getOrElse 0L
|
|
|
|
|
}
|
|
|
|
|
def generateVersionFile(version: String, dir: File, s: TaskStreams, analysis: sbt.inc.Analysis): Seq[File] =
|
|
|
|
|
{
|
|
|
|
|
import java.util.{ Date, TimeZone }
|
|
|
|
|
val formatter = new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss")
|
|
|
|
|
formatter.setTimeZone(TimeZone.getTimeZone("GMT"))
|
|
|
|
|
val timestamp = formatter.format(new Date)
|
|
|
|
|
val content = versionLine(version) + "\ntimestamp=" + timestamp
|
|
|
|
|
val f = dir / "xsbt.version.properties"
|
|
|
|
|
if (!f.exists || f.lastModified < lastCompilationTime(analysis) || !containsVersion(f, version)) {
|
|
|
|
|
s.log.info("Writing version information to " + f + " :\n" + content)
|
|
|
|
|
IO.write(f, content)
|
|
|
|
|
}
|
|
|
|
|
f :: Nil
|
|
|
|
|
}
|
|
|
|
|
def versionLine(version: String): String = "version=" + version
|
|
|
|
|
def containsVersion(propFile: File, version: String): Boolean = IO.read(propFile).contains(versionLine(version))
|
|
|
|
|
|
|
|
|
|
def binID = "compiler-interface-bin"
|
|
|
|
|
def srcID = "compiler-interface-src"
|
|
|
|
|
|
|
|
|
|
def publishPomSettings: Seq[Setting[_]] = Seq(
|
|
|
|
|
pomPostProcess := cleanPom _
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def cleanPom(pomNode: scala.xml.Node) =
|
|
|
|
|
{
|
|
|
|
|
import scala.xml._
|
2014-12-06 00:37:31 +01:00
|
|
|
def cleanNodes(nodes: Seq[Node]): Seq[Node] = nodes flatMap {
|
2014-05-01 18:50:07 +02:00
|
|
|
case elem @ Elem(prefix, "dependency", attributes, scope, children @ _*) if excludePomDependency(elem) =>
|
|
|
|
|
NodeSeq.Empty
|
|
|
|
|
case Elem(prefix, "classifier", attributes, scope, children @ _*) =>
|
|
|
|
|
NodeSeq.Empty
|
|
|
|
|
case Elem(prefix, label, attributes, scope, children @ _*) =>
|
2015-07-10 11:53:48 +02:00
|
|
|
val cleanedNodes = cleanNodes(children)
|
|
|
|
|
Elem(prefix, label, attributes, scope, cleanedNodes.isEmpty, cleanedNodes: _*).theSeq
|
2014-05-01 18:50:07 +02:00
|
|
|
case other => other
|
2014-12-06 00:37:31 +01:00
|
|
|
}
|
2014-05-01 18:50:07 +02:00
|
|
|
cleanNodes(pomNode.theSeq)(0)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def excludePomDependency(node: scala.xml.Node) = node \ "artifactId" exists { n => excludePomArtifact(n.text) }
|
|
|
|
|
|
2016-05-08 22:18:23 +02:00
|
|
|
def excludePomArtifact(artifactId: String) = (artifactId startsWith "compiler-bridge")
|
2014-05-01 18:50:07 +02:00
|
|
|
|
|
|
|
|
val testExclusive = tags in test += ((ExclusiveTest, 1))
|
|
|
|
|
|
|
|
|
|
// TODO: replace with Tags.exclusive after 0.12.0
|
|
|
|
|
val testExclusiveRestriction = Tags.customLimit { (tags: Map[Tags.Tag, Int]) =>
|
|
|
|
|
val exclusive = tags.getOrElse(ExclusiveTest, 0)
|
|
|
|
|
val all = tags.getOrElse(Tags.All, 0)
|
|
|
|
|
exclusive == 0 || all == 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
def getScalaKeywords: Set[String] =
|
|
|
|
|
{
|
|
|
|
|
val g = new scala.tools.nsc.Global(new scala.tools.nsc.Settings)
|
|
|
|
|
g.nme.keywords.map(_.toString)
|
|
|
|
|
}
|
2017-03-29 15:43:38 +02:00
|
|
|
|
2014-05-01 18:50:07 +02:00
|
|
|
def writeScalaKeywords(base: File, keywords: Set[String]): File =
|
|
|
|
|
{
|
|
|
|
|
val init = keywords.map(tn => '"' + tn + '"').mkString("Set(", ", ", ")")
|
|
|
|
|
val ObjectName = "ScalaKeywords"
|
|
|
|
|
val PackageName = "sbt"
|
|
|
|
|
val keywordsSrc =
|
|
|
|
|
"""package %s
|
2012-07-13 19:41:00 +02:00
|
|
|
object %s {
|
|
|
|
|
val values = %s
|
2012-11-07 00:27:36 +01:00
|
|
|
}""".format(PackageName, ObjectName, init)
|
2014-05-01 18:50:07 +02:00
|
|
|
val out = base / PackageName.replace('.', '/') / (ObjectName + ".scala")
|
|
|
|
|
IO.write(out, keywordsSrc)
|
|
|
|
|
out
|
|
|
|
|
}
|
2017-03-29 15:43:38 +02:00
|
|
|
|
2014-05-01 18:50:07 +02:00
|
|
|
def keywordsSettings: Seq[Setting[_]] = inConfig(Compile)(Seq(
|
|
|
|
|
scalaKeywords := getScalaKeywords,
|
2017-03-29 15:43:38 +02:00
|
|
|
generateKeywords := writeScalaKeywords(sourceManaged.value, scalaKeywords.value),
|
|
|
|
|
sourceGenerators += Def.task(Seq(generateKeywords.value)).taskValue
|
2014-05-01 18:50:07 +02:00
|
|
|
))
|
2011-06-10 13:48:53 +02:00
|
|
|
}
|
2014-12-16 19:14:14 +01:00
|
|
|
|
2014-05-01 18:50:07 +02:00
|
|
|
object Licensed {
|
|
|
|
|
lazy val notice = SettingKey[File]("notice")
|
|
|
|
|
lazy val extractLicenses = TaskKey[Seq[File]]("extract-licenses")
|
|
|
|
|
|
|
|
|
|
lazy val seeRegex = """\(see (.*?)\)""".r
|
2014-10-10 21:42:26 +02:00
|
|
|
def licensePath(base: File, str: String): File = { val path = base / str; if (path.exists) path else sys.error("Referenced license '" + str + "' not found at " + path) }
|
2014-05-01 18:50:07 +02:00
|
|
|
def seePaths(base: File, noticeString: String): Seq[File] = seeRegex.findAllIn(noticeString).matchData.map(d => licensePath(base, d.group(1))).toList
|
|
|
|
|
|
|
|
|
|
def settings: Seq[Setting[_]] = Seq(
|
2017-03-29 15:43:38 +02:00
|
|
|
notice := (baseDirectory.value / "NOTICE"),
|
|
|
|
|
unmanagedResources in Compile ++= notice.value +: extractLicenses.value,
|
|
|
|
|
extractLicenses := extractLicenses0((baseDirectory in ThisBuild).value, notice.value, streams.value)
|
2014-05-01 18:50:07 +02:00
|
|
|
)
|
|
|
|
|
def extractLicenses0(base: File, note: File, s: TaskStreams): Seq[File] =
|
|
|
|
|
if (!note.exists) Nil else
|
|
|
|
|
try { seePaths(base, IO.read(note)) }
|
2016-07-07 00:56:31 +02:00
|
|
|
catch { case NonFatal(e) => s.log.warn("Could not read NOTICE"); Nil }
|
2012-04-05 05:05:13 +02:00
|
|
|
}
|