Skip to content

Commit 04ac9f2

Browse files
committed
Plugin rework for caching heavy work
1 parent e31d37d commit 04ac9f2

File tree

9 files changed

+262
-184
lines changed

9 files changed

+262
-184
lines changed

.kotlin/errors/errors-1743146568860.log

Lines changed: 0 additions & 4 deletions
This file was deleted.

app/src/processing/app/gradle/Exceptions.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Exceptions {
4848

4949
println("\n🚨 Exception Caught 🚨")
5050
println("Type : ${exception.referenceType().name()}")
51+
// TODO: Fix exception message retrieval
5152
// println("Message : ${getExceptionMessage(exception)}")
5253
println("Thread : ${thread.name()}")
5354
println("Location : ${location.sourcePath()}:${location.lineNumber()}\n")

app/src/processing/app/gradle/GradleService.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ class GradleService(val editor: Editor) {
6767

6868
private fun startBuilding(){
6969
scope.launch {
70-
// TODO: Improve the experience with unsaved
7170
val job = BackgroundGradleJob()
7271
job.service = this@GradleService
7372
job.configure = {
@@ -140,10 +139,6 @@ class GradleService(val editor: Editor) {
140139
}
141140

142141
private fun setupGradle(): MutableList<String> {
143-
// TODO: is this the best way to handle unsaved data?
144-
// Certainly not...
145-
// Gradle is not recognizing the unsaved files as changed
146-
// Tricky as when we save the file the actual one will be the latest
147142
val unsaved = editor.sketch.code
148143
.filter { it.isModified }
149144
.map { code ->
@@ -152,6 +147,7 @@ class GradleService(val editor: Editor) {
152147
file.writeText(code.documentText)
153148
code.fileName
154149
}
150+
// TODO: Delete unsaved file if not modified
155151

156152
val group = System.getProperty("processing.group", "org.processing")
157153

java/gradle/example/brightness.pde

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ ControlP5 cp5;
1515

1616

1717
void setup() {
18-
size(640, 360);
18+
size(640, 360, P2D);
1919
colorMode(HSB, width, 100, height);
2020
noStroke();
2121
background(0);
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package org.processing.java.gradle
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.file.RegularFileProperty
5+
import org.gradle.api.tasks.InputFile
6+
import org.gradle.api.tasks.TaskAction
7+
import java.io.File
8+
import java.io.ObjectInputStream
9+
10+
abstract class DependenciesTask: DefaultTask() {
11+
@InputFile
12+
val librariesMetaData: RegularFileProperty = project.objects.fileProperty()
13+
14+
@InputFile
15+
val sketchMetaData: RegularFileProperty = project.objects.fileProperty()
16+
17+
init{
18+
librariesMetaData.convention(project.layout.buildDirectory.file("processing/libraries"))
19+
sketchMetaData.convention(project.layout.buildDirectory.file("processing/sketch"))
20+
}
21+
22+
@TaskAction
23+
fun execute() {
24+
val sketchMetaFile = sketchMetaData.get().asFile
25+
val librariesMetaFile = librariesMetaData.get().asFile
26+
27+
val libraries = librariesMetaFile.inputStream().use { input ->
28+
ObjectInputStream(input).readObject() as ArrayList<LibrariesTask.Library>
29+
}
30+
31+
val sketch = sketchMetaFile.inputStream().use { input ->
32+
ObjectInputStream(input).readObject() as PDETask.SketchMeta
33+
}
34+
35+
val dependencies = mutableSetOf<File>()
36+
37+
// Loop over the import statements in the sketch and import the relevant jars from the libraries
38+
sketch.importStatements.forEach import@{ statement ->
39+
libraries.forEach { library ->
40+
library.jars.forEach { jar ->
41+
jar.classes.forEach { className ->
42+
if (className.startsWith(statement)) {
43+
dependencies.add(jar.path)
44+
return@import
45+
}
46+
}
47+
}
48+
}
49+
}
50+
project.dependencies.add("implementation", project.files(dependencies) )
51+
52+
// TODO: Add only if user is compiling for P2D or P3D
53+
// Add JOGL and Gluegen dependencies
54+
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:jogl-all-main:2.5.0")
55+
project.dependencies.add("runtimeOnly", "org.jogamp.gluegen:gluegen-rt-main:2.5.0")
56+
57+
// TODO: Only add the native dependencies for the platform the user is building for
58+
// MacOS specific native dependencies
59+
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:jogl-all:2.5.0:natives-macosx-universal")
60+
project.dependencies.add("runtimeOnly", "org.jogamp.gluegen:gluegen-rt:2.5.0:natives-macosx-universal")
61+
62+
// Windows specific native dependencies
63+
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:jogl-all:2.5.0:natives-windows-amd64")
64+
project.dependencies.add("runtimeOnly", "org.jogamp.gluegen:gluegen-rt:2.5.0:natives-windows-amd64")
65+
66+
// Linux specific native dependencies
67+
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:jogl-all:2.5.0:natives-linux-amd64")
68+
project.dependencies.add("runtimeOnly", "org.jogamp.gluegen:gluegen-rt:2.5.0:natives-linux-amd64")
69+
70+
// NativeWindow dependencies for all platforms
71+
project.dependencies.add("implementation", "org.jogamp.jogl:nativewindow:2.5.0")
72+
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:nativewindow:2.5.0:natives-macosx-universal")
73+
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:nativewindow:2.5.0:natives-windows-amd64")
74+
project.dependencies.add("runtimeOnly", "org.jogamp.jogl:nativewindow:2.5.0:natives-linux-amd64")
75+
}
76+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package org.processing.java.gradle
2+
3+
import org.gradle.api.DefaultTask
4+
import org.gradle.api.file.DirectoryProperty
5+
import org.gradle.api.file.RegularFileProperty
6+
import org.gradle.api.tasks.InputDirectory
7+
import org.gradle.api.tasks.OutputFile
8+
import org.gradle.api.tasks.TaskAction
9+
import java.io.File
10+
import java.io.ObjectOutputStream
11+
import java.util.jar.JarFile
12+
13+
abstract class LibrariesTask : DefaultTask() {
14+
15+
@InputDirectory
16+
val librariesDirectory: DirectoryProperty = project.objects.directoryProperty()
17+
18+
@OutputFile
19+
val librariesMetaData: RegularFileProperty = project.objects.fileProperty()
20+
21+
init{
22+
librariesMetaData.convention(project.layout.buildDirectory.file("processing/libraries"))
23+
}
24+
25+
data class Jar(
26+
val path: File,
27+
val classes: List<String>
28+
) : java.io.Serializable
29+
30+
data class Library(
31+
val jars: List<Jar>
32+
) : java.io.Serializable
33+
34+
@TaskAction
35+
fun execute() {
36+
val libraries = librariesDirectory.get().asFile
37+
.listFiles { file -> file.isDirectory }
38+
?.map { folder ->
39+
// Find all the jars in the sketchbook
40+
val jars = folder.resolve("library")
41+
.listFiles{ file -> file.extension == "jar" }
42+
?.map{ file ->
43+
44+
// Inside of each jar, look for the defined classes
45+
val jar = JarFile(file)
46+
val classes = jar.entries().asSequence()
47+
.filter { entry -> entry.name.endsWith(".class") }
48+
.map { entry -> entry.name }
49+
.map { it.substringBeforeLast('/').replace('/', '.') }
50+
.distinct()
51+
.toList()
52+
53+
// Return a reference to the jar and its classes
54+
return@map Jar(
55+
path = file,
56+
classes = classes
57+
)
58+
}?: emptyList()
59+
60+
// Save the parsed jars and which folder
61+
return@map Library(
62+
jars = jars
63+
)
64+
}?: emptyList()
65+
66+
val meta = ObjectOutputStream(librariesMetaData.get().asFile.outputStream())
67+
meta.writeObject(libraries)
68+
meta.close()
69+
}
70+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
package org.processing.java.gradle
2+
3+
import org.gradle.api.file.*
4+
import org.gradle.api.tasks.*
5+
import org.gradle.internal.file.Deleter
6+
import org.gradle.work.InputChanges
7+
import processing.mode.java.preproc.PdePreprocessor
8+
import java.io.File
9+
import java.io.ObjectOutputStream
10+
import java.util.concurrent.Callable
11+
import java.util.jar.JarFile
12+
import javax.inject.Inject
13+
14+
15+
// TODO: Generate sourcemaps
16+
abstract class PDETask : SourceTask() {
17+
18+
19+
@get:InputFiles
20+
@get:PathSensitive(PathSensitivity.RELATIVE)
21+
@get:IgnoreEmptyDirectories
22+
@get:SkipWhenEmpty
23+
open val stableSources: FileCollection = project.files(Callable<Any> { this.source })
24+
25+
@OutputDirectory
26+
val outputDirectory = project.objects.directoryProperty()
27+
28+
@get:Input
29+
@get:Optional
30+
var workingDir: String? = null
31+
32+
@get:Input
33+
var sketchName: String = "processing"
34+
35+
@get:Input
36+
@get:Optional
37+
var sketchBook: String? = null
38+
39+
@OutputFile
40+
val sketchMetaData = project.objects.fileProperty()
41+
42+
init{
43+
outputDirectory.convention(project.layout.buildDirectory.dir("generated/pde"))
44+
sketchMetaData.convention(project.layout.buildDirectory.file("processing/sketch"))
45+
}
46+
47+
data class SketchMeta(
48+
val sketchName: String,
49+
val sketchRenderer: String?,
50+
val importStatements: List<String>
51+
) : java.io.Serializable
52+
53+
@TaskAction
54+
fun execute() {
55+
// TODO: Allow pre-processor to run on individual files (future)
56+
// TODO: Only compare file names from both defined roots (e.g. sketch.pde and folder/sketch.pde should both be included)
57+
58+
// Using stableSources since we can only run the pre-processor on the full set of sources
59+
val combined = stableSources
60+
.files
61+
.groupBy { it.name }
62+
.map { entry ->
63+
entry.value.maxByOrNull { it.lastModified() }!!
64+
}
65+
.joinToString("\n"){
66+
it.readText()
67+
}
68+
val javaFile = File(outputDirectory.get().asFile, "$sketchName.java").bufferedWriter()
69+
70+
val meta = PdePreprocessor
71+
.builderFor(sketchName)
72+
.build()
73+
.write(javaFile, combined)
74+
75+
javaFile.flush()
76+
javaFile.close()
77+
78+
val sketchMeta = SketchMeta(
79+
sketchName = sketchName,
80+
sketchRenderer = meta.sketchRenderer,
81+
importStatements = meta.importStatements.map { importStatement -> importStatement.packageName }
82+
)
83+
84+
val metaFile = ObjectOutputStream(sketchMetaData.get().asFile.outputStream())
85+
metaFile.writeObject(sketchMeta)
86+
metaFile.close()
87+
}
88+
89+
@get:Inject
90+
open val deleter: Deleter
91+
get() {
92+
throw UnsupportedOperationException("Decorator takes care of injection")
93+
}
94+
}

0 commit comments

Comments
 (0)