diff options
author | Jakob Odersky <jodersky@gmail.com> | 2016-01-17 17:18:13 -0800 |
---|---|---|
committer | Jakob Odersky <jodersky@gmail.com> | 2016-01-17 17:18:13 -0800 |
commit | 2b343f73fc5b7605b22af41c675c2afc86d2a447 (patch) | |
tree | 51087a72109c927c7be245367458bffb3ec48ae7 /jni-plugin/src/main/scala/ch | |
parent | 1cdbc2d2e04c7ab34d2e5af07567b37c60be571f (diff) | |
download | sbt-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/ch')
-rw-r--r-- | jni-plugin/src/main/scala/ch/jodersky/sbt/jni/JniPackager.scala | 110 | ||||
-rw-r--r-- | jni-plugin/src/main/scala/ch/jodersky/sbt/jni/build/Autotools.scala | 5 | ||||
-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.scala | 28 | ||||
-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.old | 183 | ||||
-rw-r--r-- | jni-plugin/src/main/scala/ch/jodersky/sbt/jni/plugins/JniPackaging.scala | 113 |
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) + +} |