Skip to content

Commit

Permalink
Merge pull request #2975 from armanbilge/feature/native
Browse files Browse the repository at this point in the history
Scala Native
  • Loading branch information
mpilquist authored Sep 15, 2022
2 parents 3a291db + 54782c9 commit d306fe8
Show file tree
Hide file tree
Showing 70 changed files with 2,123 additions and 94 deletions.
44 changes: 41 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
os: [ubuntu-latest]
scala: [3.1.3, 2.12.16, 2.13.8]
java: [temurin@17]
project: [rootJS, rootJVM]
project: [rootJS, rootJVM, rootNative]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout current branch (full)
Expand Down Expand Up @@ -66,6 +66,10 @@ jobs:
~/Library/Caches/Coursier/v1
key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }}

- name: Install s2n
if: startsWith(matrix.project, 'rootNative')
run: brew install s2n

- name: Check that workflows are up to date
run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' 'project /' githubWorkflowCheck

Expand All @@ -77,6 +81,10 @@ jobs:
if: matrix.project == 'rootJS'
run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' Test/scalaJSLinkerResult

- name: nativeLink
if: matrix.project == 'rootNative'
run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' Test/nativeLink

- name: Test
run: sbt 'project ${{ matrix.project }}' '++${{ matrix.scala }}' test

Expand All @@ -96,11 +104,11 @@ jobs:
- name: Make target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/series/2.5.x')
run: mkdir -p target protocols/js/target unidocs/target .js/target core/js/target mdoc/target core/jvm/target .jvm/target .native/target scodec/jvm/target scodec/js/target io/js/target reactive-streams/target io/jvm/target protocols/jvm/target benchmark/target project/target
run: mkdir -p target protocols/js/target io/native/target unidocs/target .js/target core/native/target core/js/target protocols/native/target mdoc/target core/jvm/target .jvm/target .native/target scodec/jvm/target scodec/js/target io/js/target reactive-streams/target io/jvm/target protocols/jvm/target scodec/native/target benchmark/target project/target

- name: Compress target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/series/2.5.x')
run: tar cf targets.tar target protocols/js/target unidocs/target .js/target core/js/target mdoc/target core/jvm/target .jvm/target .native/target scodec/jvm/target scodec/js/target io/js/target reactive-streams/target io/jvm/target protocols/jvm/target benchmark/target project/target
run: tar cf targets.tar target protocols/js/target io/native/target unidocs/target .js/target core/native/target core/js/target protocols/native/target mdoc/target core/jvm/target .jvm/target .native/target scodec/jvm/target scodec/js/target io/js/target reactive-streams/target io/jvm/target protocols/jvm/target scodec/native/target benchmark/target project/target

- name: Upload target directories
if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/main' || github.ref == 'refs/heads/series/2.5.x')
Expand Down Expand Up @@ -173,6 +181,16 @@ jobs:
tar xf targets.tar
rm targets.tar
- name: Download target directories (3.1.3, rootNative)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-3.1.3-rootNative

- name: Inflate target directories (3.1.3, rootNative)
run: |
tar xf targets.tar
rm targets.tar
- name: Download target directories (2.12.16, rootJS)
uses: actions/download-artifact@v2
with:
Expand All @@ -193,6 +211,16 @@ jobs:
tar xf targets.tar
rm targets.tar
- name: Download target directories (2.12.16, rootNative)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.16-rootNative

- name: Inflate target directories (2.12.16, rootNative)
run: |
tar xf targets.tar
rm targets.tar
- name: Download target directories (2.13.8, rootJS)
uses: actions/download-artifact@v2
with:
Expand All @@ -213,6 +241,16 @@ jobs:
tar xf targets.tar
rm targets.tar
- name: Download target directories (2.13.8, rootNative)
uses: actions/download-artifact@v2
with:
name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.8-rootNative

- name: Inflate target directories (2.13.8, rootNative)
run: |
tar xf targets.tar
rm targets.tar
- name: Import signing key
if: env.PGP_SECRET != '' && env.PGP_PASSPHRASE == ''
run: echo $PGP_SECRET | base64 -di | gpg --import
Expand Down
72 changes: 59 additions & 13 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import com.typesafe.tools.mima.core._

Global / onChangedBuildSource := ReloadOnSourceChanges

ThisBuild / tlBaseVersion := "3.2"
ThisBuild / tlBaseVersion := "3.3"

ThisBuild / organization := "co.fs2"
ThisBuild / organizationName := "Functional Streams for Scala"
Expand All @@ -14,6 +14,16 @@ ThisBuild / crossScalaVersions := Seq("3.1.3", "2.12.16", NewScala)
ThisBuild / tlVersionIntroduced := Map("3" -> "3.0.3")

