Skip to content

Commit

Permalink
Cross compile scala-native-cli with Scala Native
Browse files Browse the repository at this point in the history
Co-authored-by: Tomasz Godzik <tgodzik@users.noreply.github.com>
  • Loading branch information
jchyb and tgodzik committed Sep 17, 2024
1 parent a8baa8b commit e27b6ad
Show file tree
Hide file tree
Showing 390 changed files with 1,277 additions and 225 deletions.
24 changes: 22 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,29 @@ jobs:
- run:
# for GitOps tests
git config --global user.email "scalafmt@scalameta.org" && git config --global user.name "scalafmt"
- run: TEST="2.12" sbt ci-test
- run: TEST="2.12" sbt ci-test-jvm
shell: bash
- run: TEST="2.13" sbt ci-test
- run: TEST="2.13" sbt ci-test-jvm
shell: bash
test-scala-native:
strategy:
fail-fast: false
matrix:
os: [macOS-latest, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v2
- uses: olafurpg/setup-scala@v13
with:
java-version: adopt@1.8
- name: run tests
run: |
git fetch --tags -f
# for GitOps tests
git config --global user.email "scalafmt@scalameta.org" && git config --global user.name "scalafmt"
- run: TEST="2.12" sbt ci-test-native
shell: bash
- run: TEST="2.13" sbt ci-test-native
shell: bash
community-test:
strategy:
Expand Down
165 changes: 100 additions & 65 deletions build.sbt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Dependencies._
import sbtcrossproject.CrossPlugin.autoImport.crossProject
import scala.scalanative.build._

def parseTagVersion: String = {
import scala.sys.process._
Expand Down Expand Up @@ -30,17 +31,16 @@ inThisBuild(List(
crossScalaVersions := List(scala213, scala212),
resolvers ++= Resolver.sonatypeOssRepos("releases"),
resolvers ++= Resolver.sonatypeOssRepos("snapshots"),
libraryDependencies ++=
List(munit.value % Test, scalacheck % Test, scalametaTestkit % Test),
testFrameworks += new TestFramework("munit.Framework"),
))

name := "scalafmtRoot"
publish / skip := true

addCommandAlias("native-image", "cli/nativeImage")
addCommandAlias("scala-native", "cliNative/compile;cliNative/nativeLink")

commands += Command.command("ci-test") { s =>
commands += Command.command("ci-test-jvm") { s =>
val scalaVersion = sys.env.get("TEST") match {
case Some("2.12") => scala212
case _ => scala213
Expand All @@ -50,23 +50,26 @@ commands += Command.command("ci-test") { s =>
docsTest :: s
}

lazy val dynamic = project.in(file("scalafmt-dynamic")).settings(
moduleName := "scalafmt-dynamic",
description := "Implementation of scalafmt-interfaces",
buildInfoSettings,
buildInfoPackage := "org.scalafmt.dynamic",
buildInfoObject := "BuildInfo",
libraryDependencies ++= List(
"io.get-coursier" % "interface" % "0.0.17",
"com.typesafe" % "config" % "1.4.3",
munit.value % Test,
scalametaTestkit % Test,
),
scalacOptions ++= scalacJvmOptions.value,
).dependsOn(interfaces, sysops.jvm).dependsOn(core.jvm % "test")
lazy val dynamic = crossProject(JVMPlatform, NativePlatform).withoutSuffixFor(JVMPlatform)
.in(file("scalafmt-dynamic")).settings(
moduleName := "scalafmt-dynamic",
description := "Implementation of scalafmt-interfaces",
buildInfoSettings,
buildInfoPackage := "org.scalafmt.dynamic",
buildInfoObject := "BuildInfo",
libraryDependencies ++= List(
"io.get-coursier" % "interface" % "0.0.17",
"com.typesafe" % "config" % "1.4.3",
munit.value % Test,
scalametaTestkit.value % Test,
),
scalacOptions ++= scalacJvmOptions.value,
)
.dependsOn(interfaces, sysops)
.dependsOn(core % "test")
.enablePlugins(BuildInfoPlugin)

lazy val interfaces = project.in(file("scalafmt-interfaces")).settings(
lazy val interfaces = crossProject(JVMPlatform, NativePlatform).withoutSuffixFor(JVMPlatform).in(file("scalafmt-interfaces")).settings(
moduleName := "scalafmt-interfaces",
description :=
"Dependency-free, pure Java public interfaces to integrate with Scalafmt through a build tool or editor plugin.",
Expand All @@ -82,7 +85,7 @@ lazy val interfaces = project.in(file("scalafmt-interfaces")).settings(
},
)

lazy val sysops = crossProject(JVMPlatform).withoutSuffixFor(JVMPlatform)
lazy val sysops = crossProject(JVMPlatform, NativePlatform).withoutSuffixFor(JVMPlatform)
.in(file("scalafmt-sysops")).settings(
moduleName := "scalafmt-sysops",
description := "Scalafmt systems operations",
Expand All @@ -98,48 +101,67 @@ lazy val sysops = crossProject(JVMPlatform).withoutSuffixFor(JVMPlatform)
},
)

lazy val config = crossProject(JVMPlatform).withoutSuffixFor(JVMPlatform)
lazy val config = crossProject(JVMPlatform, NativePlatform).withoutSuffixFor(JVMPlatform)
.in(file("scalafmt-config")).settings(
moduleName := "scalafmt-config",
description := "Scalafmt config parsing",
scalacOptions ++= scalacJvmOptions.value,
libraryDependencies ++= Seq(metaconfig.value),
).jvmSettings(libraryDependencies ++= Seq(metaconfigTypesafe.value))
)
.jvmSettings(libraryDependencies ++= Seq(metaconfigTypesafe.value))
.nativeSettings(
libraryDependencies ++= Seq(metaconfigSconfig.value)
)
// .jsSettings(
// libraryDependencies ++= Seq(
// metaconfigHocon.value,
// )
// )

lazy val core = crossProject(JVMPlatform).in(file("scalafmt-core")).settings(
moduleName := "scalafmt-core",
buildInfoSettings,
scalacOptions ++= scalacJvmOptions.value,
libraryDependencies ++= Seq(
scalameta.value,
"org.scalameta" %% "mdoc-parser" % mdocV,
// scala-reflect is an undeclared dependency of fansi, see #1252.
// Scalafmt itself does not require scala-reflect.
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
),
libraryDependencies ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 13)) => Seq()
case _ => Seq(compilerPlugin(
"org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full,
))
}
},
)
lazy val core = crossProject(JVMPlatform, NativePlatform)
.withoutSuffixFor(JVMPlatform)
.in(file("scalafmt-core")).settings(
moduleName := "scalafmt-core",
buildInfoSettings,
scalacOptions ++= scalacJvmOptions.value,
libraryDependencies ++= Seq(
scalameta.value,
"com.lihaoyi" %%% "fastparse" % "3.1.0",
"org.scalameta" %%% "mdoc-parser" % mdocV,
// scala-reflect is an undeclared dependency of fansi, see #1252.
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
),
libraryDependencies ++= {
CrossVersion.partialVersion(scalaVersion.value) match {
case Some((2, 13)) => Seq()
case _ => Seq(compilerPlugin(
"org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full,
))
}
},
)
// .jsSettings(
// libraryDependencies ++= List(
// scalatest.value % Test // must be here for coreJS/test to run anything
// )
// )
.jvmSettings(Test / run / fork := true).dependsOn(sysops, config)
.jvmSettings(Test / run / fork := true)
.dependsOn(sysops, config, macros)
.enablePlugins(BuildInfoPlugin)

