diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/DependencyHolder.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/DependencyHolder.kt index bf88494a..2103bdc1 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/DependencyHolder.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/DependencyHolder.kt @@ -14,6 +14,7 @@ interface IDependencyHolder { val compileProvidedDependencies : ArrayList val compileRuntimeDependencies : ArrayList val excludedDependencies : ArrayList + val nativeDependencies : ArrayList @Directive var dependencies: Dependencies? @@ -28,12 +29,13 @@ open class DependencyHolder : IDependencyHolder { override val compileProvidedDependencies : ArrayList = arrayListOf() override val compileRuntimeDependencies : ArrayList = arrayListOf() override val excludedDependencies : ArrayList = arrayListOf() + override val nativeDependencies : ArrayList = arrayListOf() override var dependencies : Dependencies? = null override fun dependencies(init: Dependencies.() -> Unit) : Dependencies { dependencies = Dependencies(project, compileDependencies, compileProvidedDependencies, - compileRuntimeDependencies, excludedDependencies) + compileRuntimeDependencies, excludedDependencies, nativeDependencies) dependencies!!.init() return dependencies!! } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/IJvmFlagContributor.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/IJvmFlagContributor.kt new file mode 100644 index 00000000..f912ae1d --- /dev/null +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/IJvmFlagContributor.kt @@ -0,0 +1,13 @@ +package com.beust.kobalt.api + +/** + * Plug-ins that add flags to the JVM used to run apps should implement this interface. + */ +interface IJvmFlagContributor : IContributor { + /** + * The list of JVM flags that will be added to the JVM when the app gets run. @param[currentFlags] is only here + * for convenience, in case you need to look at the current JVM flags before adding your own flags. + */ + fun jvmFlagsFor(project: Project, context: KobaltContext, currentFlags: List) : List +} + diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Project.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Project.kt index 2e2b5146..1c3e74dc 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Project.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/api/Project.kt @@ -90,7 +90,7 @@ open class Project( @Directive fun dependenciesTest(init: Dependencies.() -> Unit) : Dependencies { dependencies = Dependencies(this, testDependencies, testProvidedDependencies, compileRuntimeDependencies, - excludedDependencies) + excludedDependencies, nativeDependencies) dependencies!!.init() return dependencies!! } @@ -138,7 +138,8 @@ class Dependencies(val project: Project, val dependencies: ArrayList, val providedDependencies: ArrayList, val runtimeDependencies: ArrayList, - val excludedDependencies: ArrayList) { + val excludedDependencies: ArrayList, + val nativeDependencies: ArrayList) { /** * Add the dependencies to the given ArrayList and return a list of future jar files corresponding to @@ -164,6 +165,9 @@ class Dependencies(val project: Project, @Directive fun exclude(vararg dep: String) = addToDependencies(project, excludedDependencies, dep) + + @Directive + fun native(vararg dep: String) = addToDependencies(project, nativeDependencies, dep) } class Scm(val connection: String, val developerConnection: String, val url: String) diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt index 33c0176e..1156e93e 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/internal/KobaltPluginXml.kt @@ -93,6 +93,7 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?, // Not documented yet val buildConfigContributors = arrayListOf() val mavenIdInterceptors = arrayListOf() + val jvmFlagContributors = arrayListOf() // Note: intentionally repeating them here even though they are defined by our base class so // that this class always contains the full list of contributors and interceptors @@ -206,6 +207,7 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?, // Not documented yet if (this is ITestJvmFlagContributor) testJvmFlagContributors.add(this) if (this is ITestJvmFlagInterceptor) testJvmFlagInterceptors.add(this) + if (this is IJvmFlagContributor) jvmFlagContributors.add(this) } } } @@ -218,7 +220,8 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?, compilerContributors, docContributors, sourceDirContributors, testSourceDirContributors, buildConfigFieldContributors, taskContributors, assemblyContributors, - incrementalAssemblyContributors, testJvmFlagInterceptors + incrementalAssemblyContributors, testJvmFlagInterceptors, + jvmFlagContributors ).forEach { it.forEach { it.cleanUpActors() @@ -256,6 +259,7 @@ class PluginInfo(val xml: KobaltPluginXml, val pluginClassLoader: ClassLoader?, incrementalAssemblyContributors.addAll(pluginInfo.incrementalAssemblyContributors) testJvmFlagContributors.addAll(pluginInfo.testJvmFlagContributors) testJvmFlagInterceptors.addAll(pluginInfo.testJvmFlagInterceptors) + jvmFlagContributors.addAll(pluginInfo.jvmFlagContributors) } } diff --git a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt index 58f07332..e570e598 100644 --- a/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt +++ b/modules/kobalt-plugin-api/src/main/kotlin/com/beust/kobalt/misc/KFiles.kt @@ -65,6 +65,10 @@ class KFiles { val TEST_CLASSES_DIR : String = "test-classes" + val NATIVES_DIR : String = "native" + + fun nativeBuildDir(project: Project) = KFiles.joinDir(project.directory, project.buildDirectory, NATIVES_DIR) + fun generatedSourceDir(project: Project, variant: Variant, name: String) = KFiles.joinDir(project.directory, project.buildDirectory, "generated", "source", name, variant.toIntermediateDir()) diff --git a/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt b/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt index 483a9f3f..720b20ac 100644 --- a/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt +++ b/src/main/kotlin/com/beust/kobalt/plugin/application/ApplicationPlugin.kt @@ -36,7 +36,7 @@ fun Project.application(init: ApplicationConfig.() -> Unit) { @Singleton class ApplicationPlugin @Inject constructor(val configActor: ConfigActor, - val executors: KobaltExecutors, + val executors: KobaltExecutors, val nativeManager: NativeManager, val dependencyManager: DependencyManager, val taskContributor : TaskContributor) : BasePlugin(), IRunnerContributor, ITaskContributor, IConfigActor by configActor { @@ -84,6 +84,9 @@ class ApplicationPlugin @Inject constructor(val configActor: ConfigActor): TaskResult { var result = TaskResult() + if (project.nativeDependencies.any()) { + nativeManager.installLibraries(project) + } configurationFor(project)?.let { config -> if (config.mainClass != null) { result = runJarFile(project, context, config) @@ -113,7 +116,11 @@ class ApplicationPlugin @Inject constructor(val configActor: ConfigActor -> println(output.joinToString("\n")) diff --git a/src/main/kotlin/com/beust/kobalt/plugin/application/NativeManager.kt b/src/main/kotlin/com/beust/kobalt/plugin/application/NativeManager.kt new file mode 100644 index 00000000..7579e1c9 --- /dev/null +++ b/src/main/kotlin/com/beust/kobalt/plugin/application/NativeManager.kt @@ -0,0 +1,36 @@ +package com.beust.kobalt.plugin.application + +import com.beust.kobalt.api.IJvmFlagContributor +import com.beust.kobalt.api.KobaltContext +import com.beust.kobalt.api.Project +import com.beust.kobalt.misc.JarUtils +import com.beust.kobalt.misc.KFiles +import com.beust.kobalt.misc.log +import com.google.inject.Inject +import java.io.File + +/** + * Used for projects that define native() dependencies. This class extracts the native jar files in the + * $build/native library and configures -Djava.library.path with that directory. + */ +class NativeManager @Inject constructor() : IJvmFlagContributor { + fun buildDir(project: Project) = File(KFiles.nativeBuildDir(project)) + + override fun jvmFlagsFor(project: Project, context: KobaltContext, currentFlags: List): List { + return if (project.nativeDependencies.any()) listOf("-Djava.library.path=${buildDir(project)}") + else emptyList() + } + + fun installLibraries(project: Project) { + val buildDir = buildDir(project) + if (! buildDir.exists()) { + buildDir.mkdirs() + project.nativeDependencies.forEach { dep -> + log(2, "Extracting $dep " + dep.jarFile.get() + " in $buildDir") + JarUtils.extractJarFile(dep.jarFile.get(), buildDir) + } + } else { + log(2, "Native directory $buildDir already exists, not extracting the native jar files") + } + } +} diff --git a/src/main/resources/META-INF/kobalt-core-plugin.xml b/src/main/resources/META-INF/kobalt-core-plugin.xml index e353de29..3186b3f5 100644 --- a/src/main/resources/META-INF/kobalt-core-plugin.xml +++ b/src/main/resources/META-INF/kobalt-core-plugin.xml @@ -6,6 +6,7 @@ com.beust.kobalt.plugin.java.JavaPlugin com.beust.kobalt.plugin.application.ApplicationPlugin + com.beust.kobalt.plugin.application.NativeManager com.beust.kobalt.plugin.KobaltPlugin com.beust.kobalt.plugin.kotlin.KotlinPlugin com.beust.kobalt.plugin.packaging.PackagingPlugin