Skip to content

Commit

Permalink
Add support for Meson build tool (#147)
Browse files Browse the repository at this point in the history
  • Loading branch information
mihnea-s authored Jun 2, 2023
1 parent 72d5a8d commit ef56c2d
Show file tree
Hide file tree
Showing 16 changed files with 234 additions and 1 deletion.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ jobs:
with:
distribution: ${{ matrix.distribution }}
java-version: ${{ matrix.java }}
- run: python3 -m pip install meson ninja

- name: Check formatting
run: sbt scalafmtCheckAll
Expand Down
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,38 @@ nativeBuildTool := Cargo.make(Seq("--release", "--ignore-rust-version"))
nativeBuildTool := Cargo.make(Nil)
```

#### Meson

A regular `Meson` native project definition usually looks this following way:

```scala
lazy val native = project
// baseDirectory = <project_root>/native
.settings(nativeCompile / sourceDirectory := baseDirectory.value)
.enablePlugins(JniNative)
```

Source directory is set to `baseDirectory.value` since the `Meson` project structure is of the following shape:

```
├── meson.build
├── meson.options
├── src/
│ ├── library.c
```

By default, `Meson` build is launched with the `--buildtype=release` flag. It is possible to configure `Meson` by overriding the `nativeBuildTool` setting:

```scala
// default
nativeBuildTool := Meson.make(Seq("--buildtype=release"))
// extra flags passed
nativeBuildTool := Meson.make(Seq("--buildtype=release", "--fatal-meson-warnings"))
// no flags passed, debug mode
nativeBuildTool := Meson.make(Nil)
```

### JniPackage
| Enabled | Source |
|--------------------------------|---------------|
Expand Down
37 changes: 37 additions & 0 deletions plugin/src/main/resources/com/github/sbt/jni/templates/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
################################################################
# Minimal SBT-JNI Meson C/C++ Project #
# #
# All settings required by sbt-jni have been marked so, please #
# add/modify/remove settings to build your specific library. #
################################################################

# Define project and languages used
# (required by sbt-jni) please use semantic versioning
# Note: Java is required in the list of languages to link JNI
#
project('{{project}}', 'c', 'cpp', 'java', version: '0.1.0')

# Find JNI headers
java_dep = dependency('jni', include_type: 'system')

# Setup project name
# (required by sbt-jni) major version should always be appended to library name
#
major_version = meson.project_version().split('.')[0]
lib_name = '@0@@1@'.format(meson.project_name(), major_version)

# Setup installation targets
# (required by sbt-jni) major version should always be appended to library name
#
shared_library(lib_name,
sources: [
'library.c',
],
install : true,
include_directories : include_directories(
'.',
'include',
),
dependencies : [
java_dep,
])
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Note: Meson >= 1.1.0 Required
option('sbt', type : 'boolean', value : false, description : 'Set if invoked from sbt-jni')
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ trait BuildTool {
object BuildTool {
lazy val buildTools: Map[String, BuildTool] = Map(
CMake.name.toLowerCase -> CMake.release,
Cargo.name.toLowerCase -> Cargo.release
Cargo.name.toLowerCase -> Cargo.release,
Meson.name.toLowerCase -> Meson.release
)
}
76 changes: 76 additions & 0 deletions plugin/src/main/scala/com/github/sbt/jni/build/Meson.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.github.sbt.jni
package build

import sbt._
import sys.process._

class Meson(protected val configuration: Seq[String]) extends BuildTool with ConfigureMakeInstall {

override val name = Meson.name

override def detect(baseDirectory: File) = baseDirectory.list().contains("meson.build")

override protected def templateMappings = Seq(
"/com/github/sbt/jni/templates/meson.build" -> "meson.build",
"/com/github/sbt/jni/templates/meson.options" -> "meson.options"
)

override def getInstance(baseDir: File, buildDir: File, logger: Logger) = new Instance {

override def log = logger
override def baseDirectory = baseDir
override def buildDirectory = buildDir

def mesonProcess(args: String*): ProcessBuilder = Process("meson" +: args, buildDirectory)

lazy val mesonVersion = mesonProcess("--version").lineStream.head.replace('.', '_')

lazy val mesonBuildDir = buildDirectory / mesonVersion

override def configure(target: File) = {
mesonProcess(
Seq("setup", "--prefix", target.getAbsolutePath) ++ configuration ++ Seq(
mesonVersion.toString,
baseDirectory.getAbsolutePath
): _*
)
}

override def clean(): Unit = mesonProcess(
"compile",
"-C",
mesonBuildDir.getAbsolutePath,
"--clean"
).run(log)

override def make(): ProcessBuilder = mesonProcess(
"compile",
"-C",
mesonBuildDir.getAbsolutePath,
"--jobs",
parallelJobs.toString
)

override def install(): ProcessBuilder = mesonProcess(
"install",
"-C",
mesonBuildDir.getAbsolutePath
)
}

}

object Meson {
val name = "Meson"
val DEFAULT_CONFIGURATION = Seq("--buildtype=release", "-Dsbt=true")

/**
* Meson setup configuration arguments.
*/
def make(configuration: Seq[String] = DEFAULT_CONFIGURATION): BuildTool = new Meson(configuration)

/**
* Meson build tool, with the release build type.
*/
lazy val release: BuildTool = make()
}
1 change: 1 addition & 0 deletions plugin/src/sbt-test/sbt-jni/simple-meson/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Very basic test using Meson.
12 changes: 12 additions & 0 deletions plugin/src/sbt-test/sbt-jni/simple-meson/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
ivyLoggingLevel := UpdateLogging.Quiet

lazy val root = (project in file(".")).aggregate(core, native)

lazy val core = project
.settings(libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.15" % Test)
.settings(javah / target := (native / nativeCompile / sourceDirectory).value / "include")
.dependsOn(native % Runtime)

lazy val native = project
.settings(nativeCompile / sourceDirectory := sourceDirectory.value)
.enablePlugins(JniNative)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package simple

import com.github.sbt.jni.nativeLoader

@nativeLoader("demo0")
object Library {

@native def say(message: String): Int

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package simple

object Main {

def main(args: Array[String]): Unit = {
val result = Library.say("hello world")
assert(result == 42)
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package simple

import org.scalatest.flatspec._

class SimpleSpec extends AnyFlatSpec {

"Calling native methods in tests" should "work" in {
assert(Library.say("hello") == 42)
}

}
16 changes: 16 additions & 0 deletions plugin/src/sbt-test/sbt-jni/simple-meson/native/src/library.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#include <stdio.h>
#include "simple_Library_00024.h"

/*
* Class: simple_Library__
* Method: say
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_simple_Library_00024_say
(JNIEnv *env, jobject clazz, jstring message) {
const char* msg = (*env)->GetStringUTFChars(env, message, 0);
fprintf(stdout, "Printing from native library: %s\n", msg);
fflush(stdout);
(*env)->ReleaseStringUTFChars(env, message, msg);
return 42;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import sbt._
import sbt.Keys._

object ScriptedHelper extends AutoPlugin {

override def requires = empty
override def trigger = allRequirements

override def projectSettings = Seq(
scalacOptions ++= Seq("-feature", "-deprecation"),
crossScalaVersions := Seq("2.13.10", "2.12.17"),
scalaVersion := crossScalaVersions.value.head
)

}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.8.2
3 changes: 3 additions & 0 deletions plugin/src/sbt-test/sbt-jni/simple-meson/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
ivyLoggingLevel := UpdateLogging.Quiet

addSbtPlugin("com.github.sbt" % "sbt-jni" % System.getProperty("plugin.version"))
5 changes: 5 additions & 0 deletions plugin/src/sbt-test/sbt-jni/simple-meson/test
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
> +javah
$ exists native/src/include/simple_Library_00024.h
> nativeInit meson demo
> +test
> +core/run

0 comments on commit ef56c2d

Please sign in to comment.