Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cross build to sbt 2.x #208

Merged
merged 2 commits into from
Nov 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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