aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakob Odersky <jakob@odersky.com>2017-07-03 20:08:36 -0700
committerJakob Odersky <jakob@odersky.com>2017-07-03 20:08:36 -0700
commit7dc655155019f25ae087f2599c82b59694f968d1 (patch)
tree1973e9ed8832f6665b2c89875fa9826fad3817fc
parent1aa2c485e0bd97fbd4db895978ddd98b7b6e30fa (diff)
downloadcbt-various-plugins.tar.gz
cbt-various-plugins.tar.bz2
cbt-various-plugins.zip
Add javah pluginvarious-plugins
-rw-r--r--plugins/javah/Javah.scala97
-rw-r--r--plugins/javah/build/build.scala9
-rw-r--r--stage2/plugins.scala1
3 files changed, 107 insertions, 0 deletions
diff --git a/plugins/javah/Javah.scala b/plugins/javah/Javah.scala
new file mode 100644
index 0000000..cc8aec1
--- /dev/null
+++ b/plugins/javah/Javah.scala
@@ -0,0 +1,97 @@
+package cbt
+
+import java.io.{ File, FileInputStream, Closeable }
+import java.nio.file._
+import scala.collection.JavaConverters._
+import scala.collection.mutable.{ HashSet }
+import scala.sys.process._
+
+import org.objectweb.asm.{ ClassReader, ClassVisitor, MethodVisitor, Opcodes }
+
+trait Javah extends BaseBuild {
+
+ def javah = Javah.apply(lib, println _).config(
+ (target / "include").toPath,
+ exportedClasspath.files ++ dependencyClasspath.files,
+ exportedClasspath.files
+ .flatMap(file => Files.walk(file.toPath).iterator().asScala.toSeq)
+ .toSet
+ .filter(Files.isRegularFile(_))
+ .flatMap(Javah.findNativeClasses)
+ )
+
+}
+
+object Javah {
+
+ case class apply(lib: Lib, log: (String) => Unit) {
+ case class config(target: Path, classpath: Seq[File], nativeClasses: Set[String]) {
+ def apply: Set[String] = {
+ val cp = classpath.mkString(sys.props("path.separator"))
+ if (!Files.exists(target)) {
+ log("creating file")
+ }
+ if (!nativeClasses.isEmpty) {
+ log(s"headers will be generated in $target")
+ }
+ for (clazz <- nativeClasses) yield {
+ log(s"generating header for $clazz")
+ val parts = Seq(
+ "javah",
+ "-d", target.toString,
+ "-classpath", cp,
+ clazz
+ )
+ val cmd = parts.mkString(" ")
+ Process(cmd).!!
+ }
+ }
+ }
+ }
+
+
+ private class NativeFinder extends ClassVisitor(Opcodes.ASM5) {
+
+ // classes found to contain at least one @native def
+ val _nativeClasses = new HashSet[String]
+ def nativeClasses = _nativeClasses.toSet
+
+ private var fullyQualifiedName: String = ""
+
+ override def visit(version: Int, access: Int, name: String, signature: String,
+ superName: String, interfaces: Array[String]): Unit = {
+ fullyQualifiedName = name.replaceAll("/", ".")
+ }
+
+ override def visitMethod(access: Int, name: String, desc: String,
+ signature: String, exceptions: Array[String]): MethodVisitor = {
+
+ val isNative = (access & Opcodes.ACC_NATIVE) != 0
+
+ if (isNative) {
+ _nativeClasses += fullyQualifiedName
+ }
+
+ null //return null, do not visit method further
+ }
+
+ }
+
+ /** Finds classes containing native implementations.
+ * @param classFile java class file from which classes are read
+ * @return all fully qualified names of classes that contain at least one member annotated
+ * with @native
+ */
+ def findNativeClasses(classFile: Path): Set[String] = {
+ val in = Files.newInputStream(classFile)
+ try {
+ val reader = new ClassReader(in)
+ val finder = new NativeFinder
+ reader.accept(finder, 0)
+ finder.nativeClasses
+ } finally {
+ in.close()
+ }
+ }
+
+}
diff --git a/plugins/javah/build/build.scala b/plugins/javah/build/build.scala
new file mode 100644
index 0000000..64e25eb
--- /dev/null
+++ b/plugins/javah/build/build.scala
@@ -0,0 +1,9 @@
+package javah_build
+
+import cbt._
+
+class Build(val context: Context) extends Plugin {
+ override def dependencies = super.dependencies ++ Resolver(mavenCentral).bind(
+ MavenDependency("org.ow2.asm", "asm", "5.0.4")
+ )
+}
diff --git a/stage2/plugins.scala b/stage2/plugins.scala
index ea1aa74..3efc1d7 100644
--- a/stage2/plugins.scala
+++ b/stage2/plugins.scala
@@ -7,6 +7,7 @@ class plugins( context: Context, scalaVersion: String ) {
),
None
)
+ final lazy val javah = plugin( "javah" )
final lazy val googleJavaFormat = plugin( "google-java-format" )
final lazy val proguard = plugin( "proguard" )
final lazy val sbtLayout = plugin( "sbt_layout" )