lazy val coreJVM = core.jvm
// lazy val coreJS = core.js

lazy val macros = crossProject(JVMPlatform, NativePlatform)
.withoutSuffixFor(JVMPlatform)
.in(file("scalafmt-macros")).settings(
moduleName := "scalafmt-macros",
buildInfoSettings,
scalacOptions ++= scalacJvmOptions.value,
libraryDependencies ++= Seq(
scalameta.value,
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
)
)

import sbtassembly.AssemblyPlugin.defaultUniversalScript

Expand All @@ -156,7 +178,7 @@ val scalacJvmOptions = Def.setting {
cross ++ unused
}

lazy val cli = project.in(file("scalafmt-cli")).settings(
lazy val cli = crossProject(JVMPlatform, NativePlatform).withoutSuffixFor(JVMPlatform).in(file("scalafmt-cli")).settings(
moduleName := "scalafmt-cli",
assembly / mainClass := Some("org.scalafmt.cli.Cli"),
assembly / assemblyOption := (assembly / assemblyOption).value
Expand All @@ -169,9 +191,9 @@ lazy val cli = project.in(file("scalafmt-cli")).settings(
oldStrategy(x)
},
libraryDependencies ++= Seq(
"com.googlecode.java-diff-utils" % "diffutils" % "1.3.0",
"org.scalameta" %%% "munit-diff" % "1.0.2",
"com.martiansoftware" % "nailgun-server" % "0.9.1",
"com.github.scopt" %% "scopt" % "4.1.0",
"com.github.scopt" %%% "scopt" % "4.1.0",
),
scalacOptions ++= scalacJvmOptions.value,
Compile / mainClass := Some("org.scalafmt.cli.Cli"),
Expand All @@ -185,29 +207,37 @@ lazy val cli = project.in(file("scalafmt-cli")).settings(
val isStatic = sys.env.get("NATIVE_IMAGE_STATIC").exists(_.toBoolean)
if (isStatic) Seq("--static") else Nil
},
).dependsOn(coreJVM, dynamic).enablePlugins(NativeImagePlugin)
).nativeSettings(scalaNativeNativeConfig).dependsOn(core, dynamic).enablePlugins(NativeImagePlugin)

