2016-07-06 23:56:31 +01:00
|
|
|
import scala.util.control.NonFatal
|
2025-01-02 11:16:32 +09:00
|
|
|
import sbt.*
|
2026-07-21 01:38:53 +09:00
|
|
|
import sbt.given
|
|
|
|
|
import sbt.util.CacheImplicits.given
|
2025-01-02 11:16:32 +09:00
|
|
|
import Keys.*
|
2024-10-11 16:57:28 +02:00
|
|
|
import scalafix.sbt.ScalafixPlugin.autoImport.scalafix
|
2026-08-24 03:38:07 -04:00
|
|
|
import PublishBinPlugin.autoImport.publishLocalBin
|
2017-05-03 15:52:36 +01:00
|
|
|
import sbt.internal.inc.Analysis
|
|
|
|
|
|
2024-10-09 09:36:37 +02:00
|
|
|
object Utils:
|
2026-08-25 02:02:37 -04:00
|
|
|
val JDK17 = config("jdk17")
|
|
|
|
|
|
2017-03-29 14:43:38 +01:00
|
|
|
val ExclusiveTest: Tags.Tag = Tags.Tag("exclusive-test")
|
|
|
|
|
|
|
|
|
|
val componentID: SettingKey[Option[String]] = settingKey[Option[String]]("")
|
2026-07-21 01:38:53 +09:00
|
|
|
@transient
|
2017-03-29 14:43:38 +01:00
|
|
|
val scalaKeywords: TaskKey[Set[String]] = taskKey[Set[String]]("")
|
2026-07-21 01:38:53 +09:00
|
|
|
@transient
|
2017-03-29 14:43:38 +01:00
|
|
|
val generateKeywords: TaskKey[File] = taskKey[File]("")
|
2026-04-27 01:03:42 -04:00
|
|
|
val sbtnVersion = SettingKey[String]("sbtn-version")
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2024-10-09 09:36:37 +02:00
|
|
|
lazy val noPublish = Seq(
|
|
|
|
|
publish := {},
|
|
|
|
|
publish / skip := true,
|
2026-08-24 03:38:07 -04:00
|
|
|
publishLocalBin / skip := true,
|
2024-10-09 09:36:37 +02:00
|
|
|
)
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2025-09-23 10:28:38 +09:00
|
|
|
lazy val javaOnlySettings: Seq[Setting[?]] = Seq(
|
2017-03-29 14:43:38 +01:00
|
|
|
// crossPaths := false,
|
2020-08-16 04:43:29 -04:00
|
|
|
// compileOrder := CompileOrder.JavaThenScala,
|
2021-05-02 23:25:23 -04:00
|
|
|
Compile / unmanagedSourceDirectories := Seq((Compile / javaSource).value)
|
2017-03-29 14:43:38 +01:00
|
|
|
)
|
|
|
|
|
|
2013-01-23 12:48:54 -05:00
|
|
|
lazy val baseScalacOptions = Seq(
|
2018-09-18 17:45:24 -04:00
|
|
|
Compile / doc / scalacOptions -= "-Xlint",
|
2025-12-05 16:22:07 +09:00
|
|
|
Compile / doc / scalacOptions -= "-Werror",
|
2013-01-23 12:48:54 -05:00
|
|
|
)
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2025-01-02 11:16:32 +09:00
|
|
|
def projectComponent: Setting[?] =
|
2017-03-29 14:43:38 +01:00
|
|
|
projectID := (componentID.value match
|
2026-04-29 21:41:54 +09:00
|
|
|
case Some(id) => projectID.value.extra("e:component" -> id)
|
2017-03-29 14:43:38 +01:00
|
|
|
case None => projectID.value)
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2017-05-03 15:52:36 +01:00
|
|
|
def lastCompilationTime(analysis: Analysis): Long =
|
2014-04-18 18:50:17 +02:00
|
|
|
val lastCompilation = analysis.compilations.allCompilations.lastOption
|
2017-06-13 00:10:21 -04:00
|
|
|
lastCompilation.map(_.getStartTime) getOrElse 0L
|
2019-11-30 14:18:41 -08:00
|
|
|
def generateVersionFile(
|
|
|
|
|
version: String,
|
|
|
|
|
dir: File,
|
|
|
|
|
s: TaskStreams,
|
|
|
|
|
analysis: Analysis
|
|
|
|
|
): Seq[File] =
|
2011-06-10 07:48:53 -04:00
|
|
|
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)
|
2012-07-01 15:16:41 -04:00
|
|
|
val content = versionLine(version) + "\ntimestamp=" + timestamp
|
2011-06-10 07:48:53 -04:00
|
|
|
val f = dir / "xsbt.version.properties"
|
2017-12-22 01:49:59 +01:00
|
|
|
// TODO: replace lastModified() with sbt.io.IO.getModifiedTimeOrZero(), once the build
|
2017-12-18 17:37:03 +01:00
|
|
|
// has been upgraded to a version of sbt that includes that call.
|
2022-01-30 15:07:23 -05:00
|
|
|
if !f.exists || f.lastModified < lastCompilationTime(analysis) || !containsVersion(f, version)
|
2026-09-10 13:52:19 -04:00
|
|
|
then
|
2011-06-26 12:27:07 -04:00
|
|
|
s.log.info("Writing version information to " + f + " :\n" + content)
|
|
|
|
|
IO.write(f, content)
|
2017-04-21 03:14:31 -04:00
|
|
|
f :: Nil
|
2012-07-01 15:16:41 -04:00
|
|
|
def versionLine(version: String): String = "version=" + version
|
|
|
|
|
def containsVersion(propFile: File, version: String): Boolean =
|
|
|
|
|
IO.read(propFile).contains(versionLine(version))
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2025-09-23 10:28:38 +09:00
|
|
|
def publishPomSettings: Seq[Setting[?]] = Seq(
|
2026-07-21 01:38:53 +09:00
|
|
|
pomPostProcess := cleanPom
|
2012-04-05 15:05:13 +12:00
|
|
|
)
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2012-04-05 15:05:13 +12:00
|
|
|
def cleanPom(pomNode: scala.xml.Node) =
|
2025-01-02 11:16:32 +09:00
|
|
|
import scala.xml.*
|
2014-12-05 15:37:31 -08:00
|
|
|
def cleanNodes(nodes: Seq[Node]): Seq[Node] = nodes flatMap {
|
2019-11-30 14:18:41 -08:00
|
|
|
case elem @ Elem(_, "dependency", _, _, _*) if excludePomDependency(elem) =>
|
2012-04-05 15:05:13 +12:00
|
|
|
NodeSeq.Empty
|
2019-11-28 18:05:49 +00:00
|
|
|
case Elem(_, "classifier", _, _, _*) =>
|
2012-04-05 15:05:13 +12:00
|
|
|
NodeSeq.Empty
|
2025-01-02 11:16:32 +09:00
|
|
|
case Elem(prefix, label, attributes, scope, children*) =>
|
2015-07-10 11:53:48 +02:00
|
|
|
val cleanedNodes = cleanNodes(children)
|
2025-01-02 11:16:32 +09:00
|
|
|
Elem(prefix, label, attributes, scope, cleanedNodes.isEmpty, cleanedNodes*).theSeq
|
2012-04-05 15:05:13 +12:00
|
|
|
case other => other
|
|
|
|
|
}
|
|
|
|
|
cleanNodes(pomNode.theSeq)(0)
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2012-04-05 15:05:13 +12:00
|
|
|
def excludePomDependency(node: scala.xml.Node) = node \ "artifactId" exists { n =>
|
|
|
|
|
excludePomArtifact(n.text)
|
|
|
|
|
}
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2026-04-29 21:41:54 +09:00
|
|
|
def excludePomArtifact(artifactId: String) = artifactId.startsWith("compiler-bridge")
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2021-05-02 23:25:23 -04:00
|
|
|
val testExclusive = test / tags += (ExclusiveTest, 1)
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2012-07-01 15:16:42 -04:00
|
|
|
// 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
|
|
|
|
|
}
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2012-07-13 13:41:00 -04:00
|
|
|
def getScalaKeywords: Set[String] =
|
2026-07-21 01:38:53 +09:00
|
|
|
dotty.tools.dotc.core.StdNames.nme.keywords.map(_.toString).toSet
|
2017-03-29 14:43:38 +01:00
|
|
|
|
2012-07-13 13:41:00 -04:00
|
|
|
def writeScalaKeywords(base: File, keywords: Set[String]): File =
|
2026-07-21 01:38:53 +09:00
|
|
|
val init = keywords.map(tn => "\"" + tn + "\"").mkString("Set(", ", ", ")")
|
2012-07-13 13:41:00 -04:00
|
|
|
val ObjectName = "ScalaKeywords"
|
2017-06-26 11:38:37 +01:00
|
|
|
val PackageName = "sbt.internal.util"
|
|
|
|
|
val keywordsSrc = s"""
|
|
|
|
|
|package $PackageName
|
|
|
|
|
|object $ObjectName {
|
|
|
|
|
| val values = $init
|
|
|
|
|
|}
|
|
|
|
|
""".trim.stripMargin
|
|
|
|
|
val out = base / PackageName.replace('.', '/') / s"$ObjectName.scala"
|
2012-07-13 13:41:00 -04:00
|
|
|
IO.write(out, keywordsSrc)
|
|
|
|
|
out
|
2017-03-29 14:43:38 +01:00
|
|
|
|
2025-09-23 10:28:38 +09:00
|
|
|
def keywordsSettings: Seq[Setting[?]] =
|
2012-07-13 13:41:00 -04:00
|
|
|
inConfig(Compile)(
|
|
|
|
|
Seq(
|
|
|
|
|
scalaKeywords := getScalaKeywords,
|
2026-07-21 01:38:53 +09:00
|
|
|
generateKeywords := Def.uncached(
|
|
|
|
|
writeScalaKeywords(sourceManaged.value, scalaKeywords.value)
|
|
|
|
|
),
|
2017-03-29 14:43:38 +01:00
|
|
|
sourceGenerators += Def.task(Seq(generateKeywords.value)).taskValue
|
2017-06-26 11:38:37 +01:00
|
|
|
)
|
|
|
|
|
)
|
2024-10-11 16:57:28 +02:00
|
|
|
|
|
|
|
|
def dataclassGen(data: Reference) = Def.taskDyn {
|
|
|
|
|
val root = (ThisBuild / baseDirectory).value.toURI.toString
|
|
|
|
|
val from = (data / Compile / sourceDirectory).value
|
|
|
|
|
val to = (Compile / sourceManaged).value
|
|
|
|
|
val outFrom = from.toURI.toString.stripSuffix("/").stripPrefix(root)
|
|
|
|
|
val outTo = to.toURI.toString.stripSuffix("/").stripPrefix(root)
|
|
|
|
|
Def.task {
|
|
|
|
|
val _ = (data / Compile / scalafix)
|
|
|
|
|
.toTask(s" --rules GenerateDataClass --out-from=$outFrom --out-to=$outTo")
|
|
|
|
|
.value
|
2026-01-13 05:19:40 +09:00
|
|
|
(to ** "*.scala").get()
|
2024-10-11 16:57:28 +02:00
|
|
|
}
|
|
|
|
|
}
|
2026-09-10 13:52:19 -04:00
|
|
|
end Utils
|
2014-12-16 13:14:14 -05:00
|
|
|
|
2011-06-10 07:48:53 -04:00
|
|
|
object Licensed:
|
2026-04-29 21:45:08 +09:00
|
|
|
lazy val notice = SettingKey[Option[File]]("notice")
|
2026-07-21 01:38:53 +09:00
|
|
|
@transient
|
2011-06-10 07:48:53 -04:00
|
|
|
lazy val extractLicenses = TaskKey[Seq[File]]("extract-licenses")
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2011-06-10 07:48:53 -04:00
|
|
|
lazy val seeRegex = """\(see (.*?)\)""".r
|
2014-10-10 15:42:26 -04:00
|
|
|
def licensePath(base: File, str: String): File =
|
|
|
|
|
val path = base / str;
|
|
|
|
|
if path.exists then path else sys.error("Referenced license '" + str + "' not found at " + path)
|
2011-06-10 07:48:53 -04:00
|
|
|
def seePaths(base: File, noticeString: String): Seq[File] =
|
|
|
|
|
seeRegex.findAllIn(noticeString).matchData.map(d => licensePath(base, d.group(1))).toList
|
2014-05-01 12:50:07 -04:00
|
|
|
|
2025-09-23 10:28:38 +09:00
|
|
|
def settings: Seq[Setting[?]] = Seq(
|
2026-04-29 21:45:08 +09:00
|
|
|
notice := Option(baseDirectory.value / "NOTICE").filter(_.isFile),
|
|
|
|
|
Compile / unmanagedResources ++= notice.value.toSeq ++ extractLicenses.value,
|
|
|
|
|
extractLicenses := notice.value
|
|
|
|
|
.map { n =>
|
|
|
|
|
extractLicenses0(
|
|
|
|
|
(ThisBuild / baseDirectory).value,
|
|
|
|
|
n,
|
|
|
|
|
streams.value
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
.getOrElse(Nil)
|
2011-06-10 07:48:53 -04:00
|
|
|
)
|
|
|
|
|
def extractLicenses0(base: File, note: File, s: TaskStreams): Seq[File] =
|
|
|
|
|
if !note.exists then Nil
|
|
|
|
|
else
|
2019-11-30 14:18:41 -08:00
|
|
|
try seePaths(base, IO.read(note))
|
2019-11-28 18:05:49 +00:00
|
|
|
catch case NonFatal(_) => s.log.warn("Could not read NOTICE"); Nil
|
2026-09-10 13:52:19 -04:00
|
|
|
end Licensed
|