ThisBuild / githubWorkflowJavaVersions := Seq(JavaSpec.temurin("17"))
ThisBuild / githubWorkflowBuildPreamble +=
WorkflowStep.Run(
List("brew install s2n"),
name = Some("Install s2n"),
cond = Some("startsWith(matrix.project, 'rootNative')")
)
val isLinux = {
val osName = Option(System.getProperty("os.name"))
osName.exists(_.toLowerCase().contains("linux"))
}

ThisBuild / tlCiReleaseBranches := List("main", "series/2.5.x")

Expand Down Expand Up @@ -160,7 +170,12 @@ ThisBuild / mimaBinaryIssueFilters ++= Seq(
ProblemFilters.exclude[DirectMissingMethodProblem]("fs2.ChunkCompanionPlatform.makeArrayBuilder"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("fs2.concurrent.Channel.trySend"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("fs2.compression.Compression.gunzip"),
ProblemFilters.exclude[ReversedMissingMethodProblem]("fs2.io.net.tls.TLSContext#Builder.insecure")
ProblemFilters.exclude[ReversedMissingMethodProblem](
"fs2.io.net.tls.TLSContext#Builder.systemResource"
),
ProblemFilters.exclude[ReversedMissingMethodProblem](
"fs2.io.net.tls.TLSContext#Builder.insecureResource"
)
)

lazy val root = tlCrossRootProject
Expand All @@ -176,7 +191,11 @@ lazy val root = tlCrossRootProject

lazy val IntegrationTest = config("it").extend(Test)

lazy val core = crossProject(JVMPlatform, JSPlatform)
lazy val commonNativeSettings = Seq(
tlVersionIntroduced := List("2.12", "2.13", "3").map(_ -> "3.2.15").toMap
)

lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.in(file("core"))
.configs(IntegrationTest)
.settings(Defaults.itSettings: _*)
Expand All @@ -194,9 +213,9 @@ lazy val core = crossProject(JVMPlatform, JSPlatform)
"org.typelevel" %%% "cats-effect-laws" % "3.3.14" % Test,
"org.typelevel" %%% "cats-effect-testkit" % "3.3.14" % Test,
"org.scodec" %%% "scodec-bits" % "1.1.34",
"org.typelevel" %%% "scalacheck-effect-munit" % "1.0.4" % Test,
"org.typelevel" %%% "munit-cats-effect-3" % "1.0.7" % Test,
"org.typelevel" %%% "discipline-munit" % "1.0.9" % Test
"org.typelevel" %%% "scalacheck-effect-munit" % "2.0.0-M2" % Test,
"org.typelevel" %%% "munit-cats-effect" % "2.0.0-M3" % Test,
"org.typelevel" %%% "discipline-munit" % "2.0.0-M3" % Test
),
tlJdkRelease := Some(8),
Compile / doc / scalacOptions ++= (if (scalaVersion.value.startsWith("2.")) Seq("-nowarn")
Expand All @@ -217,12 +236,16 @@ lazy val coreJS = core.js
scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule))
)

lazy val io = crossProject(JVMPlatform, JSPlatform)
lazy val coreNative = core.native
.disablePlugins(DoctestPlugin)
.settings(commonNativeSettings)

lazy val io = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.in(file("io"))
.settings(
name := "fs2-io",
libraryDependencies += "com.comcast" %%% "ip4s-core" % "3.1.3",
tlVersionIntroduced ~= { _.updated("3", "3.1.0") }
tlVersionIntroduced ~= { _.updated("3", "3.1.0") },
libraryDependencies += "com.comcast" %%% "ip4s-core" % "3.2.0"
)
.jvmSettings(
Test / fork := true,
Expand All @@ -235,6 +258,24 @@ lazy val io = crossProject(JVMPlatform, JSPlatform)
tlVersionIntroduced := List("2.12", "2.13", "3").map(_ -> "3.1.0").toMap,
scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule))
)
.nativeSettings(commonNativeSettings)
.nativeSettings(
libraryDependencies ++= Seq(
"com.armanbilge" %%% "epollcat" % "0.1.0" % Test
),
nativeConfig ~= { c =>
if (isLinux) { // brew-installed s2n
c.withLinkingOptions(c.linkingOptions :+ "-L/home/linuxbrew/.linuxbrew/lib")
} else c
},
Test / envVars ++= {
val ldLibPath =
if (isLinux)
Map("LD_LIBRARY_PATH" -> "/home/linuxbrew/.linuxbrew/lib")
else Map.empty
Map("S2N_DONT_MLOCK" -> "1") ++ ldLibPath
}
)
.dependsOn(core % "compile->compile;test->test")
.jsSettings(
mimaBinaryIssueFilters ++= Seq(
Expand Down Expand Up @@ -283,25 +324,29 @@ lazy val io = crossProject(JVMPlatform, JSPlatform)
ProblemFilters.exclude[DirectMissingMethodProblem]("fs2.io.net.tls.TLSSocket.forAsync")
)
)
.nativeSettings(
nativeConfig ~= { _.withEmbedResources(true) }
)