lazy val tests = crossProject(JVMPlatform, NativePlatform)
.withoutSuffixFor(JVMPlatform)
.in(file("scalafmt-tests"))
.settings(
publish / skip := true,
libraryDependencies ++= Seq(
// Test dependencies
"com.lihaoyi" %%% "scalatags" % "0.13.1",
scalametaTestkit.value,
"org.scalameta" %%% "munit" % "1.0.0" % Test
),
scalacOptions ++= scalacJvmOptions.value,
buildInfoPackage := "org.scalafmt.tests",
buildInfoKeys :=
Seq[BuildInfoKey]("resourceDirectory" -> (baseDirectory.value / ".." / "shared" / "src" / "test" / "resources")),
)
.enablePlugins(BuildInfoPlugin)
.jvmSettings(
javaOptions += "-Dfile.encoding=UTF8",
)
.dependsOn(core, dynamic, cli)

lazy val tests = project.in(file("scalafmt-tests")).settings(
publish / skip := true,
libraryDependencies ++= Seq(
// Test dependencies
"com.lihaoyi" %% "scalatags" % "0.13.1",
scalametaTestkit,
munit.value,
),
scalacOptions ++= scalacJvmOptions.value,
javaOptions += "-Dfile.encoding=UTF8",
buildInfoPackage := "org.scalafmt.tests",
buildInfoKeys :=
Seq[BuildInfoKey]("resourceDirectory" -> (Test / resourceDirectory).value),
).enablePlugins(BuildInfoPlugin).dependsOn(coreJVM, dynamic, cli)

