Skip to content

Commit

Permalink
Implement resolving of jextract resource as value source
Browse files Browse the repository at this point in the history
  • Loading branch information
tamaracha committed Sep 26, 2024
1 parent da6e5b6 commit c14514d
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 173 deletions.
Original file line number Diff line number Diff line change
@@ -1,45 +1,38 @@
package de.infolektuell.gradle.jextract

import de.infolektuell.gradle.jextract.extensions.DefaultJextractResolver
import de.infolektuell.gradle.jextract.extensions.JextractExtension
import de.infolektuell.gradle.jextract.extensions.ResourceHandler
import de.infolektuell.gradle.jextract.tasks.DownloadClient
import de.infolektuell.gradle.jextract.tasks.DownloadTask
import de.infolektuell.gradle.jextract.tasks.ExtractTask
import de.infolektuell.gradle.jextract.tasks.DumpIncludesTask
import de.infolektuell.gradle.jextract.tasks.GenerateBindingsTask
import org.gradle.api.JavaVersion
import org.gradle.api.NamedDomainObjectContainer
import de.infolektuell.gradle.jextract.extensions.JextractResolver
import de.infolektuell.gradle.jextract.tasks.*
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.plugins.JavaPlugin
import org.gradle.api.plugins.JavaPluginExtension
import org.gradle.api.tasks.SourceSet
import org.gradle.api.provider.Provider
import org.gradle.api.tasks.SourceSetContainer
import org.gradle.jvm.toolchain.JavaLanguageVersion
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform

