Cross-platform compilation support for sbt.
Requirements since sbt-crossproject 1.4.0:
- sbt 1.11.5+ or sbt 2.0.6+
- For
JSPlatform: Scala.js 1.22.0+ - For
NativePlatform: Scala Native 0.5.11+ - JDK 17+
For older versions of dependencies, use sbt-crossproject 1.3.2, which requires:
- sbt 1.2.1+
- For
JSPlatform: Scala.js 0.6.23+ or 1.0.0+ - For
NativePlatform: Scala Native 0.3.7+ - JDK 8+
In project/plugins.sbt:
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.4.0")
addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.4.0")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.22.0")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.11")In build.sbt:
val sharedSettings = Seq(scalaVersion := "2.13.18")
lazy val bar =
// select supported platforms
crossProject(JSPlatform, JVMPlatform, NativePlatform)
.crossType(CrossType.Pure) // [Pure, Full, Dummy], default: CrossType.Full
.settings(sharedSettings)
.jsSettings(/* ... */) // defined in sbt-scalajs-crossproject
.jvmSettings(/* ... */)
// configure Scala-Native settings
.nativeSettings(/* ... */) // defined in sbt-scala-native
lazy val foo =
crossProject(JSPlatform, JVMPlatform, NativePlatform)
.settings(sharedSettings)
.settings(
// sbt 1.x: use %%%
libraryDependencies += "org.example" %%% "foo" % "1.2.3",
// sbt 2.x: use %%
libraryDependencies += "org.example" %% "foo" % "1.2.3",
)If you mainly use one "default" platform in your everyday development, you can tell sbt-crossproject not to add the platform suffix to its project ID. For example, assuming you mainly compile and test for the JVM, you can write:
lazy val bar =
crossProject(JSPlatform, JVMPlatform, NativePlatform)
.withoutSuffixFor(JVMPlatform)
.crossType(...)
.settings(...)The call to withoutSuffixFor must come first after the call to crossProject(), otherwise it will not compile.
Now, in the sbt prompt, you can do
> bar/test
to test the JVM platform (instead of barJVM/test).
This of course applies to all tasks.
Note that inside the build, you still need to use barJVM to the JVM Project.
withoutSuffixFor only changes the id of the project, which is used in the sbt prompt.
Within the settings of a crossProject, you can detect the platform for which those settings are being applied to with crossProjectPlatform.
Here is a contrived example:
lazy val bar =
crossProject(JSPlatform, JVMPlatform, NativePlatform)
.crossType(...)
.settings(
name := "bar for " + crossProjectPlatform.value.identifier
)
...In project/plugins.sbt:
addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.4.0")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.11")In build.sbt:
ThisBuild / scalaVersion := "2.13.18"
lazy val bar =
// select supported platforms
crossProject(JVMPlatform, NativePlatform)
.settings(sharedSettings)
// configure JVM settings
.jvmSettings(/* ... */)
// configure Scala-Native settings
.nativeSettings(/* ... */) // defined in sbt-scala-nativeimport org.portablescala.sbtplatformdeps.PlatformDepsPlugin.autoImport._
import sbtcrossproject.CrossPlugin.autoImport.{crossProject, CrossType, _}
import scalajscrossproject.ScalaJSCrossPlugin.autoImport._
import scalanativecrossproject.ScalaNativeCrossPlugin.autoImport._
Setting a specific CrossType allows the definition of a custom source tree layout for managing native-, js- and jvm-specific sources in directories of their own.
sbt-cross provides by default 3 implementations of the CrossType class that one can
pass as .crossType parameter:
.crossType(CrossType.Pure):
.
├── .js
├── .jvm
├── .native
└── src
This layout is preferred for codebases which do not contain any platform-specific code.
Since this is the case of most existing sbt projects it is often desired during conversion to sbt-cross to place the cross-project at the root of the project source tree.
This can be done with the following set of options:
lazy val foo = crossProject.crossType(CrossType.Pure).in(file("."))
.crossType(CrossType.Full)
.
├── js
├── jvm
├── native
└── shared
This layout gives full control by providing a shared directory for common code.
.crossType(CrossType.Dummy)
.
├── js
├── jvm
└── native
.crossType({/*custom*/})
One can easily extend CrossType and provide a custom tree structure.