lazy val communityTests = project.in(file("scalafmt-tests-community")).settings(
publish / skip := true,
libraryDependencies ++= Seq(
// Test dependencies
"com.lihaoyi" %% "scalatags" % "0.13.1",
scalametaTestkit,
scalametaTestkit.value,
munit.value,
),
scalacOptions ++= scalacJvmOptions.value,
Expand All @@ -218,7 +248,7 @@ lazy val communityTests = project.in(file("scalafmt-tests-community")).settings(
lazy val benchmarks = project.in(file("scalafmt-benchmarks")).settings(
publish / skip := true,
moduleName := "scalafmt-benchmarks",
libraryDependencies ++= Seq(scalametaTestkit),
libraryDependencies ++= Seq(scalametaTestkit.value),
run / javaOptions ++= Seq(
"-Djava.net.preferIPv4Stack=true",
"-XX:+AggressiveOpts",
Expand All @@ -235,13 +265,13 @@ lazy val benchmarks = project.in(file("scalafmt-benchmarks")).settings(
"-Xmx2G",
"-server",
),
).dependsOn(coreJVM).enablePlugins(JmhPlugin)
).dependsOn(core.jvm).enablePlugins(JmhPlugin)

lazy val docs = project.in(file("scalafmt-docs")).settings(
crossScalaVersions := List(scala212),
publish / skip := true,
mdoc := (Compile / run).evaluated,
).dependsOn(cli, dynamic).enablePlugins(DocusaurusPlugin)
).dependsOn(cli.jvm, dynamic.jvm).enablePlugins(DocusaurusPlugin)

val V = "\\d+\\.\\d+\\.\\d+"
val ReleaseCandidate = s"($V-RC\\d+).*".r
Expand Down Expand Up @@ -270,3 +300,8 @@ lazy val buildInfoSettings: Seq[Def.Setting[_]] = Seq(
buildInfoPackage := "org.scalafmt",
buildInfoObject := "Versions",
)

lazy val scalaNativeNativeConfig =
nativeConfig ~= {
_.withMode(Mode.releaseFull)
}
2 changes: 1 addition & 1 deletion docs/contributing-scalafmt.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ To build a native image of the command-line interface using

- From the project root directory,
- run `sbt cli/assembly`
- run `java -jar scalafmt-cli/target/scala-2.13/scalafmt.jar`, to execute recently built artifacts
- run `java -jar scalafmt-cli/jvm/target/scala-2.13/scalafmt.jar`, to execute recently built artifacts

## Random stuff

Expand Down
2 changes: 1 addition & 1 deletion docs/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ handle parse and config errors.

Here is an example how to extend `ScalafmtReporter`.

```scala mdoc:file:scalafmt-dynamic/src/main/scala/org/scalafmt/dynamic/ConsoleScalafmtReporter.scala
```scala mdoc:file:scalafmt-dynamic/shared/src/main/scala/org/scalafmt/dynamic/ConsoleScalafmtReporter.scala

```

Expand Down
5 changes: 3 additions & 2 deletions project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ object Dependencies {
val scalacheckV = "1.18.0"
val coursier = "2.1.10"
val munitV = "1.0.1"
val mdocV = "2.5.4"
val mdocV = "2.6.0"

val scalapb = Def.setting {
ExclusionRule(
Expand All @@ -21,7 +21,7 @@ object Dependencies {
)
}

val scalametaTestkit = "org.scalameta" %% "testkit" % scalametaV
val scalametaTestkit = Def.setting("org.scalameta" %%% "testkit" % scalametaV)

val scalacheck = "org.scalacheck" %% "scalacheck" % scalacheckV
val munit = Def.setting("org.scalameta" %%% "munit" % munitV)
Expand All @@ -32,5 +32,6 @@ object Dependencies {
val metaconfigTypesafe = Def
.setting("org.scalameta" %%% "metaconfig-typesafe-config" % metaconfigV)
val metaconfigHocon = Def.setting("com.geirsson" %%% "metaconfig-hocon" % metaconfigV)
val metaconfigSconfig = Def.setting("org.scalameta" %%% "metaconfig-sconfig" % metaconfigV)

}
2 changes: 2 additions & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.16.0")
addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.3.2")
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.4")
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.10.4")
addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.3.2")
addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.5.5")
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.scalafmt.cli

class CliOptionsUtils {
def makeOutputStreamOrWriter(parsed: CliOptions): Output.StreamOrWriter = {
val usesOut = parsed.stdIn || parsed.writeMode.usesOut
val cons = if (usesOut) System.console() else null
if (cons ne null) new Output.FromWriter(cons.writer())
else new Output.FromStream(
if (parsed.noStdErr || !usesOut) parsed.common.out
else parsed.common.err,
)
}
}
Loading

0 comments on commit e27b6ad

Please sign in to comment.