Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: Add support for Scala Native 0.5.0
- Loading branch information
Showing
25 changed files
with
421 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
102 changes: 102 additions & 0 deletions
102
bridges/scala-native-0.5/src/main/scala/bloop/scalanative/NativeBridge.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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.full | ||
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 | ||
) | ||
} | ||
} |
105 changes: 105 additions & 0 deletions
105
bridges/scala-native-0.5/src/test/scala/bloop/scalanative/ScalaNativeToolchainSpec.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
} | ||
) | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
frontend/src/test/resources/cross-test-build-scala-native-0.4/project/plugins.sbt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.