From aab6047dc43a917e8cf4dd24c4a2f7eecb718688 Mon Sep 17 00:00:00 2001 From: Alexandre Archambault Date: Tue, 22 Mar 2022 16:11:12 +0100 Subject: [PATCH] Allow to run native or JVM versions of Scala.JS linker --- .../main/scala/scala/cli/commands/Fmt.scala | 3 +- .../scala/scala/cli/commands/FmtOptions.scala | 3 +- .../scala/scala/cli/commands/Metabrowse.scala | 3 +- .../cli/commands/MetabrowseOptions.scala | 2 +- .../scala/scala/cli/commands/Package.scala | 10 +- .../scala/cli/commands/ScalaJsOptions.scala | 37 +++- .../scala/cli/commands/SharedOptions.scala | 5 +- .../scala/cli/internal/ScalaJsLinker.scala | 193 +++++++++++------- .../build}/internal/FetchExternalBinary.scala | 30 ++- .../main/scala/scala/build/Artifacts.scala | 2 +- .../build/internal/ScalaJsLinkerConfig.scala | 41 +++- .../scala/build/options/BuildOptions.scala | 4 +- .../build/options/PostBuildOptions.scala | 5 +- .../scalajs/ScalaJsLinkerOptions.scala | 31 +++ website/docs/reference/cli-options.md | 16 ++ 15 files changed, 284 insertions(+), 101 deletions(-) rename modules/{cli/src/main/scala/scala/cli => core/src/main/scala/scala/build}/internal/FetchExternalBinary.scala (70%) create mode 100644 modules/options/src/main/scala/scala/build/options/scalajs/ScalaJsLinkerOptions.scala diff --git a/modules/cli/src/main/scala/scala/cli/commands/Fmt.scala b/modules/cli/src/main/scala/scala/cli/commands/Fmt.scala index 94ae6eb60c..9fd14d98a9 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/Fmt.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/Fmt.scala @@ -2,10 +2,9 @@ package scala.cli.commands import caseapp._ -import scala.build.internal.{CustomCodeWrapper, Runner} +import scala.build.internal.{CustomCodeWrapper, FetchExternalBinary, Runner} import scala.build.{CrossSources, Inputs, Logger, Sources} import scala.cli.CurrentParams -import scala.cli.internal.FetchExternalBinary import scala.util.control.NonFatal object Fmt extends ScalaCommand[FmtOptions] { diff --git a/modules/cli/src/main/scala/scala/cli/commands/FmtOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/FmtOptions.scala index 1363384dce..141cad6364 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/FmtOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/FmtOptions.scala @@ -2,9 +2,8 @@ package scala.cli.commands import caseapp._ -import scala.build.internal.Constants +import scala.build.internal.{Constants, FetchExternalBinary} import scala.build.options.BuildOptions -import scala.cli.internal.FetchExternalBinary import scala.util.Properties // format: off diff --git a/modules/cli/src/main/scala/scala/cli/commands/Metabrowse.scala b/modules/cli/src/main/scala/scala/cli/commands/Metabrowse.scala index cd6b7708fd..60e332859a 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/Metabrowse.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/Metabrowse.scala @@ -5,10 +5,9 @@ import caseapp._ import java.io.File import java.nio.file.Path -import scala.build.internal.Runner +import scala.build.internal.{FetchExternalBinary, Runner} import scala.build.{Build, BuildThreads, Logger} import scala.cli.CurrentParams -import scala.cli.internal.FetchExternalBinary object Metabrowse extends ScalaCommand[MetabrowseOptions] { override def hidden = true diff --git a/modules/cli/src/main/scala/scala/cli/commands/MetabrowseOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/MetabrowseOptions.scala index 8806146cc2..e053cc7d1b 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/MetabrowseOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/MetabrowseOptions.scala @@ -2,8 +2,8 @@ package scala.cli.commands import caseapp._ +import scala.build.internal.FetchExternalBinary import scala.build.options.BuildOptions -import scala.cli.internal.FetchExternalBinary import scala.util.Properties // format: off diff --git a/modules/cli/src/main/scala/scala/cli/commands/Package.scala b/modules/cli/src/main/scala/scala/cli/commands/Package.scala index 40e84b86a6..442f465638 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/Package.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/Package.scala @@ -709,9 +709,8 @@ object Package extends ScalaCommand[PackageOptions] { either { value { ScalaJsLinker.link( - build.options.javaHome().value.javaCommand, - build.options.javaOptions.javaOpts.toSeq.map(_.value.value), - build.artifacts.scalaJsCli, + build.options.notForBloopOptions.scalaJsLinkerOptions, + build.options.javaHome().value.javaCommand, // FIXME Allow users to use another JVM here? classPath, mainClassOpt.orNull, addTestInitializer, @@ -719,7 +718,10 @@ object Package extends ScalaCommand[PackageOptions] { linkingDir, fullOpt, noOpt, - logger + logger, + build.options.finalCache, + build.options.archiveCache, + build.options.scalaJsOptions.finalVersion ) } val relMainJs = os.rel / "main.js" diff --git a/modules/cli/src/main/scala/scala/cli/commands/ScalaJsOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/ScalaJsOptions.scala index 9b91ded483..03b7a49fd5 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/ScalaJsOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/ScalaJsOptions.scala @@ -4,6 +4,7 @@ import caseapp._ import com.github.plokhotnyuk.jsoniter_scala.core._ import com.github.plokhotnyuk.jsoniter_scala.macros._ +import scala.build.internal.FetchExternalBinary import scala.build.{Os, options} // format: off @@ -52,11 +53,31 @@ final case class ScalaJsOptions( jsModuleSplitStyle: Option[String] = None, @Group("Scala.JS") @HelpMessage("The Scala JS ECMA Script version: es5_1, es2015, es2016, es2017, es2018, es2019, es2020, es2021") - jsEsVersion: Option[String] = None + jsEsVersion: Option[String] = None, + + @Group("Scala.JS") + @HelpMessage("Path to the Scala.JS linker") + @ValueDescription("path") + @Hidden + jsLinkerPath: Option[String] = None, + @Group("Scala.JS") + @HelpMessage("Scala.JS CLI version to use for linking") + @ValueDescription("version") + @Hidden + jsCliVersion: Option[String] = None, + @Group("Scala.JS") + @HelpMessage("Scala.JS CLI Java options") + @ValueDescription("option") + @Hidden + jsCliJavaArg: List[String] = Nil, + @Group("Scala.JS") + @HelpMessage("Whether to run the Scala.JS CLI on the JVM or using a native executable") + @Hidden + jsCliOnJvm: Option[Boolean] = None ) { // format: on - def buildOptions: options.ScalaJsOptions = + def scalaJsOptions: options.ScalaJsOptions = options.ScalaJsOptions( version = jsVersion, mode = jsMode, @@ -72,6 +93,18 @@ final case class ScalaJsOptions( moduleSplitStyleStr = jsModuleSplitStyle, esVersionStr = jsEsVersion ) + def linkerOptions: options.scalajs.ScalaJsLinkerOptions = + options.scalajs.ScalaJsLinkerOptions( + linkerPath = jsLinkerPath + .filter(_.trim.nonEmpty) + .map(os.Path(_, Os.pwd)), + scalaJsCliVersion = jsCliVersion.map(_.trim).filter(_.nonEmpty), + javaArgs = jsCliJavaArg, + useJvm = jsCliOnJvm.map { + case false => Left(FetchExternalBinary.platformSuffix()) + case true => Right(()) + } + ) } object ScalaJsOptions { diff --git a/modules/cli/src/main/scala/scala/cli/commands/SharedOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/SharedOptions.scala index 5ff1c110b2..01220bb292 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/SharedOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/SharedOptions.scala @@ -148,7 +148,7 @@ final case class SharedOptions( scriptOptions = bo.ScriptOptions( codeWrapper = None ), - scalaJsOptions = js.buildOptions, + scalaJsOptions = js.scalaJsOptions, scalaNativeOptions = native.buildOptions, javaOptions = jvm.javaOptions, internalDependencies = bo.InternalDependenciesOptions( @@ -183,6 +183,9 @@ final case class SharedOptions( localRepository = LocalRepo.localRepo(directories.directories.localRepoDir), verbosity = Some(logging.verbosity), strictBloopJsonCheck = strictBloopJsonCheck + ), + notForBloopOptions = bo.PostBuildOptions( + scalaJsLinkerOptions = js.linkerOptions ) ) } diff --git a/modules/cli/src/main/scala/scala/cli/internal/ScalaJsLinker.scala b/modules/cli/src/main/scala/scala/cli/internal/ScalaJsLinker.scala index 5099e6886f..a60bd2397d 100644 --- a/modules/cli/src/main/scala/scala/cli/internal/ScalaJsLinker.scala +++ b/modules/cli/src/main/scala/scala/cli/internal/ScalaJsLinker.scala @@ -1,17 +1,95 @@ package scala.cli.internal +import coursier.cache.{ArchiveCache, FileCache} +import coursier.util.Task +import coursier.{Repositories, moduleString} import org.scalajs.testing.adapter.{TestAdapterInitializer => TAI} -import scala.build.Logger -import scala.build.errors.ScalaJsLinkingError -import scala.build.internal.{Runner, ScalaJsLinkerConfig} +import java.io.File + +import scala.build.EitherCps.{either, value} +import scala.build.errors.{BuildException, ScalaJsLinkingError} +import scala.build.internal.{FetchExternalBinary, Runner, ScalaJsLinkerConfig} +import scala.build.options.scalajs.ScalaJsLinkerOptions +import scala.build.{Logger, Positioned} +import scala.util.Properties object ScalaJsLinker { + private def linkerCommand( + options: ScalaJsLinkerOptions, + javaCommand: String, + logger: Logger, + cache: FileCache[Task], + archiveCache: ArchiveCache[Task], + scalaJsVersion: String + ): Either[BuildException, Seq[String]] = either { + + options.linkerPath match { + case Some(path) => + Seq(path.toString) + case None => + val scalaJsCliVersion = options.finalScalaJsCliVersion + + options.finalUseJvm match { + case Right(()) => + val scalaJsCliDep = { + val mod = + if (scalaJsCliVersion.contains("-sc")) + mod"io.github.alexarchambault.tmp:scalajs-cli_2.13" + else mod"org.scala-js:scalajs-cli_2.13" + coursier.Dependency(mod, scalaJsCliVersion) + } + + val forcedVersions = Seq( + mod"org.scala-js:scalajs-linker_2.13" -> scalaJsVersion + ) + + val extraRepos = + if (scalaJsVersion.endsWith("SNAPSHOT") || scalaJsCliVersion.endsWith("SNAPSHOT")) + Seq(Repositories.sonatype("snapshots").root) + else + Nil + + val linkerClassPath = value { + scala.build.Artifacts.fetch0( + Positioned.none(Seq(scalaJsCliDep)), + extraRepos, + None, + forcedVersions, + logger, + cache, + None + ) + }.files + + val command = Seq[os.Shellable]( + javaCommand, + options.javaArgs, + "-cp", + linkerClassPath.map(_.getAbsolutePath).mkString(File.pathSeparator), + "org.scalajs.cli.Scalajsld" + ) + + command.flatMap(_.value) + + case Left(osArch) => + val useLatest = scalaJsCliVersion == "latest" + val ext = if (Properties.isWin) ".zip" else ".gz" + val tag = if (useLatest) "launchers" else s"v$scalaJsCliVersion" + val url = + s"https://github.com/scala-cli/scala-js-cli-native-image/releases/download/$tag/scala-js-ld-$scalaJsVersion-$osArch$ext" + val launcher = value { + FetchExternalBinary.fetch(url, useLatest, archiveCache, logger, "scala-js-ld") + } + Seq(launcher.toString) + } + } + } + def link( + options: ScalaJsLinkerOptions, javaCommand: String, - javaArgs: Seq[String], - linkerClassPath: Seq[os.Path], classPath: Seq[os.Path], mainClassOrNull: String, addTestInitializer: Boolean, @@ -19,81 +97,52 @@ object ScalaJsLinker { linkingDir: os.Path, fullOpt: Boolean, noOpt: Boolean, - logger: Logger - ): Either[ScalaJsLinkingError, Unit] = { - - val outputArgs = Seq("--outputDir", linkingDir.toString) - val mainClassArgs = - Option(mainClassOrNull).toSeq.flatMap(mainClass => Seq("--mainMethod", mainClass + ".main")) - val testInitializerArgs = - if (addTestInitializer) - Seq("--mainMethod", TAI.ModuleClassName + "." + TAI.MainMethodName + "!") - else - Nil - // FIXME Fatal asInstanceOfs should be the default, but it seems we can't - // pass Unchecked via the CLI here - // It seems we can't pass the other semantics fields either. - val semanticsArgs = - if (config.semantics.asInstanceOfs == ScalaJsLinkerConfig.CheckedBehavior.Compliant) - Seq("--compliantAsInstanceOfs") - else - Nil - val moduleKindArgs = Seq("--moduleKind", config.moduleKind) - val moduleSplitStyleArgs = Seq("--moduleSplitStyle", config.moduleSplitStyle) - val esFeaturesArgs = - if (config.esFeatures.esVersion == ScalaJsLinkerConfig.ESVersion.ES2015) - Seq("--es2015") - else - Nil - val checkIRArgs = if (config.checkIR) Seq("--checkIR") else Nil - val optArg = - if (noOpt) "--noOpt" - else if (fullOpt) "--fullOpt" - else "--fastOpt" - val sourceMapArgs = if (config.sourceMap) Seq("--sourceMap") else Nil - val relativizeSourceMapBaseArgs = - config.relativizeSourceMapBase.toSeq - .flatMap(uri => Seq("--relativizeSourceMap", uri)) - val prettyPrintArgs = - if (config.prettyPrint) Seq("--prettyPrint") - else Nil - val configArgs = Seq[os.Shellable]( - semanticsArgs, - moduleKindArgs, - moduleSplitStyleArgs, - esFeaturesArgs, - checkIRArgs, - optArg, - sourceMapArgs, - relativizeSourceMapBaseArgs, - prettyPrintArgs - ) + logger: Logger, + cache: FileCache[Task], + archiveCache: ArchiveCache[Task], + scalaJsVersion: String + ): Either[ScalaJsLinkingError, Unit] = either { - val allArgs = Seq[os.Shellable]( - outputArgs, - mainClassArgs, - testInitializerArgs, - configArgs, - classPath.map(_.toString) - ) + val command = value { + linkerCommand(options, javaCommand, logger, cache, archiveCache, scalaJsVersion) + } + + val allArgs = { + val outputArgs = Seq("--outputDir", linkingDir.toString) + val mainClassArgs = + Option(mainClassOrNull).toSeq.flatMap(mainClass => Seq("--mainMethod", mainClass + ".main")) + val testInitializerArgs = + if (addTestInitializer) + Seq("--mainMethod", TAI.ModuleClassName + "." + TAI.MainMethodName + "!") + else + Nil + val optArg = + if (noOpt) "--noOpt" + else if (fullOpt) "--fullOpt" + else "--fastOpt" - // FIXME In quiet mode, silence the output of that? - val retCode = Runner.runJvm( - javaCommand, - javaArgs, - linkerClassPath.map(_.toIO), - "org.scalajs.cli.Scalajsld", - allArgs.flatMap(_.value), + Seq[os.Shellable]( + outputArgs, + mainClassArgs, + testInitializerArgs, + optArg, + config.linkerCliArgs, + classPath.map(_.toString) + ) + } + + val cmd = command ++ allArgs.flatMap(_.value) + val retCode = Runner.run( + "unused", + cmd, logger ) - if (retCode == 0) { + if (retCode == 0) logger.debug("Scala.JS linker ran successfully") - Right(()) - } else { logger.debug(s"Scala.JS linker exited with return code $retCode") - Left(new ScalaJsLinkingError) + value(Left(new ScalaJsLinkingError)) } } diff --git a/modules/cli/src/main/scala/scala/cli/internal/FetchExternalBinary.scala b/modules/core/src/main/scala/scala/build/internal/FetchExternalBinary.scala similarity index 70% rename from modules/cli/src/main/scala/scala/cli/internal/FetchExternalBinary.scala rename to modules/core/src/main/scala/scala/build/internal/FetchExternalBinary.scala index 44b86e75a2..63efd440eb 100644 --- a/modules/cli/src/main/scala/scala/cli/internal/FetchExternalBinary.scala +++ b/modules/core/src/main/scala/scala/build/internal/FetchExternalBinary.scala @@ -1,4 +1,4 @@ -package scala.cli.internal +package scala.build.internal import coursier.cache.{ArchiveCache, CacheLogger} import coursier.error.FetchError @@ -51,21 +51,29 @@ object FetchExternalBinary { launcher } - def platformSuffix(supportsMusl: Boolean = true): String = { + def maybePlatformSuffix(supportsMusl: Boolean = true): Either[String, String] = { val arch = sys.props("os.arch").toLowerCase(Locale.ROOT) match { case "amd64" => "x86_64" case other => other } - val os = - if (Properties.isWin) "pc-win32" + val maybeOs = + if (Properties.isWin) Right("pc-win32") else if (Properties.isLinux) - if (supportsMusl && OsLibc.isMusl.getOrElse(false)) - "pc-linux-static" - else - "pc-linux" - else if (Properties.isMac) "apple-darwin" - else sys.error(s"Unrecognized OS: ${sys.props("os.name")}") - s"$arch-$os" + Right { + if (supportsMusl && OsLibc.isMusl.getOrElse(false)) + "pc-linux-static" + else + "pc-linux" + } + else if (Properties.isMac) Right("apple-darwin") + else Left(s"Unrecognized OS: ${sys.props("os.name")}") + maybeOs.map(os => s"$arch-$os") } + def platformSuffix(supportsMusl: Boolean = true): String = + maybePlatformSuffix(supportsMusl) match { + case Left(err) => sys.error(err) + case Right(value) => value + } + } diff --git a/modules/options/src/main/scala/scala/build/Artifacts.scala b/modules/options/src/main/scala/scala/build/Artifacts.scala index 9f3d6f9cbe..cbef97c6d1 100644 --- a/modules/options/src/main/scala/scala/build/Artifacts.scala +++ b/modules/options/src/main/scala/scala/build/Artifacts.scala @@ -363,7 +363,7 @@ object Artifacts { classifiersOpt ) - private def fetch0( + def fetch0( dependencies: Positioned[Seq[coursier.Dependency]], extraRepositories: Seq[String], forceScalaVersionOpt: Option[String], diff --git a/modules/options/src/main/scala/scala/build/internal/ScalaJsLinkerConfig.scala b/modules/options/src/main/scala/scala/build/internal/ScalaJsLinkerConfig.scala index 0621eba08a..d6565f9a31 100644 --- a/modules/options/src/main/scala/scala/build/internal/ScalaJsLinkerConfig.scala +++ b/modules/options/src/main/scala/scala/build/internal/ScalaJsLinkerConfig.scala @@ -11,7 +11,46 @@ final case class ScalaJsLinkerConfig( prettyPrint: Boolean = false, relativizeSourceMapBase: Option[String] = None, semantics: ScalaJsLinkerConfig.Semantics = ScalaJsLinkerConfig.Semantics() -) +) { + def linkerCliArgs: Seq[String] = { + + // FIXME Fatal asInstanceOfs should be the default, but it seems we can't + // pass Unchecked via the CLI here + // It seems we can't pass the other semantics fields either. + val semanticsArgs = + if (semantics.asInstanceOfs == ScalaJsLinkerConfig.CheckedBehavior.Compliant) + Seq("--compliantAsInstanceOfs") + else + Nil + val moduleKindArgs = Seq("--moduleKind", moduleKind) + val moduleSplitStyleArgs = Seq("--moduleSplitStyle", moduleSplitStyle) + val esFeaturesArgs = + if (esFeatures.esVersion == ScalaJsLinkerConfig.ESVersion.ES2015) + Seq("--es2015") + else + Nil + val checkIRArgs = if (checkIR) Seq("--checkIR") else Nil + val sourceMapArgs = if (sourceMap) Seq("--sourceMap") else Nil + val relativizeSourceMapBaseArgs = + relativizeSourceMapBase.toSeq + .flatMap(uri => Seq("--relativizeSourceMap", uri)) + val prettyPrintArgs = + if (prettyPrint) Seq("--prettyPrint") + else Nil + val configArgs = Seq[os.Shellable]( + semanticsArgs, + moduleKindArgs, + moduleSplitStyleArgs, + esFeaturesArgs, + checkIRArgs, + sourceMapArgs, + relativizeSourceMapBaseArgs, + prettyPrintArgs + ) + + configArgs.flatMap(_.value) + } +} object ScalaJsLinkerConfig { object ModuleKind { diff --git a/modules/options/src/main/scala/scala/build/options/BuildOptions.scala b/modules/options/src/main/scala/scala/build/options/BuildOptions.scala index 2681b48fd9..f81a1cd3c1 100644 --- a/modules/options/src/main/scala/scala/build/options/BuildOptions.scala +++ b/modules/options/src/main/scala/scala/build/options/BuildOptions.scala @@ -157,6 +157,8 @@ final case class BuildOptions( lazy val finalCache = internal.cache.getOrElse(FileCache()) // This might download a JVM if --jvm … is passed or no system JVM is installed + lazy val archiveCache = ArchiveCache().withCache(finalCache) + case class JavaHomeInfo(javaCommand: String, version: Int) private lazy val javaCommand0: Positioned[JavaHomeInfo] = { @@ -275,7 +277,7 @@ final case class BuildOptions( val jvmCache = JvmCache() .withIndex(indexTask) .withArchiveCache( - ArchiveCache().withCache( + archiveCache.withCache( finalCache.withMessage("Downloading JVM") ) ) diff --git a/modules/options/src/main/scala/scala/build/options/PostBuildOptions.scala b/modules/options/src/main/scala/scala/build/options/PostBuildOptions.scala index 51e925b071..b3fd3084c1 100644 --- a/modules/options/src/main/scala/scala/build/options/PostBuildOptions.scala +++ b/modules/options/src/main/scala/scala/build/options/PostBuildOptions.scala @@ -1,9 +1,12 @@ package scala.build.options +import scala.build.options.scalajs.ScalaJsLinkerOptions + final case class PostBuildOptions( packageOptions: PackageOptions = PackageOptions(), replOptions: ReplOptions = ReplOptions(), - publishOptions: PublishOptions = PublishOptions() + publishOptions: PublishOptions = PublishOptions(), + scalaJsLinkerOptions: ScalaJsLinkerOptions = ScalaJsLinkerOptions() ) object PostBuildOptions { diff --git a/modules/options/src/main/scala/scala/build/options/scalajs/ScalaJsLinkerOptions.scala b/modules/options/src/main/scala/scala/build/options/scalajs/ScalaJsLinkerOptions.scala new file mode 100644 index 0000000000..d2d5f8e5e5 --- /dev/null +++ b/modules/options/src/main/scala/scala/build/options/scalajs/ScalaJsLinkerOptions.scala @@ -0,0 +1,31 @@ +package scala.build.options.scalajs + +import scala.build.internal.{Constants, FetchExternalBinary} +import scala.build.options.ConfigMonoid + +final case class ScalaJsLinkerOptions( + javaArgs: Seq[String] = Nil, + /** If right, use JVM, if left, use the value as architecture */ + useJvm: Option[Either[String, Unit]] = None, + scalaJsCliVersion: Option[String] = None, + linkerPath: Option[os.Path] = None +) { + def finalScalaJsCliVersion = scalaJsCliVersion.getOrElse { + Constants.scalaJsCliVersion + } + + /** If right, use JVM, if left, use the value as architecture */ + lazy val finalUseJvm: Either[String, Unit] = useJvm.getOrElse { + FetchExternalBinary.maybePlatformSuffix() match { + case Left(_) => + // FIXME Log error? + Right(()) + case Right(osArch) => + Left(osArch) + } + } +} + +object ScalaJsLinkerOptions { + implicit val monoid: ConfigMonoid[ScalaJsLinkerOptions] = ConfigMonoid.derive +} diff --git a/website/docs/reference/cli-options.md b/website/docs/reference/cli-options.md index ab5b9d94d0..57710c354d 100644 --- a/website/docs/reference/cli-options.md +++ b/website/docs/reference/cli-options.md @@ -998,6 +998,22 @@ The Scala JS module split style: fewestmodules, smallestmodules The Scala JS ECMA Script version: es5_1, es2015, es2016, es2017, es2018, es2019, es2020, es2021 +#### `--js-linker-path` + +Path to the Scala.JS linker + +#### `--js-cli-version` + +Scala.JS CLI version to use for linking + +#### `--js-cli-java-arg` + +Scala.JS CLI Java options + +#### `--js-cli-on-jvm` + +Whether to run the Scala.JS CLI on the JVM or using a native executable + ## Scala Native options Available in commands: