Skip to content

Commit d7311e9

Browse files
authored
Update Scala Toolkit to 0.4.0 & dynamically adjust Scala Native defaults (#2955)
1 parent c9de1cf commit d7311e9

File tree

10 files changed

+188
-97
lines changed

10 files changed

+188
-97
lines changed

build.sc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,8 @@ trait Core extends ScalaCliCrossSbtModule
406406
| def scalaJsVersion = "${Scala.scalaJs}"
407407
| def scalaJsCliVersion = "${Scala.scalaJsCli}"
408408
| def scalajsEnvJsdomNodejsVersion = "${Deps.scalaJsEnvJsdomNodejs.dep.version}"
409-
| def scalaNativeVersion = "${Deps.nativeTools.dep.version}"
409+
| def scalaNativeVersion04 = "${Deps.Versions.scalaNative04}"
410+
| def scalaNativeVersion = "${Deps.Versions.scalaNative}"
410411
|
411412
| def testRunnerOrganization = "$testRunnerOrganization"
412413
| def testRunnerModuleName = "${`test-runner`(Scala.runnerScala3).artifactName()}"
@@ -444,6 +445,8 @@ trait Core extends ScalaCliCrossSbtModule
444445
| def toolkitTestName = "${Deps.toolkitTest.dep.module.name.value}"
445446
| def toolkitDefaultVersion = "${Deps.toolkitVersion}"
446447
| def toolkitMaxScalaNative = "${Deps.Versions.maxScalaNativeForToolkit}"
448+
| def toolkitVersionForNative04 = "${Deps.toolkitVersionForNative04}"
449+
| def toolkitVersionForNative05 = "${Deps.toolkitVersionForNative05}"
447450
|
448451
| def typelevelOrganization = "${Deps.typelevelToolkit.dep.module.organization.value}"
449452
| def typelevelToolkitDefaultVersion = "${Deps.typelevelToolkitVersion}"
@@ -982,7 +985,9 @@ trait CliIntegration extends SbtModule with ScalaCliPublishModule with HasTests
982985
| def maxAmmoniteScala3Version = "${Scala.maxAmmoniteScala3Version}"
983986
| def scalaJsVersion = "${Scala.scalaJs}"
984987
| def scalaJsCliVersion = "${Scala.scalaJsCli}"
985-
| def scalaNativeVersion = "${Deps.nativeTools.dep.version}"
988+
| def scalaNativeVersion = "${Deps.Versions.scalaNative}"
989+
| def scalaNativeVersion04 = "${Deps.Versions.scalaNative04}"
990+
| def scalaNativeVersion05 = "${Deps.Versions.scalaNative05}"
986991
| def ammoniteVersion = "${Deps.ammonite.dep.version}"
987992
| def defaultGraalVMJavaVersion = "${deps.graalVmJavaVersion}"
988993
| def defaultGraalVMVersion = "${deps.graalVmVersion}"
@@ -1004,6 +1009,8 @@ trait CliIntegration extends SbtModule with ScalaCliPublishModule with HasTests
10041009
| def dockerArchLinuxImage = "${TestDeps.archLinuxImage}"
10051010
|
10061011
| def toolkitVersion = "${Deps.toolkitVersion}"
1012+
| def toolkitVersionForNative04 = "${Deps.toolkitVersionForNative04}"
1013+
| def toolkitVersionForNative05 = "${Deps.toolkitVersionForNative05}"
10071014
| def toolkiMaxScalaNative = "${Deps.Versions.maxScalaNativeForToolkit}"
10081015
| def typelevelToolkitVersion = "${Deps.typelevelToolkitVersion}"
10091016
| def typelevelToolkitMaxScalaNative = "${Deps.Versions.maxScalaNativeForTypelevelToolkit}"

modules/cli/src/main/scala/scala/cli/commands/shared/SharedOptions.scala

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import caseapp.core.help.Help
66
import com.github.plokhotnyuk.jsoniter_scala.core.*
77
import com.github.plokhotnyuk.jsoniter_scala.macros.*
88
import coursier.cache.FileCache
9+
import coursier.core.Version
910
import coursier.util.{Artifact, Task}
1011
import dependency.AnyDependency
1112
import dependency.parser.DependencyParser
@@ -29,6 +30,7 @@ import scala.build.internal.{Constants, FetchExternalBinary, OsLibc, Util}
2930
import scala.build.options.ScalaVersionUtil.fileWithTtl0
3031
import scala.build.options.{BuildOptions, ComputeVersion, Platform, ScalacOpt, ShadowingSeq}
3132
import scala.build.preprocessing.directives.ClasspathUtils.*
33+
import scala.build.preprocessing.directives.Toolkit.maxScalaNativeWarningMsg
3234
import scala.build.preprocessing.directives.{Python, Toolkit}
3335
import scala.build.options as bo
3436
import scala.cli.ScalaCli
@@ -759,24 +761,40 @@ object SharedOptions {
759761
)
760762
)
761763

