Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions gradle/plugins/library/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
plugins {
`java-gradle-plugin`
kotlin("jvm") version "2.2.20"
}

gradlePlugin {
plugins {
create("processing.library") {
id = "org.processing.library"
implementationClass = "ProcessingLibraryPlugin"
}
}
}

repositories {
mavenCentral()
}

dependencies {
testImplementation(kotlin("test"))
}

tasks.test {
useJUnitPlatform()
}
kotlin {
jvmToolchain(17)
}
77 changes: 77 additions & 0 deletions gradle/plugins/library/src/main/kotlin/BundleLibraryFilesTask.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.bundling.Jar
import org.gradle.api.tasks.javadoc.Javadoc

abstract class BundleLibraryFilesTask : DefaultTask() {
@Input
var configuration: ProcessingLibraryConfiguration? = null

@OutputDirectory
val outputDir = project.objects.directoryProperty()

init {
outputDir.convention(project.layout.buildDirectory.dir("library"))
}

@TaskAction
fun bundle() {
val configuration = configuration
?: throw GradleException("Processing library configuration must be provided.")
val libraryName = configuration.name ?: project.name

val buildDir = project.layout.buildDirectory.dir("library/$libraryName").get().asFile
buildDir.mkdirs()

val libDir = buildDir.resolve("library")
libDir.mkdirs()

// Copy the jar file
val jarFile = project.tasks.named("jar", Jar::class.java).get().archiveFile.get().asFile
jarFile.copyTo(libDir.resolve("$libraryName.jar"), overwrite = true)

// Copy all runtime dependencies
val runtimeClasspath = project.configurations.getByName("runtimeClasspath")
runtimeClasspath.resolvedConfiguration.resolvedArtifacts.forEach { artifact ->
val depFile = artifact.file
depFile.copyTo(libDir.resolve(depFile.name), overwrite = true)
}

// Copy Examples folder
val examplesDir = project.projectDir.resolve("examples")
if (!examplesDir.exists() || !examplesDir.isDirectory) {
throw GradleException("Examples folder not found in project directory.")
}
examplesDir.copyRecursively(buildDir.resolve("examples"), overwrite = true)

// Copy javadoc to reference folder
val docsDir = project.tasks.named("javadoc", Javadoc::class.java).get().destinationDir
docsDir?.copyRecursively(buildDir.resolve("reference"), overwrite = true)

// Create library.properties file
val propertiesFile = buildDir.resolve("library.properties")
propertiesFile.bufferedWriter().use { writer ->
val properties = mapOf(
"name" to libraryName,
"version" to (configuration.version ?: "1.0.0"),
"prettyVersion" to (configuration.prettyVersion ?: configuration.version ?: "1.0.0"),
"authors" to (configuration.authors.entries.joinToString(", ") { "[${it.key}](${it.value})" }),
"url" to configuration.url,
"category" to configuration.categories.joinToString(", "),
"sentence" to configuration.sentence,
"paragraph" to configuration.paragraph,
"minRevision" to configuration.minRevision,
"maxRevision" to configuration.maxRevision
)
properties
.filter { it.value != null && it.value.toString().isNotEmpty() }
.forEach { (key, value) ->
writer.write("$key=$value\n")
}
}
propertiesFile.copyTo(buildDir.resolve("../$libraryName.txt"), overwrite = true)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import org.gradle.api.Action
import org.gradle.api.model.ObjectFactory
import java.io.Serializable
import javax.inject.Inject

open class ProcessingLibraryExtension @Inject constructor(objects: ObjectFactory) {
var version: String? = null
val library = objects.newInstance(ProcessingLibraryConfiguration::class.java)
fun library(action: Action<ProcessingLibraryConfiguration>) {
action.execute(library)
}
}

open class ProcessingLibraryConfiguration @Inject constructor() : Serializable {
/**
* Name of the library. If not set, the project name will be used.
*/
var name: String? = null

/**
* Version number of the library.
*/
var version: Int? = null

/**
* Pretty version string of the library.
*/
var prettyVersion: String? = null

/**
* Map of author URLs to author names.
*/
var authors: Map<String, String> = emptyMap()

/**
* URL of the library where more information can be found.
*/
var url: String? = null

/**
* List of categories the library belongs to.
*/
var categories: List<String> = emptyList()

/**
* A one-line sentence describing the library.
*/
var sentence: String? = null

/**
* A longer paragraph describing the library.
*/
var paragraph: String? = null

/**
* Minimum Processing revision required.
*/
var minRevision: Int? = null

/**
* Maximum Processing revision supported.
*/
var maxRevision: Int? = null
}
125 changes: 125 additions & 0 deletions gradle/plugins/library/src/main/kotlin/ProcessingLibraryPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
import org.gradle.api.GradleException
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.bundling.Jar
import org.gradle.api.tasks.bundling.Zip
import org.gradle.api.tasks.javadoc.Javadoc
import org.gradle.jvm.toolchain.JavaLanguageVersion
import java.util.prefs.Preferences

class ProcessingLibraryPlugin : Plugin<Project> {

override fun apply(target: Project) {
val extension = target.extensions.create("processing", ProcessingLibraryExtension::class.java)
target.plugins.apply(JavaPlugin::class.java)

target.repositories.mavenCentral()
target.repositories.maven { it.setUrl("https://jogamp.org/deployment/maven/") }

// Grab processing core if available, otherwise use the published version
val hasCore = try {
val core = target.project(":core")
target.dependencies.add("compileOnly", core)
true
} catch (_: Exception) {
false
}

target.afterEvaluate {
if (!hasCore) {
if (extension.version == null) {
throw GradleException("Processing library version must be specified, please set processing.version in your build.gradle.kts")
}
val processingVersion = extension.version
target.dependencies.add("compileOnly", "org.processing:core:$processingVersion")
}
}
target.extensions.configure(JavaPluginExtension::class.java) { extension ->
extension.toolchain.languageVersion.set(JavaLanguageVersion.of(17))
}

target.plugins.withType(JavaPlugin::class.java) {
val jarTask = target.tasks.named("jar", Jar::class.java)
val javaDocTask = target.tasks.named("javadoc", Javadoc::class.java)

val bundleTask = target.tasks.register("bundleLibrary", BundleLibraryFilesTask::class.java) { task ->
task.configuration = extension.library
task.group = "processing"
task.description = "Creates the Processing library folder with jar, library.properties, and examples."
task.dependsOn(jarTask, javaDocTask)
}

val zipTask = target.tasks.register("zipLibrary", Zip::class.java) { task ->
task.apply {
val libraryName = extension.library.name ?: target.name
val sourceDir = bundleTask.get().outputDir.get().asFile

group = "processing"
description = "Creates a zip & pdex archive of the Processing library folder."
dependsOn(bundleTask)
include("${libraryName}/**")

archiveFileName.set("$libraryName.zip")
from(sourceDir)
destinationDirectory.set(sourceDir)
doLast {
val zip = task.outputs.files.files.first()
zip.copyTo(sourceDir.resolve("$libraryName.pdex"), overwrite = true)
}
}
}

target.tasks.register("installLibrary") { task ->
task.apply {
group = "processing"
dependsOn(zipTask)
doLast {
val preferences = Preferences.userRoot().node("org/processing/app")

val semverRe = Regex("""^(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([0-9A-Za-z.-]+))?""")
fun semverKey(v: String): Triple<Long, Boolean, String> {
val m = semverRe.find(v)
val maj = m?.groupValues?.getOrNull(1)?.toLongOrNull() ?: 0L
val min = m?.groupValues?.getOrNull(2)?.toLongOrNull() ?: 0L
val pat = m?.groupValues?.getOrNull(3)?.toLongOrNull() ?: 0L
val pre = m?.groupValues?.getOrNull(4)
val packed = (maj shl 40) or (min shl 20) or pat
return Triple(packed, pre == null, pre ?: "")
}

val installLocations = preferences.get("installLocations", "")
.split(",")
.filter { it.isNotEmpty() }
.mapNotNull {
val parts = it.split("^")
if (parts.size < 2) null else parts[1] to parts[0] // version to path
}
.sortedWith(Comparator { a, b ->
val ka = semverKey(a.first)
val kb = semverKey(b.first)
when {
ka.first != kb.first -> kb.first.compareTo(ka.first)
ka.second != kb.second -> kb.second.compareTo(ka.second)
else -> kb.third.compareTo(ka.third)
}
})

val installPath = installLocations.firstOrNull()?.second
?: throw GradleException("Could not find Processing install location in preferences.")

val libraryName = extension.library.name ?: target.name
val sourceDir = bundleTask.get().outputDir.get().asFile.resolve("$libraryName.pdex")

ProcessBuilder()
.command(installPath, sourceDir.absolutePath)
.inheritIO()
.start()
}
}
}

}
}
}
5 changes: 5 additions & 0 deletions gradle/plugins/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}

include("library")
38 changes: 26 additions & 12 deletions java/libraries/dxf/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
plugins{
java
id("org.processing.library")
}

processing {
library {
version = 1
prettyVersion = "1.0.0"

authors = mapOf(
"The Processing Foundation" to "https://processing.org"
)
url = "https://processing.org/"
categories = listOf("file", "exporter", "dxf")

sentence = "DXF export library for Processing"
paragraph =
"This library allows you to export your Processing drawings as DXF files, which can be opened in CAD applications."

}
}

sourceSets {
Expand All @@ -9,27 +27,23 @@ sourceSets {
}
}
}
repositories{
mavenCentral()
maven("https://jogamp.org/deployment/maven/")
}

dependencies{
compileOnly(project(":core"))

implementation("com.lowagie:itext:2.1.7")
}

tasks.register<Copy>("createLibrary"){
/**
* @deprecated Legacy task, use 'bundleLibrary' task provided by 'org.processing.library' plugin
*/
tasks.register<Copy>("createLibrary") {
dependsOn("jar")
into(layout.buildDirectory.dir("library"))

from(layout.projectDirectory){
include ("library.properties")
from(layout.projectDirectory) {
include("library.properties")
include("examples/**")
}

from(configurations.runtimeClasspath){
from(configurations.runtimeClasspath) {
into("library")
}

Expand Down
5 changes: 5 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
rootProject.name = "processing"

pluginManagement {
includeBuild("gradle/plugins")
}

include(
"core",
"core:examples",
Expand Down