diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6d0dd805fa..e3757becee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -66,8 +66,12 @@ jobs: sbt \ "jsBridge06/publishLocal; \ jsBridge1/publishLocal; \ - jsBridge06/test; \ - jsBridge1/test" + nativeBridge04/publishLocal; \ + nativeBridge05/publishLocal" + sbt jsBridge1/test + sbt jsBridge06/test + sbt nativeBridge05/test + sbt nativeBridge04/test shell: bash launcher: diff --git a/bridges/scala-native-0.4/src/main/scala/bloop/scalanative/NativeBridge.scala b/bridges/scala-native-0.4/src/main/scala/bloop/scalanative/NativeBridge.scala index 2e3b4bb9be..3f29b296fe 100644 --- a/bridges/scala-native-0.4/src/main/scala/bloop/scalanative/NativeBridge.scala +++ b/bridges/scala-native-0.4/src/main/scala/bloop/scalanative/NativeBridge.scala @@ -37,6 +37,7 @@ object NativeBridge { } val nativeLTO = config.mode match { case LinkerMode.Debug => build.LTO.none + case LinkerMode.Release if bloop.util.CrossPlatform.isMac => build.LTO.full case LinkerMode.Release => build.LTO.thin } diff --git a/bridges/scala-native-0.4/src/test/scala/bloop/scalanative/ScalaNativeToolchainSpec.scala b/bridges/scala-native-0.4/src/test/scala/bloop/scalanative/ScalaNativeToolchainSpec.scala index 5d61cc8038..3733523393 100644 --- a/bridges/scala-native-0.4/src/test/scala/bloop/scalanative/ScalaNativeToolchainSpec.scala +++ b/bridges/scala-native-0.4/src/test/scala/bloop/scalanative/ScalaNativeToolchainSpec.scala @@ -53,7 +53,8 @@ class ScalaNativeToolchainSpec { val resultingState = TestUtil.blockingExecute(action, state, maxDuration * 3) assertTrue(s"Linking failed: ${logger.getMessages.mkString("\n")}", resultingState.status.isOk) - logger.getMessages.assertContain("Optimizing (release-full mode)", atLevel = "info") + // nothing is printed for fast release + logger.getMessages.assertContain("Generated native binary", atLevel = "info") } @Test def canRunScalaNativeProjectDefaultMainClass(): Unit = { diff --git a/bridges/scala-native-0.5/src/main/scala/bloop/scalanative/NativeBridge.scala b/bridges/scala-native-0.5/src/main/scala/bloop/scalanative/NativeBridge.scala new file mode 100644 index 0000000000..04627c5ecc --- /dev/null +++ b/bridges/scala-native-0.5/src/main/scala/bloop/scalanative/NativeBridge.scala @@ -0,0 +1,102 @@ +package bloop.scalanative +import java.nio.file.Files +import java.nio.file.Path + +import scala.scalanative.build +import scala.scalanative.util.Scope +import scala.concurrent.Future +import scala.concurrent.ExecutionContext + +import bloop.config.Config.LinkerMode +import bloop.config.Config.NativeConfig +import bloop.data.Project +import bloop.io.Paths +import bloop.logging.DebugFilter +import bloop.logging.Logger + +object NativeBridge { + private implicit val ctx: DebugFilter = DebugFilter.Link + private val sharedScope = Scope.unsafe() + + def nativeLink( + config0: NativeConfig, + project: Project, + classpath: Array[Path], + entry: String, + target: Path, + logger: Logger, + ec: ExecutionContext + ): Future[Path] = { + val workdir = project.out.resolve("native") + if (workdir.isDirectory) Paths.delete(workdir) + Files.createDirectories(workdir.underlying) + + val nativeLogger = + build.Logger(logger.trace _, logger.debug _, logger.info _, logger.warn _, logger.error _) + val config = setUpNativeConfig(project, classpath, config0) + val nativeMode = config.mode match { + case LinkerMode.Debug => build.Mode.debug + case LinkerMode.Release => build.Mode.releaseFast + } + val nativeLTO = config.mode match { + case LinkerMode.Debug => build.LTO.none + case LinkerMode.Release if bloop.util.CrossPlatform.isMac => build.LTO.none + case LinkerMode.Release => build.LTO.thin + } + + val nativeConfig = + build.Config.empty + .withMainClass(Option(entry)) + .withClassPath(classpath) + .withBaseDir(target.getParent()) + .withLogger(nativeLogger) + .withCompilerConfig( + build.NativeConfig.empty + .withClang(config.clang) + .withClangPP(config.clangpp) + .withBaseName(target.getFileName().toString()) + .withCompileOptions(config.options.compiler) + .withLinkingOptions(config.options.linker) + .withGC(build.GC(config.gc)) + .withMode(nativeMode) + .withLTO(nativeLTO) + .withLinkStubs(config.linkStubs) + .withCheck(config.check) + .withDump(config.dump) + .withTargetTriple(config.targetTriple) + ) + + build.Build.build(nativeConfig)(sharedScope, ec) + } + + private[scalanative] def setUpNativeConfig( + project: Project, + classpath: Array[Path], + config: NativeConfig + ): NativeConfig = { + val mode = config.mode + val options = config.options + val gc = if (config.gc.isEmpty) build.GC.default.name else config.gc + val clang = if (config.clang.toString.isEmpty) build.Discover.clang() else config.clang + val clangpp = if (config.clangpp.toString.isEmpty) build.Discover.clangpp() else config.clangpp + val lopts = if (options.linker.isEmpty) build.Discover.linkingOptions() else options.linker + val copts = if (options.compiler.isEmpty) build.Discover.compileOptions() else options.compiler + + val targetTriple = config.targetTriple + + NativeConfig.apply( + version = config.version, + mode = mode, + toolchain = Nil, // No worries, toolchain is on this project's classpath + gc = gc, + targetTriple = targetTriple, + clang = clang, + clangpp = clangpp, + options = options, + linkStubs = config.linkStubs, + check = config.check, + dump = config.dump, + output = config.output + ) + } +} diff --git a/bridges/scala-native-0.5/src/test/scala/bloop/scalanative/ScalaNativeToolchainSpec.scala b/bridges/scala-native-0.5/src/test/scala/bloop/scalanative/ScalaNativeToolchainSpec.scala new file mode 100644 index 0000000000..11bd91719b --- /dev/null +++ b/bridges/scala-native-0.5/src/test/scala/bloop/scalanative/ScalaNativeToolchainSpec.scala @@ -0,0 +1,105 @@ +package bloop.scalanative + +import java.util.concurrent.TimeUnit + +import scala.concurrent.duration.Duration + +import bloop.cli.Commands +import bloop.cli.OptimizerConfig +import bloop.data.Platform +import bloop.data.Project +import bloop.engine.Run +import bloop.engine.tasks.toolchains.ScalaNativeToolchain +import bloop.logging.RecordingLogger +import bloop.util.TestUtil + +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.experimental.categories.Category +import bloop.engine.State +import bloop.config.Config + +@Category(Array(classOf[bloop.FastTests])) +class ScalaNativeToolchainSpec { + private val state0 = { + def setUpNative(p: Project): Project = { + val platform = p.platform match { + case nativePlatform: Platform.Native => + nativePlatform.copy( + toolchain = Some(ScalaNativeToolchain.apply(this.getClass.getClassLoader)) + ) + + case _ => p.platform + } + p.copy(platform = platform) + } + + val configDir = TestUtil.getBloopConfigDir("cross-test-build-scala-native-0.5") + val logger = bloop.logging.BloopLogger.default(configDir.toString()) + TestUtil.loadTestProject(configDir, logger, true, _.map(setUpNative)) + } + @Test def canLinkScalaNativeProject(): Unit = { + val logger = new RecordingLogger + val state = state0.copy(logger = logger) + val action = Run(Commands.Link(List("test-projectNative"))) + val resultingState = TestUtil.blockingExecute(action, state, maxDuration) + + assertTrue(s"Linking failed: ${logger.getMessages.mkString("\n")}", resultingState.status.isOk) + logger.getMessages.assertContain("Generated native binary '", atLevel = "info") + } + + @Test def canLinkScalaNativeProjectInReleaseMode(): Unit = { + val logger = new RecordingLogger + val mode = OptimizerConfig.Release + val state = state0.copy(logger = logger) + val action = Run(Commands.Link(List("test-projectNative"), optimize = Some(mode))) + val resultingState = TestUtil.blockingExecute(action, state, maxDuration * 3) + + assertTrue( + s"Linking failed: ${logger.getMessages.mkString("\n")}", + resultingState.status.isOk + ) + logger.getMessages.assertContain("Optimizing (release-fast mode)", atLevel = "info") + } + + @Test def canRunScalaNativeProjectDefaultMainClass(): Unit = { + val logger = new RecordingLogger + val state = state0.copy(logger = logger) + val action = Run(Commands.Run(List("test-projectNative"))) + val resultingState = TestUtil.blockingExecute(action, state, maxDuration) + + assertTrue( + s"Linking failed: ${logger.getMessages.mkString("\n")}", + resultingState.status.isOk + ) + logger.getMessages.assertContain("Hello, world from DefaultApp!", atLevel = "info") + } + + @Test def canRunScalaJvmProjectDefaultMainClass(): Unit = { + val logger = new RecordingLogger + val state = state0.copy(logger = logger) + val action = Run(Commands.Run(List("test-project"), main = None)) + val resultingState = TestUtil.blockingExecute(action, state, maxDuration) + + assertTrue( + s"Linking failed: ${logger.getMessages.mkString("\n")}", + resultingState.status.isOk + ) + logger.getMessages.assertContain("Hello, world!", atLevel = "info") + } + + private val maxDuration = Duration.apply(90, TimeUnit.SECONDS) + private implicit class RichLogs(logs: List[(String, String)]) { + def assertContain(needle: String, atLevel: String): Unit = { + def failMessage = s"""Logs did not contain `$needle` at level `$atLevel`. Logs were: + |${logs.mkString("\n")}""".stripMargin + assertTrue( + failMessage, + logs.exists { + case (`atLevel`, msg) => msg.contains(needle) + case _ => false + } + ) + } + } +} diff --git a/build.sbt b/build.sbt index f48126a65b..8cb2dfd056 100644 --- a/build.sbt +++ b/build.sbt @@ -141,6 +141,7 @@ lazy val frontend: Project = project "zincVersion" -> Dependencies.zincVersion, "bspVersion" -> Dependencies.bspVersion, "nativeBridge04" -> (nativeBridge04Name + "_" + Keys.scalaBinaryVersion.value), + "nativeBridge05" -> (nativeBridge05Name + "_" + Keys.scalaBinaryVersion.value), "jsBridge06" -> (jsBridge06Name + "_" + Keys.scalaBinaryVersion.value), "jsBridge1" -> (jsBridge1Name + "_" + Keys.scalaBinaryVersion.value) ), @@ -417,6 +418,19 @@ lazy val nativeBridge04 = project (Test / fork) := true ) +val nativeBridge05Name = "bloop-native-bridge-0-5" +lazy val nativeBridge05 = project + .dependsOn(frontend % Provided, frontend % "test->test") + .in(file("bridges") / "scala-native-0.5") + .disablePlugins(ScalafixPlugin, ScriptedPlugin) + .settings( + name := nativeBridge05Name, + testSettings, + libraryDependencies += Dependencies.scalaNativeTools05, + (Test / javaOptions) ++= jvmOptions, + (Test / fork) := true + ) + val allProjects = Seq( backend, benchmarks, @@ -432,6 +446,7 @@ val allProjects = Seq( launcher213, launcherTest, nativeBridge04, + nativeBridge05, sbtBloop, sockets ) diff --git a/frontend/src/main/scala/bloop/engine/tasks/toolchains/ScalaNativeToolchain.scala b/frontend/src/main/scala/bloop/engine/tasks/toolchains/ScalaNativeToolchain.scala index aa5faeb6e2..1b51af487c 100644 --- a/frontend/src/main/scala/bloop/engine/tasks/toolchains/ScalaNativeToolchain.scala +++ b/frontend/src/main/scala/bloop/engine/tasks/toolchains/ScalaNativeToolchain.scala @@ -9,10 +9,12 @@ import bloop.DependencyResolution import bloop.config.Config import bloop.config.Config.NativeConfig import bloop.data.Project +import bloop.engine.ExecutionContext import bloop.internal.build.BuildInfo import bloop.io.AbsolutePath import bloop.logging.Logger import bloop.task.Task +import scala.concurrent.Future final class ScalaNativeToolchain private (classLoader: ClassLoader) { @@ -35,7 +37,10 @@ final class ScalaNativeToolchain private (classLoader: ClassLoader) { logger: Logger ): Task[Try[Unit]] = { val bridgeClazz = classLoader.loadClass("bloop.scalanative.NativeBridge") - val nativeLinkMeth = bridgeClazz.getMethod("nativeLink", paramTypes: _*) + val isNative05 = config.version.startsWith("0.5") + val nativeLinkMeth = + if (isNative05) bridgeClazz.getMethod("nativeLink", paramTypes05: _*) + else bridgeClazz.getMethod("nativeLink", paramTypes04: _*) // Scala Native 0.4.{0,1,2} expect to receive the companion object class' name val fullEntry = config.version match { @@ -44,15 +49,32 @@ final class ScalaNativeToolchain private (classLoader: ClassLoader) { case _ => mainClass.stripSuffix("$") } - val linkage = Task { - nativeLinkMeth - .invoke(null, config, project, fullClasspath, fullEntry, target.underlying, logger) - .asInstanceOf[Unit] - }.materialize - + val linkage = if (isNative05) { + Task.fromFuture { + nativeLinkMeth + .invoke( + null, + config, + project, + fullClasspath, + fullEntry, + target.underlying, + logger, + ExecutionContext.ioScheduler + ) + .asInstanceOf[Future[Unit]] + }.materialize + } else { + Task { + nativeLinkMeth + .invoke(null, config, project, fullClasspath, fullEntry, target.underlying, logger) + .asInstanceOf[Unit] + }.materialize + } linkage.map { case s @ scala.util.Success(_) => s case f @ scala.util.Failure(t) => + t.printStackTrace() t match { case it: InvocationTargetException => scala.util.Failure(it.getCause) case _ => f @@ -60,9 +82,12 @@ final class ScalaNativeToolchain private (classLoader: ClassLoader) { } } - // format: OFF - private val paramTypes = classOf[NativeConfig] :: classOf[Project] :: classOf[Array[Path]] :: classOf[String] :: classOf[Path] :: classOf[Logger] :: Nil - // format: ON + private val paramTypes04 = classOf[NativeConfig] :: classOf[Project] :: + classOf[Array[Path]] :: classOf[String] :: classOf[Path] :: classOf[Logger] :: Nil + + private val paramTypes05 = classOf[NativeConfig] :: classOf[Project] :: + classOf[Array[Path]] :: classOf[String] :: classOf[Path] :: classOf[Logger] :: + classOf[scala.concurrent.ExecutionContext] :: Nil } object ScalaNativeToolchain extends ToolchainCompanion[ScalaNativeToolchain] { @@ -73,7 +98,8 @@ object ScalaNativeToolchain extends ToolchainCompanion[ScalaNativeToolchain] { override def artifactNameFrom(version: String): String = { if (version.length == 3) sys.error("The full Scala Native version must be provided") else if (version.startsWith("0.4")) BuildInfo.nativeBridge04 - else sys.error(s"Expected compatible Scala Native version [0.3, 0.4], $version given") + else if (version.startsWith("0.5")) BuildInfo.nativeBridge05 + else sys.error(s"Expected compatible Scala Native version [0.4, 0.5], $version given") } override def getPlatformData(platform: Platform): Option[PlatformData] = { diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.4/build.sbt b/frontend/src/test/resources/cross-test-build-scala-native-0.4/build.sbt index d6e44edf90..491b1868f7 100644 --- a/frontend/src/test/resources/cross-test-build-scala-native-0.4/build.sbt +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.4/build.sbt @@ -6,7 +6,7 @@ lazy val `test-project` = .withoutSuffixFor(JVMPlatform) .settings( name := "test-project", - scalaVersion := "2.13.4", + scalaVersion := "2.13.13", mainClass in (Compile, run) := Some("hello.App") ) diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.4/project/plugins.sbt b/frontend/src/test/resources/cross-test-build-scala-native-0.4/project/plugins.sbt index c3d5191808..f674586ddd 100644 --- a/frontend/src/test/resources/cross-test-build-scala-native-0.4/project/plugins.sbt +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.4/project/plugins.sbt @@ -1,5 +1,5 @@ addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.0.0") -addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.3") +addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.17") val pluginVersion = sys.props.getOrElse( "bloopVersion", diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/build.sbt b/frontend/src/test/resources/cross-test-build-scala-native-0.5/build.sbt new file mode 100644 index 0000000000..491b1868f7 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/build.sbt @@ -0,0 +1,20 @@ +bloopExportJarClassifiers in Global := Some(Set("sources")) +bloopConfigDir in Global := baseDirectory.value / "bloop-config" + +lazy val `test-project` = + crossProject(NativePlatform, JVMPlatform) + .withoutSuffixFor(JVMPlatform) + .settings( + name := "test-project", + scalaVersion := "2.13.13", + mainClass in (Compile, run) := Some("hello.App") + ) + +lazy val `test-project-native` = `test-project`.native.settings( + // Should override default set above. Tested as part of ScalaNativeToolchainSpec. + (Compile / run / bloopMainClass) := Some("hello.DefaultApp") +) + +lazy val `test-project-jvm` = `test-project`.jvm.settings( + (Compile / run / bloopMainClass) := Some("hello.App") +) diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/project/build.properties b/frontend/src/test/resources/cross-test-build-scala-native-0.5/project/build.properties new file mode 100644 index 0000000000..b089b60c7a --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/project/build.properties @@ -0,0 +1,2 @@ +sbt.version=1.9.9 + diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/project/plugins.sbt b/frontend/src/test/resources/cross-test-build-scala-native-0.5/project/plugins.sbt new file mode 100644 index 0000000000..0b8b43fe95 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/project/plugins.sbt @@ -0,0 +1,11 @@ +addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.0.0") +addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.0-RC1") + +val pluginVersion = sys.props.getOrElse( + "bloopVersion", + throw new RuntimeException("Unable to find -DbloopVersion") +) + +addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % pluginVersion) + +updateOptions := updateOptions.value.withLatestSnapshots(false) diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/native/src/main/scala/hello/DefaultApp.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/native/src/main/scala/hello/DefaultApp.scala new file mode 100644 index 0000000000..f29441fdf8 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/native/src/main/scala/hello/DefaultApp.scala @@ -0,0 +1,10 @@ +package hello + +import scalanative.unsafe._ +import scalanative.libc.stdio + +object DefaultApp { + def main(args: Array[String]): Unit = Zone { implicit z => + stdio.vprintf(c"Hello, world from DefaultApp!\n", toCVarArgList()) + } +} diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/main/scala/hello/App.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/main/scala/hello/App.scala new file mode 100644 index 0000000000..344dc7e549 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/main/scala/hello/App.scala @@ -0,0 +1,7 @@ +package hello + +object App { + def main(args: Array[String]): Unit = { + println(Hello.greet("world")) + } +} diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/main/scala/hello/Environment.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/main/scala/hello/Environment.scala new file mode 100644 index 0000000000..9d92c70ec3 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/main/scala/hello/Environment.scala @@ -0,0 +1,7 @@ +package hello + +object Environment { + def requireEnvironmentVariable(): Unit = { + sys.env.get("BLOOP_OWNER").getOrElse(sys.error("Missing BLOOP_OWNER env variable!")) + } +} diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/main/scala/hello/Hello.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/main/scala/hello/Hello.scala new file mode 100644 index 0000000000..45671be900 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/main/scala/hello/Hello.scala @@ -0,0 +1,9 @@ +package hello + +object Hello { + def greet(name: String): String = { + // We do this to check that environment variables work + Environment.requireEnvironmentVariable() + s"Hello, $name!" + } +} diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/EternalUTest.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/EternalUTest.scala new file mode 100644 index 0000000000..e60441b7fc --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/EternalUTest.scala @@ -0,0 +1,11 @@ +package hello + +import utest._ + +object EternalUTest extends TestSuite { + val tests = Tests { + "This test never ends" - { + while (true) () + } + } +} diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/JUnitTest.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/JUnitTest.scala new file mode 100644 index 0000000000..6c3325dae9 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/JUnitTest.scala @@ -0,0 +1,11 @@ +package hello + +import org.junit.Test +import org.junit.Assert.assertEquals + +class JUnitTest { + @Test + def myTest: Unit = { + assertEquals(4, 2 + 2) + } +} diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/ScalaCheckTest.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/ScalaCheckTest.scala new file mode 100644 index 0000000000..0a52e66501 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/ScalaCheckTest.scala @@ -0,0 +1,11 @@ +package hello + +import org.scalacheck.Properties +import org.scalacheck.Prop.forAll + +object ScalaCheckTest extends Properties("Greeting") { + + property("is personal") = forAll { (name: String) => + Hello.greet(name) == s"Hello, $name!" + } +} diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/ScalaTestTest.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/ScalaTestTest.scala new file mode 100644 index 0000000000..c9b6a92ea1 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/ScalaTestTest.scala @@ -0,0 +1,9 @@ +package hello + +import org.scalatest._ + +class ScalaTestTest extends FlatSpec with Matchers { + "A greeting" should "be very personal" in { + Hello.greet("Martin") shouldBe "Hello, Martin!" + } +} diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/Specs2Test.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/Specs2Test.scala new file mode 100644 index 0000000000..373220d148 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/Specs2Test.scala @@ -0,0 +1,17 @@ +package hello + +import org.specs2._ + +class Specs2Test extends Specification { + def is = s2""" + + This is a specification to check the `Hello` object. + + A greeting + is very personal $isPersonal + """ + + def isPersonal = { + Hello.greet("Martin") must beEqualTo("Hello, Martin!") + } +} diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/UTestTest.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/UTestTest.scala new file mode 100644 index 0000000000..6022e8847b --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/UTestTest.scala @@ -0,0 +1,15 @@ +package hello + +import utest._ + +object UTestTest extends TestSuite { + import utest.framework.Formatter + override def utestFormatter: Formatter = new Formatter { + override def formatColor = false + } + val tests = Tests { + "Greetings are very personal" - { + assert(Hello.greet("Martin") == "Hello, Martin!") + } + } +} diff --git a/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/WritingTest.scala b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/WritingTest.scala new file mode 100644 index 0000000000..4868ea6968 --- /dev/null +++ b/frontend/src/test/resources/cross-test-build-scala-native-0.5/test-project/shared/src/test/scala/hello/WritingTest.scala @@ -0,0 +1,9 @@ +package hello + +import org.scalatest._ + +class WritingTest extends FlatSpec with Matchers { + "A test" should "be able to print stuff" in { + (1 to 10).foreach(_ => println("message")) + } +} diff --git a/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala b/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala index 9f7924aeeb..80a2a0ba2d 100644 --- a/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala +++ b/integrations/sbt-bloop/src/main/scala/bloop/integrations/sbt/SbtBloop.scala @@ -731,10 +731,6 @@ object BloopDefaults { // FORMAT: OFF if (pluginLabels.contains(ScalaNativePluginLabel)) { - if (isWindows) { - // Default on jvm config because native is not supported in Windows yet - Def.task(Config.Platform.default) - } else { Def.task { // Add targetTriple to the config when the scala native plugin supports it val emptyNative = Config.NativeConfig.empty @@ -756,7 +752,6 @@ object BloopDefaults { val nativeConfig = Config.NativeConfig(nativeVersion, nativeMode, nativeGc, None, clang, clangpp, Nil, options, nativeLinkStubs, false, false, None) Config.Platform.Native(nativeConfig, mainClass) } - } } else if (pluginLabels.contains(ScalaJsPluginLabel)) { Def.task { val scalaJsVersion = libraryDeps diff --git a/project/Dependencies.scala b/project/Dependencies.scala index de9048ab42..0ca51038aa 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -33,6 +33,7 @@ object Dependencies { val jsoniterVersion = "2.13.3.2" val shapelessVersion = "2.3.4" val scalaNative04Version = "0.4.17" + val scalaNative05Version = "0.5.0-RC1" val scalaJs06Version = "0.6.33" val scalaJs1Version = "1.15.0" val scalaJsEnvsVersion = "1.1.1" @@ -84,6 +85,7 @@ object Dependencies { val scalaDebugAdapter = "ch.epfl.scala" %% "scala-debug-adapter" % debugAdapterVersion val scalaNativeTools04 = "org.scala-native" %% "tools" % scalaNative04Version % Provided + val scalaNativeTools05 = "org.scala-native" %% "tools" % scalaNative05Version % Provided val scalaJsTools06 = "org.scala-js" %% "scalajs-tools" % scalaJs06Version % Provided val scalaJsSbtTestAdapter06 = "org.scala-js" %% "scalajs-sbt-test-adapter" % scalaJs06Version % Provided