762-
val (dependencies, toolkitDefaults) =
764+
val (dependencies, toolkitDefinitions) =
763765
toolkitVersion.toList.map(Positioned.commandLine)
764766
.flatMap(Toolkit.resolveDependenciesWithRequirements(_).map((wbr, td) => wbr.value -> td))
765767
.unzip
766768
val maxScalaNativeVersions =
767-
toolkitDefaults.flatMap {
768-
case Toolkit.ToolkitDefaults(isScalaToolkitDefault, isTypelevelToolkitDefault) =>
769+
toolkitDefinitions.flatMap {
770+
case Toolkit.ToolkitDefinitions(
771+
isScalaToolkitDefault,
772+
explicitScalaToolkitVersion,
773+
isTypelevelToolkitDefault,
774+
_
775+
) =>
769776
val st = if (isScalaToolkitDefault)
770777
Seq(Constants.toolkitMaxScalaNative -> Toolkit.maxScalaNativeWarningMsg(
771-
"Scala Toolkit",
772-
Constants.toolkitMaxScalaNative
778+
toolkitName = "Scala Toolkit",
779+
toolkitVersion = Constants.toolkitDefaultVersion,
780+
maxNative = Constants.toolkitMaxScalaNative
773781
))
774-
else Nil
782+
else explicitScalaToolkitVersion.toList
783+
.map(Version(_))
784+
.filter(_ <= Version(Constants.toolkitVersionForNative04))
785+
.flatMap(v =>
786+
List(Constants.scalaNativeVersion04 -> maxScalaNativeWarningMsg(
787+
toolkitName = "Scala Toolkit",
788+
toolkitVersion = v.toString(),
789+
Constants.scalaNativeVersion04
790+
))
791+
)
775792
val tlt =
776793
if (isTypelevelToolkitDefault)
777794
Seq(Constants.typelevelToolkitMaxScalaNative -> Toolkit.maxScalaNativeWarningMsg(
778-
"TypeLevel Toolkit",
779-
Constants.typelevelToolkitMaxScalaNative
795+
toolkitName = "TypeLevel Toolkit",
796+
toolkitVersion = Constants.typelevelToolkitDefaultVersion,
797+
maxNative = Constants.typelevelToolkitMaxScalaNative
780798
))
781799
else Nil
782800
st ++ tlt

modules/directives/src/main/scala/scala/build/preprocessing/directives/Toolkit.scala

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package scala.build.preprocessing.directives
22

3+
import coursier.core.Version
34
import dependency.*
45

56
import scala.build.Positioned
@@ -8,7 +9,7 @@ import scala.build.errors.BuildException
89
import scala.build.internal.Constants
910
import scala.build.options.BuildRequirements.ScopeRequirement
1011
import scala.build.options.WithBuildRequirements.*
11-
import scala.build.options._
12+
import scala.build.options.*
1213
import scala.cli.commands.SpecificationLevel
1314

1415
@DirectiveGroupName("Toolkit")
@@ -37,8 +38,12 @@ object Toolkit {
3738
val typelevel = "typelevel"
3839
val scala = "scala"
3940

40-
def maxScalaNativeWarningMsg(toolkitName: String, maxNative: String): String =
41-
s"$toolkitName does not support Scala Native ${Constants.scalaNativeVersion}, $maxNative should be used instead."
41+
def maxScalaNativeWarningMsg(
42+
toolkitName: String,
43+
toolkitVersion: String,
44+
maxNative: String
45+
): String =
46+
s"$toolkitName $toolkitVersion does not support Scala Native ${Constants.scalaNativeVersion}, $maxNative should be used instead."
4247

4348
object TypelevelToolkit {
4449
def unapply(s: Option[String]): Boolean =
@@ -50,9 +55,11 @@ object Toolkit {
5055
s.isEmpty || s.contains(Constants.toolkitOrganization) || s.contains(scala)
5156
}
5257

53-
case class ToolkitDefaults(
58+
case class ToolkitDefinitions(
5459
isScalaToolkitDefault: Boolean = false,
55-
isTypelevelToolkitDefault: Boolean = false
60+
scalaToolkitExplicitVersion: Option[String] = None,
61+
isTypelevelToolkitDefault: Boolean = false,
62+
typelevelToolkitExplicitVersion: Option[String] = None
5663
)
5764

5865
/** @param toolkitCoords
@@ -62,7 +69,7 @@ object Toolkit {
6269
*/
6370
def resolveDependenciesWithRequirements(toolkitCoords: Positioned[String]): List[(
6471
WithBuildRequirements[Positioned[DependencyLike[NameAttributes, NameAttributes]]],
65-
ToolkitDefaults
72+
ToolkitDefinitions
6673
)] =
6774
toolkitCoords match
6875
case Positioned(positions, coords) =>
@@ -71,21 +78,36 @@ object Toolkit {
7178
def isDefault = rawVersion == "default"
7279
val notDefaultVersion = if rawVersion == "latest" then "latest.release" else rawVersion
7380
val flavor = tokens.dropRight(1).headOption
74-
val (org, v, trv: ToolkitDefaults) = flavor match {
75-
case TypelevelToolkit() => (
76-
Constants.typelevelOrganization,
81+
val (org, v, trv: ToolkitDefinitions) = flavor match {
82+
case TypelevelToolkit() =>
83+
val typelevelToolkitVersion =
7784
if isDefault then Constants.typelevelToolkitDefaultVersion
78-
else notDefaultVersion,
79-
ToolkitDefaults(isTypelevelToolkitDefault = isDefault)
85+
else notDefaultVersion
86+
val explicitVersion =
87+
if isDefault then None else Some(typelevelToolkitVersion)
88+
(
89+
Constants.typelevelOrganization,
90+
typelevelToolkitVersion,
91+
ToolkitDefinitions(
92+
isTypelevelToolkitDefault = isDefault,
93+
typelevelToolkitExplicitVersion = explicitVersion
94+
)
8095
)
8196
case ScalaToolkit() | None =>
97+
val scalaToolkitVersion =
98+
if isDefault then Constants.toolkitDefaultVersion
99+
else notDefaultVersion
100+
val explicitVersion =
101+
if isDefault then None else Some(scalaToolkitVersion)
82102
(
83103
Constants.toolkitOrganization,
84-
if isDefault then Constants.toolkitDefaultVersion
85-
else notDefaultVersion,
86-
ToolkitDefaults(isScalaToolkitDefault = isDefault)
104+
scalaToolkitVersion,
105+
ToolkitDefinitions(
106+
isScalaToolkitDefault = isDefault,
107+
scalaToolkitExplicitVersion = explicitVersion
108+
)
87109
)
88-
case Some(org) => (org, notDefaultVersion, ToolkitDefaults())
110+
case Some(org) => (org, notDefaultVersion, ToolkitDefinitions())
89111
}
90112
List(
91113
Positioned(positions, dep"$org::${Constants.toolkitName}::$v,toolkit")
@@ -122,20 +144,37 @@ object Toolkit {
122144
.map {
123145
case (
124146
WithBuildRequirements(requirements, positionedDep),
125-
ToolkitDefaults(isScalaToolkitDefault, isTypelevelToolkitDefault)
147+
ToolkitDefinitions(
148+
isScalaToolkitDefault,
149+
explicitScalaToolkitVersion,
150+
isTypelevelToolkitDefault,
151+
_
152+
)
126153
) =>
127154
val scalaToolkitMaxNativeVersions =
128155
if isScalaToolkitDefault then
129156
List(Constants.toolkitMaxScalaNative -> maxScalaNativeWarningMsg(
130-
"Scala Toolkit",
131-
Constants.toolkitMaxScalaNative
157+
toolkitName = "Scala Toolkit",
158+
toolkitVersion = Constants.toolkitDefaultVersion,
159+
maxNative = Constants.toolkitMaxScalaNative
132160
))
133-
else Nil
161+
else
162+
explicitScalaToolkitVersion.toList
163+
.map(Version(_))
164+
.filter(_ <= Version(Constants.toolkitVersionForNative04))
165+
.flatMap(v =>
166+
List(Constants.scalaNativeVersion04 -> maxScalaNativeWarningMsg(
167+
toolkitName = "Scala Toolkit",
168+
toolkitVersion = v.toString(),
169+
Constants.scalaNativeVersion04
170+
))
171+
)
134172
val typelevelToolkitMaxNativeVersions =
135173
if isTypelevelToolkitDefault then
136174
List(Constants.typelevelToolkitMaxScalaNative -> maxScalaNativeWarningMsg(
137-
"TypeLevel Toolkit",
138-
Constants.typelevelToolkitMaxScalaNative
175+
toolkitName = "TypeLevel Toolkit",
176+
toolkitVersion = Constants.typelevelToolkitDefaultVersion,
177+
maxNative = Constants.typelevelToolkitMaxScalaNative
139178
))
140179
else Nil
141180
val maxNativeVersions =

modules/integration/src/test/scala/scala/cli/integration/RunScalaNativeTestDefinitions.scala

Lines changed: 65 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -300,55 +300,80 @@ trait RunScalaNativeTestDefinitions { _: RunTestDefinitions =>
300300
for {
301301
useDirectives <- Seq(true, false)
302302
titleStr = if (useDirectives) "with directives" else "with command line args"
303+
explicitNativeVersion <-
304+
Seq(Some(Constants.scalaNativeVersion04), Some(Constants.scalaNativeVersion05), None)
305+
actualNativeVersion = explicitNativeVersion.getOrElse(Constants.scalaNativeVersion)
306+
nativeVersionStr = explicitNativeVersion.map(v => s"explicit: $v").getOrElse("default")
307+
nativeVersionOpts = explicitNativeVersion.toSeq.flatMap(v => Seq("--native-version", v))
308+
nativeVersionDirectiveStr =
309+
explicitNativeVersion
310+
.map(v => s"""//> using nativeVersion $v
311+
|""".stripMargin)
312+
.getOrElse("")
313+
scalaToolkitVersion =
314+
if (explicitNativeVersion.contains(Constants.scalaNativeVersion04))
315+
Constants.toolkitVersionForNative04
316+
else "default"
317+
typelevelToolkitVersion = "default"
303318
} {
304-
test(s"native & typelevel toolkit defaults $titleStr") {
305-
val expectedMessage = "Hello"
306-
val cmdLineOpts =
307-
if (useDirectives) Nil
308-
else Seq("--toolkit", "typelevel:default", "--native")
309-
val directivesStr =
310-
if (useDirectives)
311-
"""//> using toolkit typelevel:default
312-
|//> using platform native
313-
|""".stripMargin
314-
else ""
315-
TestInputs(
316-
os.rel / "toolkit.scala" ->
317-
s"""$directivesStr
318-
|import cats.effect._
319-
|
320-
|object Hello extends IOApp.Simple {
321-
| def run = IO.println("$expectedMessage")
322-
|}
323-
|""".stripMargin
324-
).fromRoot { root =>
325-
val result = os.proc(TestUtil.cli, "run", "toolkit.scala", cmdLineOpts, extraOptions)
326-
.call(cwd = root, stderr = os.Pipe)
327-
expect(result.out.trim() == expectedMessage)
328-
if (Constants.scalaNativeVersion != Constants.typelevelToolkitMaxScalaNative) {
329-
val err = result.err.trim()
330-
expect(
331-
err.contains(
332-
s"Scala Native default version ${Constants.scalaNativeVersion} is not supported in this build"
319+
// for the time being, typelevel toolkit does nto support Scala Native 0.5.x
320+
if (!explicitNativeVersion.contains(Constants.scalaNativeVersion05))
321+
test(
322+
s"native ($nativeVersionStr) & typelevel toolkit ($typelevelToolkitVersion) $titleStr"
323+
) {
324+
val expectedMessage = "Hello"
325+
val cmdLineOpts =
326+
if (useDirectives) Nil
327+
else Seq(
328+
"--toolkit",
329+
s"typelevel:$typelevelToolkitVersion",
330+
"--native"
331+
) ++ nativeVersionOpts
332+
val directivesStr =
333+
if (useDirectives)
334+
s"""//> using toolkit typelevel:$typelevelToolkitVersion
335+
|//> using platform native
336+
|$nativeVersionDirectiveStr
337+
|""".stripMargin
338+
else ""
339+
TestInputs(
340+
os.rel / "toolkit.scala" ->
341+
s"""$directivesStr
342+
|import cats.effect._
343+
|
344+
|object Hello extends IOApp.Simple {
345+
| def run = IO.println("$expectedMessage")
346+
|}
347+
|""".stripMargin
348+
).fromRoot { root =>
349+
val result = os.proc(TestUtil.cli, "run", "toolkit.scala", cmdLineOpts, extraOptions)
350+
.call(cwd = root, stderr = os.Pipe)
351+
expect(result.out.trim() == expectedMessage)
352+
if (actualNativeVersion != Constants.typelevelToolkitMaxScalaNative) {
353+
val err = result.err.trim()
354+
expect(
355+
err.contains(
356+
s"Scala Native default version ${Constants.scalaNativeVersion} is not supported in this build"
357+
)
333358
)
334-
)
335-
expect(err.contains(s"Using ${Constants.typelevelToolkitMaxScalaNative} instead."))
336-
expect(err.contains(
337-
s"TypeLevel Toolkit does not support Scala Native ${Constants.scalaNativeVersion}"
338-
))
359+
expect(err.contains(s"Using ${Constants.typelevelToolkitMaxScalaNative} instead."))
360+
expect(err.contains(
361+
s"TypeLevel Toolkit ${Constants.typelevelToolkitVersion} does not support Scala Native ${Constants.scalaNativeVersion}"
362+
))
363+
}
339364
}
340365
}
341-
}
342366

343-
test(s"native & scala toolkit defaults $titleStr") {
367+
test(s"native ($nativeVersionStr) & scala toolkit ($scalaToolkitVersion) $titleStr") {
344368
val cmdLineOpts =
345369
if (useDirectives) Nil
346-
else Seq("--toolkit", "default", "--native")
370+
else Seq("--toolkit", scalaToolkitVersion, "--native") ++ nativeVersionOpts
347371
val directivesStr =
348372
if (useDirectives)
349-
"""//> using toolkit default
350-
|//> using platform native
351-
|""".stripMargin
373+
s"""//> using toolkit $scalaToolkitVersion
374+
|//> using platform native
375+
|$nativeVersionDirectiveStr
376+
|""".stripMargin
352377
else ""
353378
TestInputs(
354379
os.rel / "toolkit.scala" ->

0 commit comments

Comments
 (0)