Skip to content

Commit

Permalink
feat: Platform and runtime independent bindings must be able to targe…
Browse files Browse the repository at this point in the history
…t libraries on the system path (#129)

Fixes #96
  • Loading branch information
markehammons authored Apr 2, 2023
1 parent fcb054c commit daf1380
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 8 deletions.
26 changes: 21 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,35 +32,51 @@ jobs:
java-version: |
17
19
- run: mkdir reports
- name: Core tests
run: |
./mill core.compile
./mill core.test
./mill core.scoverage.xmlReport
cp out/core/scoverage/xmlReport.dest/scoverage.xml reports/core-coverage.xml
env:
JAVA_HOME: ${{ env.JAVA_HOME_17_X64}}

- name: Java 17 Implementation test
run: |
./mill j17.compile
./mill j17.test
./mill j17.scoverage.xmlReport
cp out/j17/scoverage/xmlReport.dest/scoverage.xml reports/java17-coverage.xml
env:
JAVA_HOME: ${{ env.JAVA_HOME_17_X64}}

- name: Java 19 Implementation test
run: |
./mill j19.compile
./mill j19.test
./mill j19.scoverage.xmlReport
cp out/j19/scoverage/xmlReport.dest/scoverage.xml reports/java19-coverage.xml
- name: Runtime 17 implementation tests
run: ./mill runtime.test
run: |
./mill runtime.test
./mill runtime.scoverage.xmlReport
cp out/runtime/scoverage/xmlReport.dest/scoverage.xml reports/java-17-runtime-coverage.xml
env:
JAVA_HOME: ${{ env.JAVA_HOME_17_X64 }}

- name: Runtime 19 implementation tests
run: ./mill runtime.test
- run: ./mill scoverage.xmlReportAll
run: |
./mill runtime.test
./mill runtime.scoverage.xmlReport
cp out/runtime/scoverage/xmlReport.dest/scoverage.xml reports/java-19-runtime-coverage.xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
directory: out/scoverage/xmlReportAll.dest
flags: unittests
directory: reports
flags: ${{ matrix.os }}
8 changes: 6 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
![workflow status](https://github.com/markehammons/slinc/actions/workflows/ci.yml/badge.svg)![Maven Central](https://img.shields.io/maven-central/v/fr.hammons/slinc-core_3)
![workflow status](https://github.com/markehammons/slinc/actions/workflows/ci.yml/badge.svg)![Maven Central](https://img.shields.io/maven-central/v/fr.hammons/slinc-core_3)[![codecov](https://codecov.io/gh/markehammons/slinc/branch/master/graph/badge.svg?token=MSTGFQYNXI)](https://codecov.io/gh/markehammons/slinc)

```
S Lin C
Expand Down Expand Up @@ -50,4 +50,8 @@ val myLib = Lib.instance[MyLib]

This library relies on the user importing the runtime from `fr.hammons.slinc.runtime`.

To learn more about the library, refer to the documentation website for Slinc [here](https://slinc.hammons.fr/docs/index.html)
To learn more about the library, refer to the documentation website for Slinc [here](https://slinc.hammons.fr/docs/index.html)

## Coverage

![CodeCvg](https://codecov.io/gh/markehammons/slinc/branch/master/graphs/tree.svg?token=MSTGFQYNXI)
3 changes: 2 additions & 1 deletion core/src/fr/hammons/slinc/FSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import java.util.concurrent.atomic.AtomicStampedReference
import scala.annotation.nowarn
import fr.hammons.slinc.fset.Dependency
import fr.hammons.slinc.annotations.NeedsResource
import fr.hammons.slinc.annotations.Needs

trait FSet[L]:
val dependencies: List[Dependency]
Expand Down Expand Up @@ -58,7 +59,7 @@ object FSet:
'{
new FSet[L]:
val dependencies =
NeedsResource[L].map(_.toDependency)
(NeedsResource[L] ++ Needs[L]).map(_.toDependency)
val description = $descriptors
val generation = $generators
}
Expand Down
31 changes: 31 additions & 0 deletions core/src/fr/hammons/slinc/annotations/Needs.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package fr.hammons.slinc.annotations

import scala.annotation.StaticAnnotation
import fr.hammons.slinc.fset.Dependency
import scala.quoted.*

final case class Needs(libName: String)
extends StaticAnnotation,
DependencyAnnotation:
def toDependency: Dependency = Dependency.PathLibrary(libName)

object Needs:
inline def apply[F]: List[Needs] = ${
apply[F]()
}

def apply[F]()(using Quotes, Type[F]) =
import quotes.reflect.*

Expr.ofList(
TypeRepr
.of[F]
.classSymbol
.get
.annotations
.view
.map(_.asExpr)
.collect:
case n @ '{ new Needs(${ _ }) } => n
.toList
)
1 change: 1 addition & 0 deletions core/src/fr/hammons/slinc/fset/Dependency.scala
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ import java.nio.file.Path
enum Dependency:
case LibraryResource(path: Path)
case CResource(path: Path)
case PathLibrary(name: String)
5 changes: 5 additions & 0 deletions core/src/fr/hammons/slinc/modules/LinkageTools.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ object LinkageTools:
def load(path: Path): Unit =
System.load(path.toAbsolutePath().toString())

def loadLibrary(name: String): Unit =
System.loadLibrary(name)

def loadDependency(dependency: Dependency): Unit = synchronized {
val currentDeps = dependenciesLoaded.get.nn
if !currentDeps.contains(dependency) then
Expand All @@ -70,6 +73,8 @@ object LinkageTools:
val cachedFile = sendResourceToCache(path)
val compilationPath = compileCachedCCode(cachedFile)
load(compilationPath)
case Dependency.PathLibrary(name) =>
loadLibrary(name)

dependenciesLoaded.compareAndExchange(
currentDeps,
Expand Down
19 changes: 19 additions & 0 deletions core/test/src/fr/hammons/slinc/BindingSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,20 @@ package fr.hammons.slinc
import munit.ScalaCheckSuite
import scala.concurrent.duration.*
import scala.annotation.nowarn
import annotations.Needs

trait BindingSpec(val slinc: Slinc) extends ScalaCheckSuite:
import slinc.{given, *}
override def munitTimeout: Duration = 5.minutes
@LibraryName("@test")
object Test derives Library:
@nowarn("msg=unused explicit parameter")
def identity_int(i: CInt): CInt = Library.binding

case class I31Struct(field: Ptr[CChar]) derives Struct

// issue 31 test binding
@nowarn("msg=unused explicit parameter")
def i31test(struct: I31Struct): Ptr[CChar] = Library.binding

case class I36Struct(i: CInt, c: Ptr[CChar]) derives Struct
Expand All @@ -24,6 +27,7 @@ trait BindingSpec(val slinc: Slinc) extends ScalaCheckSuite:
// issue 36 test bindings
def i36_get_my_struct(): Ptr[I36Struct] = Library.binding
def i36_get_mystruct_by_value(): I36Struct = Library.binding
@nowarn("msg=unused explicit parameter")
def i36_copy_my_struct(ptr: Ptr[I36Struct]): Unit = Library.binding
def i36_nested(): Ptr[I36Outer] = Library.binding

Expand Down Expand Up @@ -63,3 +67,18 @@ trait BindingSpec(val slinc: Slinc) extends ScalaCheckSuite:

assertEquals((!(!ptr2).inner).i, 43)
}

// ZLIB test
test("zlib works"):
@Needs("z")
trait ZLib derives FSet:
def zlibVersion(): Ptr[CChar]
val zlib = FSet.instance[ZLib]

val version = zlib.zlibVersion().copyIntoString(256)

assertEquals(
version.count(_ == '.'),
2,
s"$version contains more than 2 periods."
)
10 changes: 10 additions & 0 deletions core/test/src/fr/hammons/slinc/FSetSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,13 @@ class FSetSpec extends munit.FunSuite:
summon[FSet[L]].dependencies,
List(Dependency.CResource(Paths.get("test.c").nn))
)

test("library dependencies should be recorded for loading"):
@Needs("posix")
trait L derives FSet:
def abs(i: CInt): CInt

assertEquals(
summon[FSet[L]].dependencies,
List(Dependency.PathLibrary("posix"))
)

0 comments on commit daf1380

Please sign in to comment.