abstract class GradleJextractPlugin : Plugin<Project> {
override fun apply(project: Project) {
val serviceProvider = project.gradle.sharedServices.registerIfAbsent("${project.name}_${DownloadClient.SERVICE_NAME}", DownloadClient::class.java)
project.tasks.withType(DownloadTask::class.java).configureEach { task ->
task.downloadClient.set(serviceProvider)
task.usesService(serviceProvider)
}
val extension = project.extensions.create(JextractExtension.EXTENSION_NAME, JextractExtension::class.java)
extension.generator.distribution.registerPlatforms()
val javaExtension: JavaPluginExtension? = project.extensions.findByType(JavaPluginExtension::class.java)
val sourceSets = project.extensions.findByType(SourceSetContainer::class.java)
javaExtension?.let { extension.generator.javaLanguageVersion.convention(it.toolchain.languageVersion) }
val resourceProvider: Provider<JextractResolver.Resource> = project.providers.of(DefaultJextractResolver::class.java) { spec ->
spec.parameters.javaLanguageVersion.convention(extension.generator.javaLanguageVersion)
}

val userOutput = project.layout.projectDirectory.dir(project.gradle.gradleUserHomeDir.absolutePath)
val resource: ResourceHandler = extension.generator.distribution.currentResource()
val downloadTask = project.tasks.register("downloadJextract", DownloadTask::class.java) { task ->
task.description = "Downloads Jextract for ${resource.name} platform"
task.source.set(resource.url)
task.target.set(userOutput.dir("downloads").file(resource.url.map { it.path.replaceBeforeLast("/", "").trim('/') }))
task.integrity.put(resource.integrity.algorithm.get(), resource.integrity.checksum)
task.description = "Downloads Jextract"
task.downloadClient.convention(serviceProvider)
task.usesService(serviceProvider)
task.resource.convention(resourceProvider)
task.target.convention(userOutput.dir("downloads").file(task.resource.map { it.fileName }))
}

val extractTask = project.tasks.register("extract", ExtractTask::class.java) { task ->
task.source.set(downloadTask.get().target)
task.target.set(userOutput.dir("jextract").dir(resource.integrity.checksum.map { it.substring(0, 8) }))
task.source.convention(downloadTask.flatMap { it.target })
task.target.convention(userOutput.dir("jextract").dir(extension.generator.javaLanguageVersion.map { "jextract-${it.asInt()}" }))
}
extension.generator.local.convention(extractTask.flatMap { it.target })

Expand All @@ -48,8 +41,8 @@ abstract class GradleJextractPlugin : Plugin<Project> {
project.tasks.register("${lib.name}Jextract", GenerateBindingsTask::class.java) { task ->
task.group = "Build"
task.description = "Generates bindings for the ${lib.name} library using Jextract"
task.outputDirectory.convention(project.layout.buildDirectory.dir("generated/sources/jextract/main/java"))
task.generator.location.set(extension.generator.local)
task.outputDirectory.convention(project.layout.buildDirectory.dir("generated/sources/jextract/${lib.name}/main/java"))
task.generator.location.convention(extension.generator.local)
task.header.set(lib.header)
task.definedMacros.set(lib.definedMacros)
task.whitelist.set(lib.whitelist.mapProvider)
Expand All @@ -59,57 +52,22 @@ abstract class GradleJextractPlugin : Plugin<Project> {
task.includes.set(lib.includes)
task.libraries.set(lib.libraries)
task.useSystemLoadLibrary.set(lib.useSystemLoadLibrary)
sourceSets?.named("main") { main ->
main.java.srcDir(task)
main.compileClasspath += project.files(task)
main.runtimeClasspath += project.files(task)
}
}
project.tasks.register("${lib.name}DumpIncludes", DumpIncludesTask::class.java) { task ->
task.group = "documentation"
task.description = "Generates a dump of all symbols encountered in a header file"
task.generator.location.set(extension.generator.local)
task.generator.location.convention(extension.generator.local)
task.header.set(lib.header)
task.argFile.convention(project.layout.buildDirectory.file("reports/jextract/${lib.name}-includes.txt"))
}
}
project.plugins.withType(JavaPlugin::class.java) { _ ->
val javaExtension = project.extensions.getByType(JavaPluginExtension::class.java)
val version = javaExtension.toolchain.languageVersion.orElse(JavaLanguageVersion.of(JavaVersion.current().majorVersion))
extension.generator.javaVersion(version.get())
val sourceSets = project.extensions.getByType(SourceSetContainer::class.java)
sourceSets.named(SourceSet.MAIN_SOURCE_SET_NAME) { main ->
val generatorTasks = project.tasks.withType(GenerateBindingsTask::class.java)
val generatedFiles = project.files(generatorTasks)
main.java.srcDir(generatorTasks)
main.compileClasspath += generatedFiles
main.runtimeClasspath += generatedFiles
}
}
}

private fun NamedDomainObjectContainer<ResourceHandler>.registerPlatforms() {
register("linux_aarch64")
register("linux_x64")
register("mac_aarch64")
register("mac_x64")
register("windows_aarch64")
register("windows_x64")
}
private fun NamedDomainObjectContainer<ResourceHandler>.currentResource(): ResourceHandler {
val currentOs = DefaultNativePlatform.getCurrentOperatingSystem()
val currentArch = DefaultNativePlatform.getCurrentArchitecture()
return if (currentOs.isLinux) {
if (currentArch.isArm) named("linux_aarch64").orElse(getByName("linux_x64"))
getByName("linux_x64")
}
else if (currentOs.isMacOsX) {
if (currentArch.isArm) named("mac_aarch64").orElse(getByName("mac_x64"))
getByName("mac_x64")
}
else if (currentOs.isWindows) {
if (currentArch.isArm) named("windows_aarch64").orElse(getByName("windows_x64"))
getByName("windows_x64")
}
else {
getByName("windows_x64")
}
}
companion object {
const val PLUGIN_NAME = "de.infolektuell.jextract"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package de.infolektuell.gradle.jextract.extensions

import org.gradle.api.GradleException
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
import java.net.URI

abstract class DefaultJextractResolver : JextractResolver {
data class Resource(override val url: URI, override val checksum: String, override val algorithm: String) : JextractResolver.Resource {
override val fileName = url.path.replaceBeforeLast("/", "").trim('/')
constructor(url: String, checksum: String) : this(URI.create(url), checksum, "SHA-256")
}
private val currentOs = DefaultNativePlatform.getCurrentOperatingSystem()
private val currentArch = DefaultNativePlatform.getCurrentArchitecture()
private val data = mapOf(
22 to mapOf(
"linux_x64" to Resource("https://download.java.net/java/early_access/jextract/22/5/openjdk-22-jextract+5-33_linux-x64_bin.tar.gz", "53d66299cda8d079aeff42b2cc765314e44b384f3e0ec2a7eb994bae62b4b728"),
"mac_aarch64" to Resource("https://download.java.net/java/early_access/jextract/22/5/openjdk-22-jextract+5-33_macos-aarch64_bin.tar.gz", "2a4411c32aedb064c3e432eb8a2791e6e60fea452330c71386f6573dc4c9c850"),
"mac_x64" to Resource("https://download.java.net/java/early_access/jextract/22/5/openjdk-22-jextract+5-33_macos-x64_bin.tar.gz", "0f65d480a1713d73c179e91f3ab6b9553c22694cd1a9f7936ffa8ca351d12390"),
"windows_x64" to Resource("https://download.java.net/java/early_access/jextract/22/5/openjdk-22-jextract+5-33_windows-x64_bin.tar.gz", "f51d7b79dac50dbe1827f73ea4569d7565657f107bdb41f9dc90057a1106b267"),
),
21 to mapOf(
"linux_x64" to Resource("https://download.java.net/java/early_access/jextract/21/1/openjdk-21-jextract+1-2_linux-x64_bin.tar.gz", "83626610b1b074bfe4985bd825d8ba44d906a30b24c42d971b6ac836c7eb0671"),
"mac_x64" to Resource("https://download.java.net/java/early_access/jextract/21/1/openjdk-21-jextract+1-2_macos-x64_bin.tar.gz", "6183f3d079ed531cc5a332e6d86c0abfbc5d001f1e85f721ebc5232204c987a2"),
"windows_x64" to Resource("https://download.java.net/java/early_access/jextract/21/1/openjdk-21-jextract+1-2_windows-x64_bin.tar.gz", "30a4723f4eaa506b926d3d8d368e5b00e2774be7b5df326a7f779bbef48de69f"),
),
20 to mapOf(
"linux_x64" to Resource("https://download.java.net/java/early_access/jextract/20/1/openjdk-20-jextract+1-2_linux-x64_bin.tar.gz", "fced495b34d776f91f65a4f72023f2c3de0c9e8c3787157288baf0d82d1ec1f2"),
"mac_x64" to Resource("https://download.java.net/java/early_access/jextract/20/1/openjdk-20-jextract+1-2_macos-x64_bin.tar.gz", "84e3dcd6674ad486b01b5fb2cf7359adf5a1d5112d13de2321882bf1ec1dd904"),
"windows_x64" to Resource("https://download.java.net/java/early_access/jextract/20/1/openjdk-20-jextract+1-2_windows-x64_bin.tar.gz", "9ad31b338ff8b94834869e6d865e2b986efcdaa0d76e28d4054f8b291b74019f"),
),
19 to mapOf(
"linux_x64" to Resource("https://download.java.net/java/early_access/jextract/19/2/openjdk-19-jextract+2-3_linux-x64_bin.tar.gz", "5f97e63ed608e7a68e7995b8038e225b8beb2e9fb67216ba2bcd711453a6bb51"),
"mac_x64" to Resource("https://download.java.net/java/early_access/jextract/19/2/openjdk-19-jextract+2-3_macos-x64_bin.tar.gz", "f2672332b5a4a8f07464472f74060e8fad9ab86c77bf3d4def8fb0fc4c6b4510"),
"windows_x64" to Resource("https://download.java.net/java/early_access/jextract/19/2/openjdk-19-jextract+2-3_windows-x64_bin.tar.gz", "770723ae81a2ff48bfba6ec83c6fcbff6975a4dbb635b49bd5c3b7c042aefea2"),
),
)
override fun obtain(): JextractResolver.Resource {
val version = parameters.javaLanguageVersion.get()
val distribution = data[version.asInt()] ?: data[22]
if (distribution == null) throw GradleException("No distribution found")
val resource = if (currentOs.isLinux) {
if (currentArch.isArm) {
distribution["linux_aarch64"] ?: distribution["linux_x64"]
} else {
distribution["linux_x64"]
}
} else if (currentOs.isMacOsX) {
if (currentArch.isArm) {
distribution["mac_aarch64"] ?: distribution["mac_x64"]
} else {
distribution["mac_x64"]
}
} else {
if (currentArch.isArm) {
distribution["windows_aarch64"] ?: distribution["windows_x64"]
} else {
distribution["windows_x64"]
}
}
if (resource == null) throw GradleException("No platform found")
return resource
}
}
Original file line number Diff line number Diff line change
@@ -1,95 +1,12 @@
package de.infolektuell.gradle.jextract.extensions

import org.gradle.api.Action
import org.gradle.api.GradleException
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.Property
import org.gradle.jvm.toolchain.JavaLanguageVersion
import java.net.URI
import javax.inject.Inject

abstract class GeneratorHandler @Inject constructor(objects: ObjectFactory) {
/** Contains platform-specific locations where JExtract can be downloaded */
val distribution: NamedDomainObjectContainer<ResourceHandler> = objects.domainObjectContainer(ResourceHandler::class.java)
/** Configures platform-specific locations where JExtract can be downloaded */
fun distribution(action: Action<in NamedDomainObjectContainer<ResourceHandler>>) {
action.execute(distribution)
}
abstract class GeneratorHandler {
/** Explicitly set Java version to download Jextract for, defaults to JVM toolchain */
abstract val javaLanguageVersion: Property<JavaLanguageVersion>
/** A directory containing a JExtract installation */
abstract val local: DirectoryProperty

/** Sets sensible defaults to download Jextract for a specific Java version */
fun javaVersion(version: JavaLanguageVersion) {
when(version) {
JavaLanguageVersion.of(23), JavaLanguageVersion.of(22) -> {
distribution.getByName("linux_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/22/5/openjdk-22-jextract+5-33_linux-x64_bin.tar.gz",
"53d66299cda8d079aeff42b2cc765314e44b384f3e0ec2a7eb994bae62b4b728",
)}
distribution.getByName("mac_aarch64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/22/5/openjdk-22-jextract+5-33_macos-aarch64_bin.tar.gz",
"2a4411c32aedb064c3e432eb8a2791e6e60fea452330c71386f6573dc4c9c850",
)}
distribution.getByName("mac_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/22/5/openjdk-22-jextract+5-33_macos-x64_bin.tar.gz",
"0f65d480a1713d73c179e91f3ab6b9553c22694cd1a9f7936ffa8ca351d12390",
)}
distribution.getByName("windows_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/22/5/openjdk-22-jextract+5-33_windows-x64_bin.tar.gz",
"f51d7b79dac50dbe1827f73ea4569d7565657f107bdb41f9dc90057a1106b267",
)}
}
JavaLanguageVersion.of(21) -> {
distribution.getByName("linux_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/21/1/openjdk-21-jextract+1-2_linux-x64_bin.tar.gz",
"83626610b1b074bfe4985bd825d8ba44d906a30b24c42d971b6ac836c7eb0671",
)}
distribution.getByName("mac_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/21/1/openjdk-21-jextract+1-2_macos-x64_bin.tar.gz",
"6183f3d079ed531cc5a332e6d86c0abfbc5d001f1e85f721ebc5232204c987a2",
)}
distribution.getByName("windows_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/21/1/openjdk-21-jextract+1-2_windows-x64_bin.tar.gz",
"30a4723f4eaa506b926d3d8d368e5b00e2774be7b5df326a7f779bbef48de69f",
)}
}
JavaLanguageVersion.of(20) -> {
distribution.getByName("linux_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/20/1/openjdk-20-jextract+1-2_linux-x64_bin.tar.gz",
"fced495b34d776f91f65a4f72023f2c3de0c9e8c3787157288baf0d82d1ec1f2",
)}
distribution.getByName("mac_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/20/1/openjdk-20-jextract+1-2_macos-x64_bin.tar.gz",
"84e3dcd6674ad486b01b5fb2cf7359adf5a1d5112d13de2321882bf1ec1dd904",
)}
distribution.getByName("windows_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/20/1/openjdk-20-jextract+1-2_windows-x64_bin.tar.gz",
"9ad31b338ff8b94834869e6d865e2b986efcdaa0d76e28d4054f8b291b74019f"
)}
}
JavaLanguageVersion.of(19) -> {
distribution.getByName("linux_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/19/2/openjdk-19-jextract+2-3_linux-x64_bin.tar.gz",
"5f97e63ed608e7a68e7995b8038e225b8beb2e9fb67216ba2bcd711453a6bb51",
)}
distribution.getByName("mac_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/19/2/openjdk-19-jextract+2-3_macos-x64_bin.tar.gz",
"f2672332b5a4a8f07464472f74060e8fad9ab86c77bf3d4def8fb0fc4c6b4510",
)}
distribution.getByName("windows_x64") { it.setConventions(
"https://download.java.net/java/early_access/jextract/19/2/openjdk-19-jextract+2-3_windows-x64_bin.tar.gz",
"770723ae81a2ff48bfba6ec83c6fcbff6975a4dbb635b49bd5c3b7c042aefea2"
)}
}
else -> {
throw GradleException("This plugin does not support conventions for supplied Java version. Please select a version between 19 and 22.")
}
}
}
private fun ResourceHandler.setConventions(src: String, checksum: String) {
url.convention(URI.create(src))
integrity.checksum.convention(checksum)
integrity.algorithm.convention("SHA-256")
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package de.infolektuell.gradle.jextract.extensions

import org.gradle.api.provider.Property
import org.gradle.api.provider.ValueSource
import org.gradle.api.provider.ValueSourceParameters
import org.gradle.jvm.toolchain.JavaLanguageVersion
import java.io.Serializable
import java.net.URI

interface JextractResolver : ValueSource<JextractResolver.Resource, JextractResolver.Parameters> {
interface Resource : Serializable {
val url: URI
val fileName: String
val checksum: String
val algorithm: String
}
interface Parameters : ValueSourceParameters {
val javaLanguageVersion: Property<JavaLanguageVersion>
}
}
Loading

0 comments on commit c14514d

Please sign in to comment.