From c2e05a185dcb230cdd267fb3feedafd7416fdb45 Mon Sep 17 00:00:00 2001 From: thirstycrow <5451vs5451@gmail.com> Date: Thu, 24 Oct 2019 20:01:27 +0800 Subject: [PATCH] Implement the build task using reflection to remove javacpp library as a dependency of the plugin --- README.markdown | 4 +- build.sbt | 2 - .../bytedeco/sbt/javacpp/JavaCppPlugin.scala | 72 ++++++++++++++----- .../org/bytedeco/sbt/javacpp/Platform.scala | 30 ++++++-- src/sbt-test/sbt-javacpp/simple/build.sbt | 4 ++ .../sbt-javacpp/simple/project/plugins.sbt | 2 - 6 files changed, 84 insertions(+), 30 deletions(-) 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..af15040 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,12 @@ object JavaCppPlugin extends AutoPlugin { Seq( autoCompilerPlugins := true, javaCppClasses := Seq.empty, - javaCppCustomization := identity, + javaCppCustomizer := identity, javaCppPlatform := Platform.current, javaCppPresetLibs := Seq.empty, + javaCppVersion := Versions.javaCppVersion, libraryDependencies += { - "org.bytedeco" % "javacpp" % Versions.javaCppVersion jar + "org.bytedeco" % "javacpp" % javaCppVersion.value jar }, javaCppPresetDependencies, javaCppBuild := javaCpp.value, @@ -26,18 +29,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 @@ -47,7 +80,7 @@ object JavaCppPlugin extends AutoPlugin { private def javaCppPresetDependencies: Def.Setting[Seq[ModuleID]] = { import autoImport._ libraryDependencies ++= { - lazy val cppPresetVersion = buildPresetVersion(Versions.javaCppVersion) + lazy val cppPresetVersion = buildPresetVersion(javaCppVersion.value) javaCppPresetLibs.value.flatMap { case (libName, libVersion) => val generic = "org.bytedeco.javacpp-presets" % libName % s"$libVersion-$cppPresetVersion" classifier "" @@ -83,20 +116,23 @@ 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 thread = Thread.currentThread() + thread.setContextClassLoader(cl) + val builder = cl.loadClass("org.bytedeco.javacpp.tools.Builder").newInstance().asInstanceOf[JavaCppBuilder] val saved = thread.getContextClassLoader - thread.setContextClassLoader(classOf[Builder].getClassLoader) + 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"