diff --git a/README.md b/README.md index 5de36b6..56295ff 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ This is a Gradle plugin for integrating Project Panama's [`jextract`](https://github.com/openjdk/jextract) tool in the build process. - +There is also a [full demo project](https://github.com/krakowski/jextract-demo) showcasing the `gradle-jextract` plugin. ## :bulb:   Example Since the plugin is available on [Gradle's Plugin Portal](https://plugins.gradle.org/) it can be applied within the build script's `plugins` block. @@ -48,7 +48,7 @@ file usually located inside `${HOME}/.gradle`. org.gradle.java.installations.paths=/custom/path/jdk19 ``` -There is also a [full demo project](https://github.com/krakowski/jextract-demo) showcasing the `gradle-jextract` plugin. +The plugin will first try to find `jextract` inside `PATH` and then fall back to `${JAVA_HOME}/bin`. ## :triangular_ruler:   Configuration Options diff --git a/build.gradle.kts b/build.gradle.kts index 5372c0f..e9bcf01 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -10,7 +10,7 @@ plugins { } group = "io.github.krakowski" -version = "0.2.4" +version = "0.2.5" repositories { mavenCentral() diff --git a/src/main/kotlin/io/github/krakowski/jextract/JextractTask.kt b/src/main/kotlin/io/github/krakowski/jextract/JextractTask.kt index b02ed24..29ebaca 100644 --- a/src/main/kotlin/io/github/krakowski/jextract/JextractTask.kt +++ b/src/main/kotlin/io/github/krakowski/jextract/JextractTask.kt @@ -10,8 +10,11 @@ import org.gradle.api.tasks.* import org.gradle.internal.os.OperatingSystem import org.gradle.kotlin.dsl.newInstance import org.gradle.kotlin.dsl.property +import java.io.File import java.nio.file.Files +import java.nio.file.Path import java.nio.file.Paths +import java.util.regex.Pattern abstract class JextractTask : DefaultTask() { @@ -39,18 +42,42 @@ abstract class JextractTask : DefaultTask() { group = "build" } + private fun findExecutable(): Path { + + // Select appropriate executable for operating system + val operatingSystem = OperatingSystem.current() + val executable = if (operatingSystem.isWindows) WINDOWS_EXECUTABLE else UNIX_EXECUTABLE + + // Search for jextract in PATH + val pathExecutable = System.getenv(ENV_PATH) + .split(Pattern.quote(File.pathSeparator)).stream() + .map { Paths.get(it, executable) } + .filter { Files.exists(it) } + .findFirst() + + if (pathExecutable.isPresent) { + return pathExecutable.get() + } + + // Use bundled jextract binary as a fallback + val bundledExecutable = Paths.get(toolchain.get(), "bin", executable) + if (Files.exists(bundledExecutable)) { + return bundledExecutable + } + + throw GradleException("jextract binary could not be found in PATH or at ${bundledExecutable}") + } + @TaskAction fun action() { - // Check if jextract is present - val javaPath = toolchain.get() - val jextractBinary = if (OperatingSystem.current().isWindows) { - Paths.get(javaPath, "bin/jextract.exe") - } else { - Paths.get(javaPath, "bin/jextract") + val jextractBinary = findExecutable() + if (Files.isDirectory(jextractBinary)) { + throw GradleException("${jextractBinary} is not a regular file but a directory") } - if (Files.notExists(jextractBinary)) { - throw GradleException("jextract binary could not be found at ${jextractBinary}") + + if (!Files.isExecutable(jextractBinary)) { + throw GradleException("${jextractBinary} is not executable") } for (definition in definitions) { @@ -145,7 +172,12 @@ abstract class JextractTask : DefaultTask() { definitions += definition } - companion object { + private companion object { + + const val ENV_PATH = "PATH" + const val UNIX_EXECUTABLE = "jextract" + const val WINDOWS_EXECUTABLE = "jextract.exe" + private fun execute(command: String) { // Create buffers for stdout and stderr streams val stdout = StringBuffer()