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

Add the ability to emit wasm to scala js cli #99

Merged
merged 7 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from 6 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
12 changes: 12 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ jobs:
- uses: VirtusLab/scala-cli-setup@9bc68588ab2d49dae03e5395a5f411e20914f97e
with:
jvm: "temurin:17"
- uses: actions/setup-node@v4
with:
node-version: '22'
- name: Test CLI
run: ./mill -i 'tests.test'

Expand Down Expand Up @@ -60,6 +63,9 @@ jobs:
- uses: coursier/[email protected]
with:
jvm: temurin:17
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: |
./mill -i "native.writeNativeImageScript" generate.sh "" && \
./generate.sh && \
Expand Down Expand Up @@ -98,6 +104,9 @@ jobs:
- uses: coursier/[email protected]
with:
jvm: temurin:17
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: |
./mill -i "native-static.writeNativeImageScript" generate.sh "" && \
./generate.sh && \
Expand Down Expand Up @@ -128,6 +137,9 @@ jobs:
- uses: coursier/[email protected]
with:
jvm: temurin:17
- uses: actions/setup-node@v4
with:
node-version: '22'
- run: |
./mill -i "native-mostly-static.writeNativeImageScript" generate.sh "" && \
./generate.sh && \
Expand Down
29 changes: 27 additions & 2 deletions cli/src/org/scalajs/cli/Scalajsld.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,8 @@ object Scalajsld {
jsHeader: String = "",
logLevel: Level = Level.Info,
importMap: Option[File] = None,
longRunning: Boolean = false
longRunning: Boolean = false,
emitWasm: Boolean = false
)

private def moduleInitializer(
Expand Down Expand Up @@ -238,6 +239,9 @@ object Scalajsld {
opt[Unit]("longRunning")
.action { (_, c) => c.copy(longRunning = true) }
.text("Run linking incrementally every time a line is printed to stdin")
opt[Unit]("emitWasm")
.action { (_, c) => c.copy(emitWasm = true) }
.text("If present, use the _experimental_ web assembly backend in the linker")
opt[Unit]('d', "debug")
.action { (_, c) => c.copy(logLevel = Level.Debug) }
.text("Debug mode: Show full log")
Expand Down Expand Up @@ -277,13 +281,32 @@ object Scalajsld {
}
}
}
val allValidations = Seq(outputCheck, importMapCheck)

val wasEsModule = c.emitWasm match {
case true =>
if (c.moduleKind != ModuleKind.ESModule) {
failure("Wasm can only be emitted with module kind EsModule")
} else success
case false => success
}

val wasmFewestModules = c.emitWasm match {
case true => {
if (c.moduleSplitStyle != ModuleSplitStyle.FewestModules.toString) {
failure("Wasm can only be emitted with module split style FewestModules")
Quafadas marked this conversation as resolved.
Show resolved Hide resolved
} else success
}
case false => success
}

val allValidations = Seq(outputCheck, importMapCheck, wasEsModule, wasmFewestModules)
allValidations.forall(_.isRight) match {
case true => success
case false => failure(allValidations.filter(_.isLeft).map(_.left.get).mkString("\n\n"))
}
}


override def showUsageOnError = Some(true)
}

Expand Down Expand Up @@ -319,6 +342,7 @@ object Scalajsld {
.withBatchMode(true)
.withJSHeader(options.jsHeader)
.withMinify(options.fullOpt)
.withExperimentalUseWebAssembly(options.emitWasm)

val linker = StandardImpl.linker(config)
val logger = new ScalaConsoleLogger(options.logLevel)
Expand Down Expand Up @@ -347,6 +371,7 @@ object Scalajsld {
logger
)
case (None, Some(outputDir)) =>

linker.link(
irImportMappedFiles,
moduleInitializers,
Expand Down
60 changes: 60 additions & 0 deletions tests/test/src/org/scalajs/cli/tests/Tests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -498,4 +498,64 @@ class Tests extends munit.FunSuite {
val rawJs = os.read.lines(dir / "out" / "main.js")
assert(rawJs(1).contains(substTo))
}


test("wasm flag emits wasm") {
val dir = os.temp.dir()
os.write(
dir / "foo.scala",
"""object Foo {
| def main(args: Array[String]): Unit = {
| println("Hello")
| }
|
|}
|""".stripMargin
)

val scalaJsLibraryCp = getScalaJsLibraryCp(dir)

os.makeDir.all(dir / "bin")
os.proc(
"cs",
"launch",
"scalac:2.13.15",
"--",
"-classpath",
scalaJsLibraryCp,
s"-Xplugin:${getScalaJsCompilerPlugin(dir)}",
"-d",
"bin",
"foo.scala"
).call(cwd = dir, stdin = os.Inherit, stdout = os.Inherit)

os.makeDir.all(dir / "out")
val res = os
.proc(
launcher,
"--stdlib",
scalaJsLibraryCp,
"-s",
"--emitWasm",
"--moduleKind",
"ESModule",
"--moduleSplitStyle",
"FewestModules",
"--outputDir",
"out",
"-mm",
"Foo.main",
"bin"
)
.call(cwd = dir, mergeErrIntoOut = true)

os.walk(dir).foreach(println)
val testSize = os.size(dir / "out" / "main.wasm")
val testMapSize = os.size(dir / "out" / "main.wasm.map")
assert(testSize > 0)
assert(testMapSize > 0)

os.proc("node", "--experimental-wasm-exnref", "main.js").call(cwd = dir / "out", check = true, stdin = os.Inherit, stdout = os.Inherit, stderr = os.Inherit)

}
}
Loading