lazy val scodec = crossProject(JVMPlatform, JSPlatform)
lazy val scodec = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.in(file("scodec"))
.settings(
name := "fs2-scodec",
libraryDependencies += "org.scodec" %%% "scodec-core" % (if (
scalaVersion.value.startsWith("2.")
)
"1.11.9"
else "2.1.0"),
"1.11.10"
else "2.2.0"),
tlVersionIntroduced := List("2.12", "2.13", "3").map(_ -> "3.2.0").toMap,
tlJdkRelease := Some(8)
)
.jsSettings(
scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule))
)
.nativeSettings(commonNativeSettings)
.dependsOn(core % "compile->compile;test->test", io % "test")

lazy val protocols = crossProject(JVMPlatform, JSPlatform)
lazy val protocols = crossProject(JVMPlatform, JSPlatform, NativePlatform)
.in(file("protocols"))
.settings(
name := "fs2-protocols",
Expand All @@ -311,6 +356,7 @@ lazy val protocols = crossProject(JVMPlatform, JSPlatform)
.jsSettings(
scalaJSLinkerConfig ~= (_.withModuleKind(ModuleKind.CommonJSModule))
)
.nativeSettings(commonNativeSettings)
.dependsOn(core % "compile->compile;test->test", scodec, io)

lazy val reactiveStreams = project
Expand Down
1 change: 1 addition & 0 deletions core/js/src/test/scala/fs2/TestPlatform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ package fs2

trait TestPlatform {
def isJVM: Boolean = false
def isNative: Boolean = false
}
1 change: 1 addition & 0 deletions core/jvm/src/test/scala/fs2/TestPlatform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ package fs2

trait TestPlatform {
def isJVM: Boolean = true
def isNative: Boolean = false
}
26 changes: 26 additions & 0 deletions core/native/src/main/scala/fs2/ChunkRuntimePlatform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2013 Functional Streams for Scala
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package fs2

private[fs2] trait ChunkRuntimePlatform[+O]

private[fs2] trait ChunkCompanionRuntimePlatform
27 changes: 27 additions & 0 deletions core/native/src/test/scala/fs2/TestPlatform.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (c) 2013 Functional Streams for Scala
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package fs2

trait TestPlatform {
def isJVM: Boolean = false
def isNative: Boolean = true
}
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ class StreamCombinatorsSuite extends Fs2Suite {
.map { result =>
assertEquals(result.size, 1)
val head = result.head
assert(head.toMillis >= (delay.toMillis - 5))
assert(clue(head.toMillis) >= clue(delay.toMillis - 5))
}
}

Expand Down
25 changes: 25 additions & 0 deletions io/js-jvm/src/test/scala/fs2/io/Fs2IoSuite.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright (c) 2013 Functional Streams for Scala
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

package fs2
package io

abstract class Fs2IoSuite extends Fs2Suite
10 changes: 9 additions & 1 deletion io/js/src/main/scala/fs2/io/net/tls/TLSContextPlatform.scala
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ private[tls] trait TLSContextCompanionPlatform { self: TLSContext.type =>

private[tls] trait BuilderPlatform[F[_]] {
def fromSecureContext(context: SecureContext): TLSContext[F]
def system: F[TLSContext[F]]
def insecure: F[TLSContext[F]]
}

private[tls] trait BuilderCompanionPlatform {
private[tls] final class AsyncBuilder[F[_]](implicit F: Async[F]) extends Builder[F] {
private[tls] final class AsyncBuilder[F[_]](implicit F: Async[F]) extends UnsealedBuilder[F] {

def fromSecureContext(
context: SecureContext,
Expand Down Expand Up @@ -143,8 +145,14 @@ private[tls] trait TLSContextCompanionPlatform { self: TLSContext.type =>
def system: F[TLSContext[F]] =
Async[F].delay(fromSecureContext(SecureContext.default))

def systemResource: Resource[F, TLSContext[F]] =
Resource.eval(system)

def insecure: F[TLSContext[F]] =
Async[F].delay(fromSecureContext(SecureContext.default, insecure = true))

def insecureResource: Resource[F, TLSContext[F]] =
Resource.eval(insecure)
}
}
}
Loading

0 comments on commit d306fe8

Please sign in to comment.