aboutsummaryrefslogtreecommitdiff
path: root/jni-plugin/src/main/scala
diff options
context:
space:
mode:
authorJakob Odersky <jodersky@gmail.com>2016-01-17 17:18:13 -0800
committerJakob Odersky <jodersky@gmail.com>2016-01-17 17:18:13 -0800
commit2b343f73fc5b7605b22af41c675c2afc86d2a447 (patch)
tree51087a72109c927c7be245367458bffb3ec48ae7 /jni-plugin/src/main/scala
parent1cdbc2d2e04c7ab34d2e5af07567b37c60be571f (diff)
downloadsbt-jni-2b343f73fc5b7605b22af41c675c2afc86d2a447.tar.gz
sbt-jni-2b343f73fc5b7605b22af41c675c2afc86d2a447.tar.bz2
sbt-jni-2b343f73fc5b7605b22af41c675c2afc86d2a447.zip
Refactor to multi-plugin build
Diffstat (limited to 'jni-plugin/src/main/scala')
-rw-r--r--jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniPackager.scala110
-rw-r--r--jni-plugin/src/main/scala/ch/jodersky/sbt/jni/build/Autotools.scala5
-rw-r--r--jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniJavah.scala (renamed from jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniJvm.scala)26
-rw-r--r--jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniLoading.scala28
-rw-r--r--jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniNative.scala (renamed from jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniPlugin.scala)19
-rw-r--r--jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniNative.scala.old (renamed from jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniNative.scala)0
-rw-r--r--jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniPackage.scala.old183
-rw-r--r--jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniPackaging.scala113
8 files changed, 346 insertions, 138 deletions
diff --git a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniPackager.scala b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniPackager.scala
deleted file mode 100644
index 56322ad..0000000
--- a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniPackager.scala
+++ /dev/null
@@ -1,110 +0,0 @@
-package ch.jodersky.sbt.jni
-
-import build._
-import ch.jodersky.jni.{NativeLoader, Platform}
-import sbt._
-import sbt.Keys._
-
-object JniPackager extends AutoPlugin {
-
- override def requires = Jni
- override def trigger = allRequirements
-
- object autoImport {
-
- //Main task, inspect this first
- val packageNative = taskKey[File]("Packages native libraries in a jar.")
-
- val nativeLibraryPath = settingKey[String](
- "String that is prepended to the path of a native library when packaged.")
-
- val enableNativeCompilation = settingKey[Boolean](
- "Determines if native compilation is enabled in a scoped key (typically for packaging).")
-
- val unmanagedNativeDirectories = settingKey[Seq[File]](
- """|Unmanaged directories containing native libraries. The libraries must be regular files
- |contained in a subdirectory corresponding to a platform.""".stripMargin)
-
- val unmanagedNativeLibraries = taskKey[Map[Platform, File]]("")
-
- }
- import autoImport._
- import Jni.autoImport._
-
- lazy val settings: Seq[Setting[_]] = Seq(
-
- nativeLibraryPath := {
- val orgPath = organization.value.replaceAll("\\.", "/")
- s"/${orgPath}/${name.value}/native"
- },
-
- //Make NativeLoader available to project
- libraryDependencies += "ch.jodersky" %% "jni-library" % Version.PluginVersion,
-
- name in packageNative := {
- name.value + "-native-" + version.value + ".jar"
- },
-
- enableNativeCompilation in packageNative := true,
-
- unmanagedNativeDirectories := Seq(baseDirectory.value / "lib_native"),
-
- unmanagedNativeLibraries := {
- val dirs: Seq[File] = unmanagedNativeDirectories.value
- val seq: Seq[(Platform, File)] = for (
- dir <- dirs;
- platformDir <- dir.listFiles();
- if platformDir.isDirectory;
- platform = Platform.fromId(platformDir.name);
- library <- platformDir.listFiles();
- if library.isFile
- ) yield {
- platform -> library.getCanonicalFile()
- }
-
- seq.toMap
- },
-
- packageNative := {
- val log = streams.value.log
-
- val unmanagedMappings: Seq[(File, String)] = {
- unmanagedNativeLibraries.value.toSeq.map{ case (platform, file) =>
- file -> NativeLoader.fullLibraryPath(
- (nativeLibraryPath in Compile).value,
- platform)
- }
- }
-
- val enableManaged = (enableNativeCompilation in packageNative).value
-
- val managedMappings: Seq[(File, String)] = if (enableManaged) {
- val library: File = (nativeCompile in Compile).value
- val path: String = NativeLoader.fullLibraryPath(
- (nativeLibraryPath in Compile).value,
- (nativePlatform in Compile).value
- )
- Seq(library -> path)
- } else {
- Seq()
- }
-
- val mappings = unmanagedMappings ++ managedMappings
- val manifest = new java.util.jar.Manifest
- val jar: File = (target in nativeCompile).value / (name in packageNative).value
-
- Package.makeJar(mappings, jar, manifest, log)
- jar
- },
-
- //Add native jar to runtime classpath. Note that it is not added as a resource (this would cause
- //the native library to included in the main jar).
- unmanagedClasspath in Runtime += Attributed.blank(packageNative.value),
-
- fork in run := true //fork new JVM, since native libraries can only be loaded once
-
- )
- override lazy val projectSettings = (settings)
-
-
-}
diff --git a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/build/Autotools.scala b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/build/Autotools.scala
index c1de1ea..960e66e 100644
--- a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/build/Autotools.scala
+++ b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/build/Autotools.scala
@@ -16,11 +16,12 @@ object Autotools extends BuildTool {
val targetPath = target.getAbsolutePath
Process(
- s"${base.getAbsolutePath}/configure " +
+ s"${base.getAbsolutePath}/configure " +
s"--prefix=$targetPath " +
s"--libdir=$targetPath " +
"--disable-versioned-lib",
- build)
+ build
+ )
}
}
diff --git a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniJvm.scala b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniJavah.scala
index 789eabf..63e5b23 100644
--- a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniJvm.scala
+++ b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniJavah.scala
@@ -1,12 +1,15 @@
package ch.jodersky.sbt.jni
+package plugins
import sbt._
import sbt.Keys._
import util.ByteCode
-object JniJvm extends AutoPlugin {
+/** Adds `javah` header-generation functionality to projects. */
+object JniJavah extends AutoPlugin {
override def requires = plugins.JvmPlugin
+ override def trigger = allRequirements
object autoImport {
@@ -34,22 +37,17 @@ object JniJvm extends AutoPlugin {
target in javah := target.value / "include",
+ fullClasspath in javah := fullClasspath.value,
+
javah := {
val out = (target in javah).value
- val jcp: Seq[File] = {
- (compile in Compile).value
- //FIXME: a cleaner approach that would also call compile would
- //be to use `fullClasspath`, this however results in generating resources
- //which in turn might require header files generated by javah. Hence
- //to avoid a cyclic dependency `compile` is called first and the
- //class directory returned.
- Seq((classDirectory in Compile).value)
- }
+ val jcp: Seq[File] = (fullClasspath in javah).value.map(_.data)
val cp = jcp.mkString(sys.props("path.separator"))
val log = streams.value.log
val classes = (javahClasses in javah).value
+ log.info("Headers will be generated to " + out.getAbsolutePath)
for (clazz <- classes) {
log.info("Generating header for " + clazz + "...")
val parts = Seq(
@@ -66,12 +64,6 @@ object JniJvm extends AutoPlugin {
}
)
- lazy val clientSettings = Seq(
- //enable enhanced native library extraction
- libraryDependencies += "ch.jodersky" %% "jni-library" % Version.PluginVersion,
- fork in run := true //fork new JVM, since native libraries can only be loaded once
- )
-
- override lazy val projectSettings = mainSettings ++ clientSettings
+ override lazy val projectSettings = inConfig(Compile)(mainSettings)
}
diff --git a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniLoading.scala b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniLoading.scala
new file mode 100644
index 0000000..599bfa1
--- /dev/null
+++ b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniLoading.scala
@@ -0,0 +1,28 @@
+package ch.jodersky.sbt.jni
+package plugins
+
+import sbt._
+import sbt.Keys._
+import util.ByteCode
+
+/**
+ * Enables loading native libraries from the classpath, typically created
+ * from a project using JniPackaging.
+ */
+object JniLoading extends AutoPlugin {
+
+ override def requires = plugins.JvmPlugin
+
+ lazy val settings = Seq(
+
+ //enable enhanced native library extraction
+ libraryDependencies += "ch.jodersky" %% "jni-library" % Version.PluginVersion,
+
+ //fork new JVM, since native libraries can only be loaded once
+ fork in run := true
+
+ )
+
+ override lazy val projectSettings = settings
+
+}
diff --git a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniPlugin.scala b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniNative.scala
index 2b76b7a..2ac179d 100644
--- a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniPlugin.scala
+++ b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniNative.scala
@@ -1,13 +1,13 @@
package ch.jodersky.sbt.jni
+package plugins
import build._
import ch.jodersky.jni.{NativeLoader, Platform}
import sbt._
import sbt.Keys._
-object Jni extends AutoPlugin {
-
- override def requires = plugins.JvmPlugin
+/** Wraps a native build system in sbt tasks. */
+object JniNative extends AutoPlugin {
object autoImport {
@@ -17,17 +17,18 @@ object Jni extends AutoPlugin {
val nativePlatform = settingKey[Platform]("Platform of the system this build is running on.")
val nativeBuildTools = taskKey[Seq[BuildTool]](
- "A collection of build tools that are tested to determine the current build environment")
+ "A collection of build tools that are tested to determine the current build environment"
+ )
val nativeBuildTool = taskKey[BuildTool](
- "The build tool to be used when building a native library.")
-
+ "The build tool to be used when building a native library."
+ )
}
import autoImport._
- lazy val mainSettings: Seq[Setting[_]] = Seq(
+ lazy val settings: Seq[Setting[_]] = Seq(
- nativePlatform := Platform.current.getOrElse{
+ nativePlatform := Platform.current.getOrElse {
sLog.value.warn("Warning: cannot determine platform! It will be set to 'unknown'.")
Platform.Unknown
},
@@ -95,5 +96,5 @@ object Jni extends AutoPlugin {
)
- override lazy val projectSettings = inConfig(Compile)(mainSettings)
+ override lazy val projectSettings = inConfig(Compile)(settings)
}
diff --git a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniNative.scala b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniNative.scala.old
index 9cfa2af..9cfa2af 100644
--- a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniNative.scala
+++ b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniNative.scala.old
diff --git a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniPackage.scala.old b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniPackage.scala.old
new file mode 100644
index 0000000..60980f5
--- /dev/null
+++ b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniPackage.scala.old
@@ -0,0 +1,183 @@
+package ch.jodersky.sbt.jni
+
+import build._
+import ch.jodersky.jni.{NativeLoader, Platform}
+import sbt._
+import sbt.Keys._
+
+object JniPackager extends AutoPlugin {
+
+ override def requires = Jni
+ override def trigger = allRequirements
+
+ object autoImport {
+
+ //Main task, inspect this first
+ //val packageNative = taskKey[File]("Packages native libraries in a jar.")
+
+ //val packageNativeMappings = taskKey[Seq[(File, String)]]("")
+
+ val nativeLibraryPath = settingKey[String](
+ "String that is prepended to the path of a native library when packaged.")
+
+ val enableNativeCompilation = settingKey[Boolean](
+ "Determines if native compilation is enabled in a scoped key (typically for packaging).")
+
+ val unmanagedNativeDirectories = settingKey[Seq[File]](
+ """|Unmanaged directories containing native libraries. The libraries must be regular files
+ |contained in a subdirectory corresponding to a platform.""".stripMargin)
+
+ val unmanagedNativeLibraries = taskKey[Map[Platform, File]]("")
+
+ val managedNativeLibraries = taskKey[Map[Platform, File]]("")
+
+ }
+ import autoImport._
+ import Jni.autoImport._
+
+ lazy val settings: Seq[Setting[_]] = Seq(
+
+ nativeLibraryPath := {
+ val orgPath = organization.value.replaceAll("\\.", "/")
+ s"/${orgPath}/${name.value}/native"
+ },
+
+ //Make NativeLoader available to project
+ libraryDependencies += "ch.jodersky" %% "jni-library" % Version.PluginVersion,
+
+ name in packageNative := {
+ name.value + "-native-" + version.value + ".jar"
+ },
+
+ enableNativeCompilation := true,
+
+ unmanagedNativeDirectories := Seq(baseDirectory.value / "lib_native"),
+
+ unmanagedNativeLibraries := {
+ val dirs: Seq[File] = unmanagedNativeDirectories.value
+ val seq: Seq[(Platform, File)] = for (
+ dir <- dirs;
+ platformDir <- dir.listFiles();
+ if platformDir.isDirectory;
+ platform = Platform.fromId(platformDir.name);
+ library <- platformDir.listFiles();
+ if library.isFile
+ ) yield {
+ platform -> library.getCanonicalFile()
+ }
+
+ seq.toMap
+ },
+
+ managedNativeLibraries := Def.taskDyn[Map[Platform, File]]{
+ val enableManaged = (enableNativeCompilation).value
+ if (enableManaged) Def.task {
+ val library: File = (nativeCompile in Compile).value
+ val platform = (nativePlatform in Compile).value
+ Map(platform -> library)
+ } else Def.task{
+ Map()
+ }
+ }.value,
+
+ resourceGenerators in Compile += Def.task {
+
+ val libraries: Seq[(Patform, File)] = (managedNativeLibraries.value ++ unmanagedNativeLibraries.value).toSeq
+
+ val resources: Seq[File] = for ((plat, file) <- libraries) yield {
+
+ //native library as a managed resource file
+ val resource = (resourceManaged in Compile).value /
+ NativeLoader.fullLibraryPath(
+ (nativeLibraryPath).value,
+ plat)
+
+ //copy native library to a managed resource (so it can also be loaded when not packaged as a jar)
+ IO.copyFile(file, resource)
+ resource
+ }
+ resources
+ }.taskValue,
+
+ //don't add scala version to native jars
+ crossPaths := false
+
+ )
+
+ override lazy val projectSettings = settings
+ /*
+ name in packageNative := name,
+
+
+ //this is file name of the artifact
+ artifactName in packageNative := { (sv: ScalaVersion, module: ModuleID, artifact: Artifact) =>
+ artifact.name + "-native." + module.revision + "." + artifact.extension
+ }
+
+ packageNative := {
+ val log = streams.value.log
+
+ val mappings: Seq[(File, String)] = {
+ val libs = unmanagedNativeLibraries.value.toSeq ++ managedNativeLibraries.value.toSeq
+ libs.map{ case (platform, file) =>
+ file -> NativeLoader.fullLibraryPath(
+ (nativeLibraryPath in Compile).value,
+ platform)
+ }
+ }
+
+ val manifest = new java.util.jar.Manifest
+ val namer = (artifactName in packageNative).value
+ val jar: File = (target in nativeCompile).value / namer(
+ scalaVersion,
+
+ (artifactName in packageNative).value
+ )
+
+ Package.makeJar(mappings, jar, manifest, log)
+ jar
+ },
+ */
+
+ //Add native jar to runtime classpath. Note that it is not added as a resource (this would cause
+ //the native library to included in the main jar).
+ //unmanagedClasspath in Runtime += Attributed.blank(packageNative.value),
+
+ //Fork new JVM when running locally, since native libraries can only be loaded once
+ //fork in run := true
+
+ /*
+ override lazy val projectSettings =
+ Defaults.packageTaskSettings(packageNative, packageNativeMappings) ++
+ addArtifact(artifact in packageNative, packageNative) ++
+ inConfig(Compile)(settings) ++ Seq(
+
+ packageNativeMappings := {
+ val libs = (unmanagedNativeLibraries in Compile).value.toSeq ++
+ (managedNativeLibraries in Compile).value.toSeq
+ libs.map{ case (platform, file) =>
+ file -> NativeLoader.fullLibraryPath(
+ (nativeLibraryPath in Compile).value,
+ platform)
+ }
+ },
+
+ artifactClassifier in packageNative := Some("native"),
+
+ //this is file name of the artifact
+ artifactName := { (sv: ScalaVersion, module: ModuleID, artifact: Artifact) =>
+ artifact.name + "-foso" + module.revision + "." + artifact.extension
+ },
+
+ artifact in packageNative := {
+ Artifact("foo", "jar", "jar", Some("native"), Nil, None, Map("platform" -> "all"))
+ },
+
+ crossVersion in packageNative := CrossVersion.Disabled
+// projectID in packageNative := { projectID.value.copy(crossVersion = CrossVersion.Disabled) }
+
+
+ )
+ */
+
+}
diff --git a/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniPackaging.scala b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniPackaging.scala
new file mode 100644
index 0000000..6014086
--- /dev/null
+++ b/jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniPackaging.scala
@@ -0,0 +1,113 @@
+package ch.jodersky.sbt.jni
+package plugins
+
+import ch.jodersky.jni._
+import sbt._
+import sbt.Keys._
+
+/** Packages libraries built with JniNative. */
+object JniPackaging extends AutoPlugin {
+
+ //JvmPlugin is required or else resource generators will be overriden
+ override def requires = JniNative && plugins.JvmPlugin
+ override def trigger = allRequirements
+
+ object autoImport {
+
+ val nativeLibraryPath = settingKey[String](
+ "String that is prepended to the path of a native library when packaged. This value should be " +
+ "passed to `NativeLoader.load()`"
+ )
+
+ val enableNativeCompilation = settingKey[Boolean](
+ "Determines if native compilation is enabled. If disabled, only pre-compiled libraries in " +
+ "`unmanagedNativeDirectories` will be packaged."
+ )
+
+ val unmanagedNativeDirectories = settingKey[Seq[File]](
+ "Unmanaged directories containing native libraries. The libraries must be regular files " +
+ "contained in a subdirectory corresponding to a platform. For example " +
+ "`<unamagedNativeDirectory>/x86_64-linux/libfoo.so` is an unmanaged library for machines having " +
+ "the x86_64 architecture and running the Linux kernel."
+ )
+
+ val unmanagedNativeLibraries = taskKey[Map[Platform, File]](
+ "Reads `unmanagedNativeDirectories` and maps platforms to library files specified theirin."
+ )
+
+ val managedNativeLibraries = taskKey[Map[Platform, File]](
+ "Maps locally built, platform-dependant libraries."
+ )
+
+ }
+ import autoImport._
+ import JniNative.autoImport._
+
+ lazy val settings: Seq[Setting[_]] = Seq(
+
+ nativeLibraryPath := {
+ val orgPath = organization.value.replaceAll("\\.", "/")
+ s"/${orgPath}/${name.value}/native"
+ },
+
+ enableNativeCompilation := true,
+
+ unmanagedNativeDirectories := Seq(baseDirectory.value / "lib_native"),
+
+ unmanagedNativeLibraries := {
+ val dirs: Seq[File] = unmanagedNativeDirectories.value
+ val seq: Seq[(Platform, File)] = for (
+ dir <- dirs;
+ if (dir.exists && dir.isDirectory);
+ platformDir <- dir.listFiles();
+ if platformDir.isDirectory;
+ platform = Platform.fromId(platformDir.name);
+ library <- platformDir.listFiles();
+ if library.isFile
+ ) yield {
+ platform -> library.getCanonicalFile()
+ }
+
+ seq.toMap
+ },
+
+ managedNativeLibraries := Def.taskDyn[Map[Platform, File]] {
+ val enableManaged = (enableNativeCompilation).value
+ if (enableManaged) Def.task {
+ val library: File = nativeCompile.value
+ val platform = nativePlatform.value
+ Map(platform -> library)
+ }
+ else Def.task {
+ Map()
+ }
+ }.value,
+
+ resourceGenerators += Def.task {
+
+ val libraries: Seq[(Platform, File)] = (managedNativeLibraries.value ++ unmanagedNativeLibraries.value).toSeq
+
+ val resources: Seq[File] = for ((plat, file) <- libraries) yield {
+
+ //native library as a managed resource file
+ val resource = resourceManaged.value /
+ NativeLoader.fullLibraryPath(
+ (nativeLibraryPath).value,
+ plat
+ )
+
+ //copy native library to a managed resource (so it can also be loaded when not packaged as a jar)
+ IO.copyFile(file, resource)
+ resource
+ }
+ resources
+ }.taskValue,
+
+ //don't add scala version to native jars
+ crossPaths in Global := false
+
+ )
+
+ override lazy val projectSettings = inConfig(Compile)(settings)
+
+}