mirror of
https://github.com/processing/processing4.git
synced 2026-03-13 16:07:38 +01:00
Merge pull request #1347 from Stefterv/library-plugin
Gradle Plugin for creating Processing Libraries
This commit is contained in:
28
gradle/plugins/library/build.gradle.kts
Normal file
28
gradle/plugins/library/build.gradle.kts
Normal file
@@ -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)
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
gradle/plugins/settings.gradle.kts
Normal file
5
gradle/plugins/settings.gradle.kts
Normal file
@@ -0,0 +1,5 @@
|
||||
plugins {
|
||||
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
|
||||
}
|
||||
|
||||
include("library")
|
||||
@@ -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 {
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
rootProject.name = "processing"
|
||||
|
||||
pluginManagement {
|
||||
includeBuild("gradle/plugins")
|
||||
}
|
||||
|
||||
include(
|
||||
"core",
|
||||
"core:examples",
|
||||
|
||||
Reference in New Issue
Block a user