Skip to content

Commit

Permalink
Merge pull request #208 from sbt/wip/cross
Browse files Browse the repository at this point in the history
Cross build to sbt 2.x
  • Loading branch information
eed3si9n authored Nov 3, 2024
2 parents d7aac72 + 2bb2281 commit a57f12b
Show file tree
Hide file tree
Showing 51 changed files with 372 additions and 222 deletions.
18 changes: 11 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,28 @@ jobs:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
java: 11
distribution: temurin
- os: macos-latest
java: 8
distribution: zulu
jobtype: 1
- os: ubuntu-latest
java: 8
distribution: temurin
distribution: zulu
jobtype: 1
runs-on: ${{ matrix.os }}
env:
JAVA_OPTS: -Xms800M -Xmx1G -Xss2M -XX:ReservedCodeCacheSize=128M -Dfile.encoding=UTF-8
JVM_OPTS: -Xms800M -Xmx1G -Xss2M -XX:ReservedCodeCacheSize=128M -Dfile.encoding=UTF-8
JAVA_OPTS: -Xms800M -Xmx2G -Xss2M -XX:ReservedCodeCacheSize=128M -Dfile.encoding=UTF-8
JVM_OPTS: -Xms800M -Xmx2G -Xss2M -XX:ReservedCodeCacheSize=128M -Dfile.encoding=UTF-8
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: "${{ matrix.distribution }}"
java-version: "${{ matrix.java }}"
cache: "sbt"
- uses: sbt/setup-sbt@v1
- shell: bash
run: sbt -v clean test scripted
run: |
sbt -v clean compile || true
sleep 1
sbt -v test scripted
2 changes: 1 addition & 1 deletion README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Customize `buildInfoKeys` by adding whatever keys you want to have in `BuildInfo
```scala
buildInfoKeys ++= Seq[BuildInfoKey](
resolvers,
libraryDependencies in Test,
Test / libraryDependencies,
BuildInfoKey.map(name) { case (k, v) => "project" + k.capitalize -> v.capitalize },
"custom" -> 1234, // computed at project load time
BuildInfoKey.action("buildTime") {
Expand Down
23 changes: 19 additions & 4 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,23 +1,38 @@
ThisBuild / organization := "com.eed3si9n"
import Dependencies.*

ThisBuild / organization := "com.eed3si9n"
ThisBuild / version := {
val orig = (ThisBuild / version).value
if (orig.endsWith("-SNAPSHOT")) "0.11.0-SNAPSHOT"
else orig
}
val scala3 = "3.3.4"
ThisBuild / scalaVersion := scala3

lazy val root = (project in file("."))
.enablePlugins(SbtPlugin)
.settings(
name := "sbt-buildinfo",
scalacOptions := Seq("-Xlint", "-Xfatal-warnings", "-unchecked", "-deprecation", "-feature", "-language:implicitConversions"),
scalacOptions := {
scalaBinaryVersion.value match {
case "2.12" => Seq("-Xsource:3", "-Xfatal-warnings", "-unchecked", "-deprecation", "-feature", "-language:implicitConversions")
case _ => Seq("-Vdebug")
}
},
scalacOptions += "-language:experimental.macros",
libraryDependencies += "org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided,
libraryDependencies ++= {
scalaBinaryVersion.value match {
case "2.12" => "org.scala-lang" % "scala-reflect" % scalaVersion.value % Provided :: Nil
case _ => "org.scala-lang" % "scala-reflect" % "2.13.12" % Provided :: manifesto :: Nil
}
},
scriptedLaunchOpts ++= Seq("-Xmx1024M", "-Xss4M", "-Dplugin.version=" + version.value),
scriptedBufferLog := false,
crossSbtVersions := List(scala3, "2.12.20"),
(pluginCrossBuild / sbtVersion) := {
scalaBinaryVersion.value match {
case "2.12" => "1.2.8"
case "2.12" => "1.5.8"
case _ => "2.0.0-M2"
}
}
)
Expand Down
5 changes: 5 additions & 0 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import sbt.*

object Dependencies {
val manifesto = "com.eed3si9n.manifesto" %% "manifesto" % "0.1.1"
}
2 changes: 1 addition & 1 deletion project/build.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sbt.version=1.9.9
sbt.version=1.10.2
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ final class BuildInfoKeyMacros(val c: blackbox.Context) {

def taskImpl(key: Tree): Tree = {
val A = key.tpe.typeArgs.head
q"$BuildInfoKey.sbtbuildinfoTaskValueEntry[$A]($key.taskValue)($key.key.manifest.typeArguments.head.asInstanceOf[_root_.scala.reflect.Manifest[$A]])"
q"""$BuildInfoKey.sbtbuildinfoTaskValueEntry[$A]($key.taskValue)($key.key.manifest.typeArguments.head.asInstanceOf[_root_.scala.reflect.Manifest[$A]])"""
}
}
51 changes: 51 additions & 0 deletions src/main/scala-2.12/sbtbuildinfo/PluginCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package sbtbuildinfo

import java.nio.file.{ Path => NioPath }
import sbt.*
import scala.language.higherKinds
import scala.annotation.nowarn

object PluginCompat {
type FileRef = java.io.File
type Out = java.io.File
type Entry[A1] = sbtbuildinfo.BuildInfoKey.Entry[A1]
type Manifest[A1] = scala.reflect.Manifest[A1]
val Manifest = scala.reflect.Manifest

val Setting = BuildInfoKey.Setting
val Task = BuildInfoKey.Task
val TaskValue = BuildInfoKey.TaskValue
val Constant = BuildInfoKey.Constant
val Mapped = BuildInfoKey.Mapped
val Action = BuildInfoKey.Action

object TypeExpression {
def unapply(m: Manifest[?]): Option[(String, List[Manifest[?]])] =
Some(({
val s = m.toString()
if (s.contains("[")) s.split("""\[""").head
else s
}, m.typeArguments))
}

trait BuildInfoKeys0
object BuildInfoKeys0 extends BuildInfoKeys0

def toClasspath(cp: Vector[NioPath]): Seq[Attributed[File]] =
cp.map((x) => Attributed.blank(x.toFile()))

implicit class RichScope(scope: Scope) {
@nowarn
def rescope(ref: Reference): Scope = scope.in(ref)
}
implicit class RichRichTaskable4[A1, A2, A3, A4](
val taskable: Scoped.RichTaskable4[A1, A2, A3, A4]) {
def flatMapN[R](f: (A1, A2, A3, A4) => Task[R]) =
taskable.flatMap(f)
}
implicit class RichRichTaskable11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11](
val taskable: Scoped.RichTaskable11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11]) {
def flatMapN[R](f: (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) => Task[R]) =
taskable.flatMap(f)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,16 @@ package object sbtbuildinfo {
private[sbtbuildinfo] final case class Constant[A](tuple: (String, A))(implicit val manifest: Manifest[A])
extends Entry[A]

private[sbtbuildinfo] final case class Mapped[A, B](from: Entry[A], fun: ((String, A)) => (String, B))
(implicit val manifest: Manifest[B])
extends Entry[B]
private[sbtbuildinfo] final case class Mapped[A1, A2](from: Entry[A1], fun: ((String, A1)) => (String, A2))
(implicit val manifest: Manifest[A2])
extends Entry[A2]

private[sbtbuildinfo] final case class Action[A](name: String, fun: () => A)(implicit val manifest: Manifest[A])
extends Entry[A]

sealed trait Entry[A] {
private[sbtbuildinfo] def manifest: Manifest[A]
sealed trait Entry[A1] {
type A = A1
private[sbtbuildinfo] def manifest: Manifest[A1]
}
}
}
27 changes: 27 additions & 0 deletions src/main/scala-3/sbtbuildinfo/BuildInfoKey.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package sbtbuildinfo

import sbt.*
import scala.reflect.ClassTag
import scala.quoted.*

object BuildInfoKey:
import Entry.*

def apply[A1: PluginCompat.Manifest](key: SettingKey[A1]): Entry[A1] =
Entry.Setting(key)

def apply[A1: PluginCompat.Manifest](key: TaskKey[A1]): Entry[A1] =
Entry.Task(key)

def apply[A1: PluginCompat.Manifest](tuple: (String, A1)): Entry[A1] =
Entry.Constant(tuple)

def map[A1, A2: PluginCompat.Manifest](from: Entry[A1])(fun: ((String, A1)) => (String, A2)): Entry[A2] =
Entry.Mapped(from, fun)

def action[A1: PluginCompat.Manifest](name: String)(fun: => A1): Entry[A1] =
Entry.Action(name, () => fun)

def outOfGraphUnsafe[A1: PluginCompat.Manifest](key: TaskKey[A1]): Entry[A1] =
Entry.Task(key)
end BuildInfoKey
16 changes: 16 additions & 0 deletions src/main/scala-3/sbtbuildinfo/Entry.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package sbtbuildinfo

import sbt.*
import PluginCompat.Manifest

enum Entry[A1: Manifest]:
type A = A1
def manifest: Manifest[A1] = Manifest[A1]

case Setting[A1: Manifest](scoped: SettingKey[A1]) extends Entry[A1]
case Task[A1: Manifest](scoped: TaskKey[A1]) extends Entry[A1]
case TaskValue[A1: Manifest](task: sbt.Task[A1]) extends Entry[A1]
case Constant[A1: Manifest](tuple: (String, A1)) extends Entry[A1]
case Mapped[A1, A2: Manifest](from: Entry[A1], fun: ((String, A1)) => (String, A2)) extends Entry[A2]
case Action[A1: Manifest](name: String, fun: () => A1) extends Entry[A1]
end Entry
43 changes: 43 additions & 0 deletions src/main/scala-3/sbtbuildinfo/PluginCompat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package sbtbuildinfo

import com.eed3si9n.manifesto.Manifesto
import java.nio.file.{ Path => NioPath }
import sbt.*
import scala.annotation.nowarn
import xsbti.{ FileConverter, HashedVirtualFileRef, VirtualFile }

object PluginCompat:
type FileRef = HashedVirtualFileRef
type Out = VirtualFile
type Entry[A1] = sbtbuildinfo.Entry[A1]
type Manifest[A1] = Manifesto[A1]
val Manifest = Manifesto

val Setting = Entry.Setting
val Task = Entry.Task
val TaskValue = Entry.TaskValue
val Constant = Entry.Constant
val Action = Entry.Action
val Mapped = Entry.Mapped

def toClasspath(cp: Vector[NioPath])(using conv: FileConverter): Seq[Attributed[HashedVirtualFileRef]] =
cp.map((x) => Attributed.blank(conv.toVirtualFile(x)))

trait BuildInfoKeys0:
@nowarn inline given [A1]: Conversion[SettingKey[A1], Entry[A1]] = BuildInfoKey(_)
@nowarn inline given [A1]: Conversion[TaskKey[A1], Entry[A1]] = BuildInfoKey(_)
@nowarn inline given [A1]: Conversion[sbt.Task[A1], Entry[A1]] = Entry.TaskValue[A1](_)
@nowarn inline given [A1]: Conversion[(String, A1), Entry[A1]] = BuildInfoKey(_)
end BuildInfoKeys0

object TypeExpression:
def unapply(m: Manifest[?]): (String, List[Manifest[?]]) =
(m.typeCon, m.typeArguments)
end TypeExpression

object BuildInfoKeys0 extends BuildInfoKeys0

inline def RichRichTaskable4[A1, A2, A3, A4](tuple: (A1, A2, A3, A4)) = tuple
inline def RichRichTaskable11[A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11](tuple: (A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11)) =
tuple
end PluginCompat
30 changes: 19 additions & 11 deletions src/main/scala/sbtbuildinfo/BuildInfo.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package sbtbuildinfo

import sbt._, Keys._
import PluginCompat.BuildInfoKeys0.{ given, * }
import PluginCompat.*
import scala.language.implicitConversions

case class BuildInfoResult(identifier: String, value: Any, typeExpr: TypeExpression)
case class BuildInfoResult(identifier: String, value: Any, manifest: Manifest[?])

object BuildInfo {
type BuildInfoKey = Entry[?]

def apply(dir: File, renderer: BuildInfoRenderer, obj: String,
keys: Seq[BuildInfoKey], options: Seq[BuildInfoOption],
proj: ProjectRef, state: State, cacheDir: File): Task[File] =
Expand All @@ -28,25 +33,28 @@ object BuildInfo {
val distinctKeys = (keys ++ extraKeys(options)).toList.distinct
val extracted = Project.extract(state)

def entry[A](info: BuildInfoKey.Entry[A]): Option[Task[BuildInfoResult]] = {
val typeExpr = TypeExpression.parse(info.manifest.toString())._1
def entry[A](info: PluginCompat.Entry[A]): Option[Task[BuildInfoResult]] = {
// val typeExpr = TypeExpression.parse(info.manifest.toString())._1

val result = info match {
case BuildInfoKey.Setting(key) => extracted getOpt (key in scope(key, project)) map (v => task(ident(key) -> v))
case BuildInfoKey.Task(key) => Some(task(ident(key) -> extracted.runTask(key in scope(key, project), state)._2))
case BuildInfoKey.TaskValue(task) => Some(task.map(x => ident(task) -> x))
case BuildInfoKey.Constant(tuple) => Some(task(tuple))
case BuildInfoKey.Action(name, fun) => Some(task(name -> fun.apply))
case BuildInfoKey.Mapped(from, fun) => entry(from) map (_ map (r => fun((r.identifier, r.value.asInstanceOf[A]))))
case PluginCompat.Setting(key) => extracted.getOpt(project / key).map((v) => task(ident(key) -> v))
case PluginCompat.Task(key) => Some(task(ident(key) -> extracted.runTask(project / key, state)._2))
case PluginCompat.TaskValue(task) => Some(task.map(x => ident(task) -> x))
case PluginCompat.Constant(tuple) => Some(task(tuple))
case PluginCompat.Action(name, fun) => Some(task(name -> fun.apply))
case m@PluginCompat.Mapped(from, fun) => entry(from).map { (t) => t.map((r) => fun((r.identifier, r.value.asInstanceOf[from.A]))) }
}
result map (_ map { case (identifier, value) => BuildInfoResult(identifier, value, typeExpr) })
result.map(_.map {
case (identifier, value) => BuildInfoResult(identifier, value, info.manifest)
})
}

distinctKeys.flatMap(entry(_)).join
}

private def scope(scoped: Scoped, project: ProjectReference) = {
val scope0 = scoped.scope
if (scope0.project == This) scope0 in project
if (scope0.project == This) scope0.rescope(project)
else scope0
}

Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/sbtbuildinfo/BuildInfoKeys.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ trait BuildInfoKeys {
lazy val buildInfoObject = settingKey[String]("The name for the generated object.")
lazy val buildInfoPackage = settingKey[String]("The name for the generated package.")
lazy val buildInfoUsePackageAsPath = settingKey[Boolean]("If true, the generated object is placed in the folder of the package instead of \"sbt-buildinfo\".")
lazy val buildInfoKeys = settingKey[Seq[BuildInfoKey.Entry[_]]]("Entries for build info.")
lazy val buildInfoKeys = settingKey[Seq[PluginCompat.Entry[_]]]("Entries for build info.")
lazy val buildInfoBuildNumber = taskKey[Int]("The build number.")
lazy val buildInfoOptions = settingKey[Seq[BuildInfoOption]]("Options for generating the build info.")
}
Expand Down
Loading

0 comments on commit a57f12b

Please sign in to comment.