Cross-Platform Dependencies
Cross-platform dependency support (Scala.js, Scala Native) is experimental. It may not work correctly and may change in future versions.
For projects that target Scala.js or Scala Native, the plugin supports additional dependency keys and platform-aware filtering.
Setup
Cross-platform projects still require a build.sbt to enable platform plugins and define sub-projects — build.conf handles only the dependencies and metadata.
Using crossProject (recommended)
The sbt-crossproject plugin provides a crossProject DSL that manages shared and platform-specific source directories automatically. This is the recommended approach for real cross-compilation with shared source code.
// project/plugins.sbt
addSbtPlugin("io.github.matejcerny" % "sbt-config" % "0.6.0")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.10")
addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.3.2")
// build.sbt
lazy val root = crossProject(JVMPlatform, NativePlatform)
.crossType(CrossType.Full)
By default, the plugin reads build.conf from the build root, so every platform sub-project picks it up automatically. Override sbtConfigFile only if your build.conf lives elsewhere.
If build.conf defines name, that value is used as the published artifact's moduleName for every platform component, regardless of the crossProject val name. The auto-generated root project that only aggregates those components is skipped during publishing, so it does not produce an empty aggregate artifact.
This gives you the standard crossProject directory layout:
shared/src/main/scala/ # shared sources compiled on all platforms
jvm/src/main/scala/ # JVM-only sources
native/src/main/scala/ # Native-only sources
For Scala.js, use sbt-scalajs-crossproject instead:
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.20.2")
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2")
Manual separate projects (alternative)
If you don't need shared source code and only want platform-aware dependency filtering, you can define separate projects manually:
// project/plugins.sbt
addSbtPlugin("io.github.matejcerny" % "sbt-config" % "0.6.0")
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.20.2")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.10")
// build.sbt
lazy val jvm = project.in(file("jvm"))
lazy val js = project.in(file("js"))
.enablePlugins(ScalaJSPlugin)
lazy val native = project.in(file("native"))
.enablePlugins(ScalaNativePlugin)
All sub-projects share the same build.conf; the plugin automatically detects each project's platform and filters dependencies accordingly.
Language-Split Format
Use js and native keys alongside scala and java:
dependencies {
scala = ["org.typelevel:cats-core:2.13.0"]
java = ["com.google.code.gson:gson:2.11.0"]
js = ["org.scala-js:scalajs-dom:2.8.0"]
native = ["com.armanbilge:epollcat:0.1.6"]
}
Key Mapping
| Key | sbt Operator | Description |
|---|---|---|
scala |
%% / %%% |
Shared Scala library (%% on JVM, platform-suffixed on JS/Native) |
java |
% |
Plain Java library (no cross-version) |
js |
%%% |
Scala.js library (requires sbt-scalajs plugin) |
native |
%%% |
Scala Native library (requires sbt-scala-native plugin) |
The real distinction between scala and js/native here is scope, not operator: scala (and java) deps are shared — included in every platform — while js/native deps are platform-specific. All Scala deps adapt their cross-version automatically via the active platform plugin, so a shared scala dep resolves as %% on the JVM and %%% in a Scala.js / Scala Native project.
Full Matrix Format
For cross-compiled projects (JVM + Scala.js / Scala Native), use explicit platform grouping:
dependencies {
shared {
scala = ["org.typelevel:cats-core:2.13.0"]
}
jvm {
scala = ["org.typelevel:cats-effect:3.5.0"]
java = ["com.google.code.gson:gson:2.11.0"]
}
js = ["org.scala-js:scalajs-dom:2.8.0"]
native = ["com.armanbilge:epollcat:0.1.6"]
}
The shared and jvm blocks are objects containing scala and/or java keys. The js and native keys are flat lists (all platform-specific deps use %%%).
Platform-Aware Filtering
Dependencies are automatically filtered based on the active platform. The plugin auto-detects which platform a project targets by inspecting the cross-version set by sbt-scalajs or sbt-scala-native:
| Block | JVM project | Scala.js project | Scala Native project |
|---|---|---|---|
shared |
included | included | included |
jvm |
included | excluded | excluded |
js |
excluded | included | excluded |
native |
excluded | excluded | included |
Overriding Platform Detection
The detected platform is exposed as the sbtConfigPlatform setting. If auto-detection doesn't work for your setup, you can override it explicitly:
sbtConfigPlatform := Platform.Js // or Platform.Native, Platform.Jvm
Test Dependencies
Test dependencies also support all cross-platform formats:
testDependencies {
scala = ["org.scalatest:scalatest:3.2.19"]
js = ["org.scala-js:scalajs-test-interface:1.0.0"]
}