diff --git a/README.markdown b/README.markdown index 6599bde..ef6a175 100644 --- a/README.markdown +++ b/README.markdown @@ -42,8 +42,8 @@ you can change the target platform for your build straight from your command lin sbt compile -Dsbt.javacpp.platform="android-arm android-x86" ``` -In case you want to select a different javacpp version, add the following line in your `project/plugins.sbt`: +In case you want to select a different javacpp version: ```scala -libraryDependencies += "org.bytedeco" % "javacpp" % "1.5.1" +javaCppVersion := "1.4.3" ``` diff --git a/build.sbt b/build.sbt index 21e13a6..04c96cc 100644 --- a/build.sbt +++ b/build.sbt @@ -23,8 +23,6 @@ publishArtifact in Test := false pomIncludeRepository := { _ => false } -libraryDependencies += "org.bytedeco" % "javacpp" % "1.4.3" - scalacOptions ++= Seq("-unchecked", "-deprecation", "-feature", "-Xlint", "-Xlog-free-terms") publishTo := { diff --git a/src/main/scala/org/bytedeco/sbt/javacpp/JavaCppPlugin.scala b/src/main/scala/org/bytedeco/sbt/javacpp/JavaCppPlugin.scala index 5734e30..1e19ba0 100644 --- a/src/main/scala/org/bytedeco/sbt/javacpp/JavaCppPlugin.scala +++ b/src/main/scala/org/bytedeco/sbt/javacpp/JavaCppPlugin.scala @@ -1,10 +1,12 @@ package org.bytedeco.sbt.javacpp -import org.bytedeco.javacpp.tools.Builder +import java.net.URLClassLoader +import java.util.Properties + import sbt.Keys._ import sbt._ -import scala.language.postfixOps +import scala.language.{ postfixOps, reflectiveCalls } import scala.util.Try object JavaCppPlugin extends AutoPlugin { @@ -14,11 +16,11 @@ object JavaCppPlugin extends AutoPlugin { Seq( autoCompilerPlugins := true, javaCppClasses := Seq.empty, - javaCppCustomization := identity, + javaCppCustomizer := identity, javaCppPlatform := Platform.current, javaCppPresetLibs := Seq.empty, libraryDependencies += { - "org.bytedeco" % "javacpp" % Versions.javaCppVersion jar + "org.bytedeco" % "javacpp" % javaCppVersion.value jar }, javaCppPresetDependencies, javaCppBuild := javaCpp.value, @@ -26,18 +28,48 @@ object JavaCppPlugin extends AutoPlugin { } object Versions { - val javaCppVersion = { - val javaCppJar = classOf[Builder].getProtectionDomain.getCodeSource.getLocation.getFile - "(?<=javacpp-)(.*)(?=\\.jar)".r.findFirstIn(javaCppJar).get - } + val javaCppVersion = "1.4.3" } object autoImport { - val javaCppCustomization = SettingKey[Builder => Builder]("javaCppCustomization", "Customize the Java CPP builder") + type JavaCppBuilder = { + def classPaths(classPath: String): this.type + def classPaths(classPath: Array[String]): this.type + def encoding(encoding: String): this.type + def outputDirectory(outputDirectory: String): this.type + def outputDirectory(outputDirectory: File): this.type + def clean(clean: Boolean): this.type + def generate(generate: Boolean): this.type + def compile(compile: Boolean): this.type + def deleteJniFiles(deleteJniFiles: Boolean): this.type + def header(header: Boolean): this.type + def copyLibs(copyLibs: Boolean): this.type + def copyResources(copyResources: Boolean): this.type + def outputName(outputName: String): this.type + def jarPrefix(jarPrefix: String): this.type + def properties(platform: String): this.type + def properties(properties: Properties): this.type + def propertyFile(propertyFile: String): this.type + def propertyFile(propertyFile: File): this.type + def property(keyValue: String): this.type + def property(key: String, value: String): this.type + def classesOrPackages(classes: Array[String]): this.type + def buildCommand(buildCommand: Array[String]): this.type + def workingDirectory(workingDirectory: String): this.type + def workingDirectory(workingDirectory: File): this.type + def environmentVariables(environmentVariables: java.util.Map[String, String]): this.type + def compilerOptions(options: Array[String]): this.type + def build(): Array[File] + def printHelp(): Unit + def getClass(): Class[_] + } + + val javaCppBuild = TaskKey[Seq[File]]("javaCppBuild", "Build Java CPP products") + val javaCppClasses = SettingKey[Seq[String]]("javaCppClasses", "A list of Java CPP classes. Suffix of '.*' ('.**') can be used to match all classes under the specified package (and any subpackages)") + val javaCppCustomizer = SettingKey[JavaCppBuilder => JavaCppBuilder]("javaCppCustomization", "Customize the Java CPP builder") val javaCppPlatform = SettingKey[Seq[String]]("javaCppPlatform", """The platform that you want to compile for (defaults to the platform of the current computer). You can also set this via the "sbt.javacpp.platform" System Property """) val javaCppPresetLibs = SettingKey[Seq[(String, String)]]("javaCppPresetLibs", "List of additional JavaCPP presets that you would wish to bind lazily, defaults to an empty list") - val javaCppClasses = SettingKey[Seq[String]]("javaCppClasses", "A list of Java CPP classes. Suffix of '.*' ('.**') can be used to match all classes under the specified package (and any subpackages)") - val javaCppBuild = TaskKey[Seq[File]]("javaCppBuild", "Build Java CPP products") + val javaCppVersion = SettingKey[String]("javaCppVersion", s"Version of Java CPP that you want to use, defaults to ${Versions.javaCppVersion}") } override def requires: Plugins = plugins.JvmPlugin @@ -83,20 +115,24 @@ object JavaCppPlugin extends AutoPlugin { private def javaCpp = Def.task { import autoImport._ val classes = javaCppClasses.value - val customization = javaCppCustomization.value + val customizer = javaCppCustomizer.value val dependencies = (dependencyClasspath in Compile).value val output = (classDirectory in Compile).value val _ = (compile in Compile).value + val cl = new URLClassLoader(dependencies.map(_.data.toURI.toURL).toArray, null) + val builder = cl.loadClass("org.bytedeco.javacpp.tools.Builder").newInstance().asInstanceOf[JavaCppBuilder] + val thread = Thread.currentThread() val saved = thread.getContextClassLoader - thread.setContextClassLoader(classOf[Builder].getClassLoader) + thread.setContextClassLoader(cl) + try { - customization( - new Builder() + customizer( + builder .classPaths(output.getAbsolutePath) - .classPaths(dependencies.map(_.data.absolutePath): _*) - .classesOrPackages(classes: _*)).build() + .classPaths(dependencies.map(_.data.absolutePath).toArray) + .classesOrPackages(classes.toArray)).build() } finally { thread.setContextClassLoader(saved) } diff --git a/src/main/scala/org/bytedeco/sbt/javacpp/Platform.scala b/src/main/scala/org/bytedeco/sbt/javacpp/Platform.scala index bfbd0a0..3536421 100644 --- a/src/main/scala/org/bytedeco/sbt/javacpp/Platform.scala +++ b/src/main/scala/org/bytedeco/sbt/javacpp/Platform.scala @@ -1,11 +1,8 @@ package org.bytedeco.sbt.javacpp -import org.bytedeco.javacpp.Loader - /** * Created by Lloyd on 2/22/16. */ - object Platform { private val platformOverridePropertyKey: String = "sbt.javacpp.platform" @@ -20,7 +17,28 @@ object Platform { */ val current: Seq[String] = sys.props.get(platformOverridePropertyKey) match { case Some(platform) if platform.trim().nonEmpty => platform.split(' ') - case _ => Seq(Loader.getPlatform) + case _ => + val jvmName = System.getProperty("java.vm.name", "").toLowerCase + var osName = System.getProperty("os.name", "").toLowerCase + var osArch = System.getProperty("os.arch", "").toLowerCase + val abiType = System.getProperty("sun.arch.abi", "").toLowerCase + val libPath = System.getProperty("sun.boot.library.path", "").toLowerCase + if (jvmName.startsWith("dalvik") && osName.startsWith("linux")) { + osName = "android" + } else if (jvmName.startsWith("robovm") && osName.startsWith("darwin")) { + osName = "ios" + osArch = "arm" + } else if (osName.startsWith("mac os x") || osName.startsWith("darwin")) { + osName = "macosx" + } else { + val spaceIndex = osName.indexOf(' ') + if (spaceIndex > 0) osName = osName.substring(0, spaceIndex) + } + if (osArch == "i386" || osArch == "i486" || osArch == "i586" || osArch == "i686") osArch = "x86" + else if (osArch == "amd64" || osArch == "x86-64" || osArch == "x64") osArch = "x86_64" + else if (osArch.startsWith("aarch64") || osArch.startsWith("armv8") || osArch.startsWith("arm64")) osArch = "arm64" + else if (osArch.startsWith("arm") && ((abiType == "gnueabihf") || libPath.contains("openjdk-armhf"))) osArch = "armhf" + else if (osArch.startsWith("arm")) osArch = "arm" + Seq(osName + "-" + osArch) } - -} \ No newline at end of file +} diff --git a/src/sbt-test/sbt-javacpp/simple/build.sbt b/src/sbt-test/sbt-javacpp/simple/build.sbt index df26c1c..ad57313 100644 --- a/src/sbt-test/sbt-javacpp/simple/build.sbt +++ b/src/sbt-test/sbt-javacpp/simple/build.sbt @@ -4,4 +4,8 @@ scalaVersion := "2.11.12" javaCppClasses := Seq("javacpp.*") +javaCppVersion := "1.5.1" + +javaCppCustomizer := { builder => builder.compilerOptions(Array("-std=c++11")) } + libraryDependencies += "org.scalatest" %% "scalatest" % "3.0.8" % Test diff --git a/src/sbt-test/sbt-javacpp/simple/project/plugins.sbt b/src/sbt-test/sbt-javacpp/simple/project/plugins.sbt index d82a7fe..fba3ef8 100644 --- a/src/sbt-test/sbt-javacpp/simple/project/plugins.sbt +++ b/src/sbt-test/sbt-javacpp/simple/project/plugins.sbt @@ -5,5 +5,3 @@ |Specify this property using the scriptedLaunchOpts -D.""".stripMargin) else addSbtPlugin("org.bytedeco" % "sbt-javacpp" % pluginVersion) } - -libraryDependencies += "org.bytedeco" % "javacpp" % "1.5.1"