Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Organize projects #222

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@ out
.attach*
*.log
*.so
*.dylib
slinc/src/io/gitlab/mhammons/slinc/test.worksheet.sc
*.bench
.bsp
.scala-build
.DS_Store

metals.sbt
metals.sbt
target
98 changes: 77 additions & 21 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -33,26 +33,82 @@ inThisBuild(
)
)

scalacOptions ++= Seq(
"-deprecation",
"-Wunused:all",
"-feature",
"-unchecked",
"-Xcheck-macros",
"-Xprint-suspension",
"-Xsemanticdb",
"-Yexplicit-nulls",
"-Ysafe-init",
"-source:future",
"-Ykind-projector",
"-Vprofile"
)
lazy val slinc = project
.in(file("slinc"))
.settings(
name := "slinc",
scalacOptions ++= Seq(
"-deprecation",
"-Wunused:all",
"-feature",
"-unchecked",
"-Xcheck-macros",
"-Xprint-suspension",
"-Xsemanticdb",
"-Yexplicit-nulls",
"-Ysafe-init",
"-source:future",
"-Ykind-projector",
"-Vprofile"
),
libraryDependencies += "org.scalameta" %% "munit" % "1.0.0-M10" % Test,
libraryDependencies += "org.scalameta" %% "munit-scalacheck" % "1.0.0-M10" % Test,
libraryDependencies += "org.scala-lang" %% "scala3-staging" % scalaVersion.value,
Compile / doc / scalacOptions ++= Seq("-siteroot", "docs"),
mimaPreviousArtifacts := previousStableVersion.value
.map(organization.value %% moduleName.value % _)
.toSet
)

libraryDependencies += "org.scalameta" %% "munit" % "1.0.0-M10" % Test
libraryDependencies += "org.scalameta" %% "munit-scalacheck" % "1.0.0-M10" % Test
libraryDependencies += "org.scala-lang" %% "scala3-staging" % scalaVersion.value
lazy val copyNative = TaskKey[Set[File]]("copy shared lib")

Compile / doc / scalacOptions ++= Seq("-siteroot", "docs")
mimaPreviousArtifacts := previousStableVersion.value
.map(organization.value %% moduleName.value % _)
.toSet
lazy val examples = project
.in(file("slinc-examples"))
.dependsOn(slinc)
.settings(
publishTo := None,
publishLocal := Def.task(()),
copyNative := {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This copies a shared lib from examples-native project to load it from resource.
https://github.com/scala-interop/slinc/pull/222/files#diff-d7b7c9d5ea6a2ac0cbbd2da77262f2b3074469d52c44ad9dd3a3dd2b16f00ebbR7

Compile / resourceGenerators is invoked at run and package.

Executing run (or package, not compile) will add a file demo to resourceManaged, which is target/scala-*/resource_managed". By default, generated resources are not included in the packaged source artifact. To do so, add them as you would other mappings. See Adding files to a package.
https://www.scala-sbt.org/1.x/docs/Howto-Generating-Files.html

val nativeSrc = (`examples-native` / Compile / nativeCompile).value
// rename shared lib name so that it complies with SlinC convention(`{lib name}_{arch}.{ext}`).
val destName = {
val arch =
(`examples-native` / nativePlatform).value.takeWhile(_ != '-')
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nativePlatform returns string in format {arch}-{kernel} such as arm64-darwin.

val (base, ext) = nativeSrc.baseAndExt
s"${base}_${arch}.${ext}"
}
val nativeDest =
(Compile / resourceDirectory).value / "native" / destName
IO.copy(Seq(nativeSrc -> nativeDest))
},
Compile / resourceGenerators += Def.task {
copyNative.value.toSeq
}.taskValue,
run / fork := true,
javaOptions ++= Seq(
"--add-modules=jdk.incubator.foreign",
"--enable-native-access=ALL-UNNAMED"
),
libraryDependencies += "fr.hammons" %% "slinc-runtime" % "0.6.0"
)
.dependsOn(`examples-native`)

/*
* A project to build native shared library
*/
lazy val `examples-native` = project
.in(file("slinc-examples-native"))
.enablePlugins(JniNative)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JniNative is not necessary, but I think it will reduce LoC.

.settings(
publishTo := None,
publishLocal := Def.task(()),
nativeCompile / sourceDirectory := sourceDirectory.value
)
Comment on lines +99 to +106
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JniNative plugin invokes CMake to create native shared lib.


lazy val root = project
.in(file("."))
.aggregate(slinc, examples, `examples-native`)
.settings(
publishTo := None,
publishLocal := Def.task(())
)
1 change: 1 addition & 0 deletions project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.5")
addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.12")
addSbtPlugin("ch.epfl.scala" % "sbt-tasty-mima" % "1.1.0")
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "1.1.3")
addSbtPlugin("com.github.sbt" % "sbt-jni" % "1.6.0")
24 changes: 24 additions & 0 deletions slinc-examples-native/src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 3.1)

option(SBT "Set if invoked from sbt-jni" OFF)

project(add)

set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 0)
set(PROJECT_VERSION_PATCH 0)

include_directories(.)
include_directories(include)
add_library(add MODULE add.c)

# Sources
file(GLOB LIB_SRC
"*.c"
"*.cc"
"*.cpp"
)

set (LIB_NAME ${PROJECT_NAME}${PROJECT_VERSION_MAJOR})
add_library(${LIB_NAME} SHARED ${LIB_SRC})
install(TARGETS ${LIB_NAME} LIBRARY DESTINATION .)
19 changes: 19 additions & 0 deletions slinc-examples-native/src/add.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int add(int a,int b) {
return a + b;
}

int add_by_callback(int a, int (*f)(void)) {
int b = f();
return a + b;
}

char* add_str(char* a, char* b) {
int size = strlen(a) + strlen(b) + 1;
char *buf = malloc (size);
snprintf(buf, size, "%s%s", a, b);
return buf;
}
28 changes: 28 additions & 0 deletions slinc-examples/src/main/scala/fr/hammons/slinc/CallSharedLib.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import fr.hammons.slinc.runtime.given
import fr.hammons.slinc.types.*
import fr.hammons.slinc.*

import fr.hammons.slinc.annotations.NeedsResource

@NeedsResource("libadd0")
trait libadd derives FSet:
def add(a: CInt, b: CInt): CInt
def add_by_callback(a: CInt, f: Ptr[?]): CInt
def add_str(a: Ptr[Byte], f: Ptr[Byte]): Ptr[Byte]

@main def run =
val libadd = FSet.instance[libadd]
assert(libadd.add(21, 21) == 42)

val callback = Scope.global:
Ptr.upcall(() => 21)
assert(libadd.add_by_callback(21, callback) == 42)

val (hello, world) = ("Hello", "World")
val (a, b) = Scope.global:
(Ptr.copy(hello), Ptr.copy(world))

val c = libadd.add_str(a, b)
val result =
Ptr.copyIntoString(c)(hello.getBytes().length + world.getBytes().length + 1)
assert(result == hello + world)
13 changes: 13 additions & 0 deletions slinc-examples/src/main/scala/fr/hammons/slinc/CallStdLib.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import fr.hammons.slinc.runtime.given
import fr.hammons.slinc.types.*
import fr.hammons.slinc.*

case class div_t(quot: CInt, rem: CInt) derives Struct

trait MyLib derives FSet:
def div(numer: CInt, denom: CInt): div_t
val myLib = FSet.instance[MyLib]

@main def calc =
val div_t(quot, rem) = myLib.div(5, 2)
assert((quot, rem) == (2, 1), s"Unexpected (quot, rem): ($quot, $rem)")