11import org.gradle.internal.jvm.Jvm
22import org.gradle.kotlin.dsl.support.zipTo
3+ import org.gradle.internal.os.OperatingSystem
34import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform
45import org.jetbrains.compose.ExperimentalComposeLibrary
56import org.jetbrains.compose.desktop.application.dsl.TargetFormat
@@ -48,7 +49,7 @@ sourceSets{
4849
4950compose.desktop {
5051 application {
51- mainClass = " processing.app.ui.Start "
52+ mainClass = " processing.app.ProcessingKt "
5253
5354
5455 val variables = mapOf (
@@ -64,7 +65,7 @@ compose.desktop {
6465 jvmArgs(* variables.entries.map { " -D${it.key} =${it.value} " }.toTypedArray())
6566
6667 nativeDistributions{
67- modules(" jdk.jdi" , " java.compiler" , " jdk.accessibility" , " jdk.zipfs " , " java.management.rmi " )
68+ modules(" jdk.jdi" , " java.compiler" , " jdk.accessibility" , " java.management.rmi " , " java.scripting " )
6869 targetFormats(TargetFormat .Dmg , TargetFormat .Msi , TargetFormat .Deb )
6970 packageName = " Processing"
7071
@@ -132,6 +133,8 @@ dependencies {
132133 implementation(gradleApi())
133134 @OptIn(ExperimentalComposeLibrary ::class )
134135 testImplementation(compose.uiTest)
136+
137+ implementation(libs.clikt)
135138}
136139
137140tasks.test {
@@ -144,14 +147,35 @@ tasks.compileJava{
144147 options.encoding = " UTF-8"
145148}
146149
150+ tasks.register(" lsp-develop" ){
151+ group = " processing"
152+ // This task is used to run the LSP server when developing the LSP server itself
153+ // to run the LSP server for end-users use `processing lsp` instead
154+ dependencies.add(" runtimeOnly" , project(" :java" ))
155+
156+ // Usage: ./gradlew lsp-develop
157+ // Make sure the cwd is set to the project directory
158+ // or use -p to set the project directory
159+
160+ // Modify run configuration to start the LSP server rather than the Processing IDE
161+ val run = tasks.named<JavaExec >(" run" ).get()
162+ run.standardInput = System .`in `
163+ run.standardOutput = System .out
164+ dependsOn(run)
165+
166+ // TODO: Remove after command line is integrated, then add the `lsp` argument instead, `lsp-develop` can't be removed because we still need to pipe the input and output
167+ run.jvmArgs(" -Djava.awt.headless=true" )
168+ compose.desktop.application.mainClass = " processing.mode.java.lsp.PdeLanguageServer"
169+ }
170+
147171val version = if (project.version == " unspecified" ) " 1.0.0" else project.version
148172
149173tasks.register<Exec >(" installCreateDmg" ) {
150- onlyIf { org.gradle.internal.os. OperatingSystem .current().isMacOsX }
174+ onlyIf { OperatingSystem .current().isMacOsX }
151175 commandLine(" arch" , " -arm64" , " brew" , " install" , " --quiet" , " create-dmg" )
152176}
153177tasks.register<Exec >(" packageCustomDmg" ){
154- onlyIf { org.gradle.internal.os. OperatingSystem .current().isMacOsX }
178+ onlyIf { OperatingSystem .current().isMacOsX }
155179 group = " compose desktop"
156180
157181 val distributable = tasks.named<AbstractJPackageTask >(" createDistributable" ).get()
@@ -181,8 +205,6 @@ tasks.register<Exec>("packageCustomDmg"){
181205 extra.add(" 25" )
182206 }
183207
184- commandLine(" brew" , " install" , " --quiet" , " create-dmg" )
185-
186208 commandLine(" create-dmg" ,
187209 " --volname" , packageName,
188210 " --volicon" , file(" macos/volume.icns" ),
@@ -199,7 +221,7 @@ tasks.register<Exec>("packageCustomDmg"){
199221}
200222
201223tasks.register<Exec >(" packageCustomMsi" ){
202- onlyIf { org.gradle.internal.os. OperatingSystem .current().isWindows }
224+ onlyIf { OperatingSystem .current().isWindows }
203225 dependsOn(" createDistributable" )
204226 workingDir = file(" windows" )
205227 group = " compose desktop"
@@ -215,20 +237,22 @@ tasks.register<Exec>("packageCustomMsi"){
215237 )
216238}
217239
218- val snapname = findProperty(" snapname" ) ? : rootProject.name
219- val snaparch = when (System .getProperty(" os.arch" )) {
220- " amd64" , " x86_64" -> " amd64"
221- " aarch64" -> " arm64"
222- else -> System .getProperty(" os.arch" )
223- }
240+
224241tasks.register(" generateSnapConfiguration" ){
225- onlyIf { org.gradle.internal.os.OperatingSystem .current().isLinux }
242+ val name = findProperty(" snapname" ) ? : rootProject.name
243+ val arch = when (System .getProperty(" os.arch" )) {
244+ " amd64" , " x86_64" -> " amd64"
245+ " aarch64" -> " arm64"
246+ else -> System .getProperty(" os.arch" )
247+ }
248+
249+ onlyIf { OperatingSystem .current().isLinux }
226250 val distributable = tasks.named<AbstractJPackageTask >(" createDistributable" ).get()
227251 dependsOn(distributable)
228252
229253 val dir = distributable.destinationDir.get()
230254 val content = """
231- name: $snapname
255+ name: $name
232256 version: $version
233257 base: core22
234258 summary: A creative coding editor
@@ -251,11 +275,12 @@ tasks.register("generateSnapConfiguration"){
251275 - network
252276 - opengl
253277 - home
278+ - removable-media
254279
255280 parts:
256281 processing:
257282 plugin: dump
258- source: deb/processing_$version -1_$snaparch .deb
283+ source: deb/processing_$version -1_$arch .deb
259284 source-type: deb
260285 stage-packages:
261286 - openjdk-17-jre
@@ -267,7 +292,7 @@ tasks.register("generateSnapConfiguration"){
267292}
268293
269294tasks.register<Exec >(" packageSnap" ){
270- onlyIf { org.gradle.internal.os. OperatingSystem .current().isLinux }
295+ onlyIf { OperatingSystem .current().isLinux }
271296 dependsOn(" packageDeb" , " generateSnapConfiguration" )
272297 group = " compose desktop"
273298
@@ -276,7 +301,7 @@ tasks.register<Exec>("packageSnap"){
276301 commandLine(" snapcraft" )
277302}
278303tasks.register<Zip >(" zipDistributable" ){
279- dependsOn(" createDistributable" )
304+ dependsOn(" createDistributable" , " setExecutablePermissions " )
280305 group = " compose desktop"
281306
282307 val distributable = tasks.named<AbstractJPackageTask >(" createDistributable" ).get()
@@ -289,34 +314,29 @@ tasks.register<Zip>("zipDistributable"){
289314}
290315
291316afterEvaluate{
317+ // Override the default DMG task to use our custom one
292318 tasks.named(" packageDmg" ).configure{
293319 dependsOn(" packageCustomDmg" )
294320 group = " compose desktop"
295321 actions = emptyList()
296322 }
297-
323+ // Override the default MSI task to use our custom one
298324 tasks.named(" packageMsi" ).configure{
299325 dependsOn(" packageCustomMsi" )
300326 group = " compose desktop"
301327 actions = emptyList()
302328 }
303329 tasks.named(" packageDistributionForCurrentOS" ).configure {
304- if (org.gradle.internal.os. OperatingSystem .current().isMacOsX
330+ if (OperatingSystem .current().isMacOsX
305331 && compose.desktop.application.nativeDistributions.macOS.notarization.appleID.isPresent
306332 ){
307333 dependsOn(" notarizeDmg" )
308334 }
309335 dependsOn(" packageSnap" , " zipDistributable" )
310336 }
311- tasks.named(" prepareAppResources" ).configure {
312- dependsOn(
313- " :core:publishAllPublicationsToAppRepository" ,
314- " :java:gradle:publishAllPublicationsToAppRepository" ,
315- " :java:preprocessor:publishAllPublicationsToAppRepository"
316- )
317- }
318337}
319338
339+
320340// LEGACY TASKS
321341// Most of these are shims to be compatible with the old build system
322342// They should be removed in the future, as we work towards making things more Gradle-native
@@ -338,6 +358,10 @@ tasks.register<Copy>("includeJavaMode") {
338358 into(composeResources(" modes/java/mode" ))
339359 duplicatesStrategy = DuplicatesStrategy .EXCLUDE
340360}
361+ tasks.register<Copy >(" includeJdk" ) {
362+ from(Jvm .current().javaHome.absolutePath)
363+ destinationDir = composeResources(" jdk" ).get().asFile
364+ }
341365tasks.register<Copy >(" includeSharedAssets" ){
342366 from(" ../build/shared/" )
343367 into(composeResources(" " ))
@@ -382,44 +406,44 @@ tasks.register<Copy>("includeJavaModeResources") {
382406 from(java.layout.buildDirectory.dir(" resources-bundled" ))
383407 into(composeResources(" ../" ))
384408}
385- tasks.register(" includeJdk" ) {
386- dependsOn(" createDistributable" )
387- doFirst {
388- val jdk = Jvm .current().javaHome.absolutePath
389- val target = layout.buildDirectory.dir(" compose/binaries" ).get().asFileTree.matching { include(" **/include.jdk" ) }
390- .files
391- .firstOrNull()
392- ?.parentFile
393- ?.resolve(" jdk" )
394- ?.absolutePath
395- ? : error(" Could not find include.jdk" )
396-
397- val isWindows = System .getProperty(" os.name" ).lowercase().contains(" win" )
398- val command = if (isWindows) {
399- listOf (" xcopy" , " /E" , " /I" , " /Q" , jdk, target)
400- } else {
401- listOf (" cp" , " -a" , jdk, target)
402- }
403- ProcessBuilder (command).inheritIO().start().waitFor()
409+ // TODO: Move to java mode
410+ tasks.register<Copy >(" renameWindres" ) {
411+ dependsOn(" includeSharedAssets" ," includeJavaModeResources" )
412+ val dir = composeResources(" modes/java/application/launch4j/bin/" )
413+ val os = DefaultNativePlatform .getCurrentOperatingSystem()
414+ val platform = when {
415+ os.isWindows -> " windows"
416+ os.isMacOsX -> " macos"
417+ else -> " linux"
404418 }
405- }
406- tasks.register(" signResources" ){
407- onlyIf {
408- org.gradle.internal.os.OperatingSystem .current().isMacOsX
409- &&
410- compose.desktop.application.nativeDistributions.macOS.signing.sign.get()
419+ from(dir) {
420+ include(" *-$platform *" )
421+ rename(" (.*)-$platform (.*)" , " $1$2" )
411422 }
412- group = " compose desktop"
423+ duplicatesStrategy = DuplicatesStrategy .INCLUDE
424+ into(dir)
425+ }
426+ tasks.register(" includeProcessingResources" ){
413427 dependsOn(
428+ " includeJdk" ,
414429 " includeCore" ,
415430 " includeJavaMode" ,
416431 " includeSharedAssets" ,
417432 " includeProcessingExamples" ,
418433 " includeProcessingWebsiteExamples" ,
419434 " includeJavaModeResources" ,
435+ " renameWindres"
420436 )
421- finalizedBy(" prepareAppResources" )
437+ finalizedBy(" signResources" )
438+ }
422439
440+ tasks.register(" signResources" ){
441+ onlyIf {
442+ OperatingSystem .current().isMacOsX
443+ &&
444+ compose.desktop.application.nativeDistributions.macOS.signing.sign.get()
445+ }
446+ group = " compose desktop"
423447 val resourcesPath = composeResources(" " )
424448
425449 // find jars in the resources directory
@@ -454,7 +478,7 @@ tasks.register("signResources"){
454478 include(" **/*x86_64*" )
455479 include(" **/*ffmpeg*" )
456480 include(" **/ffmpeg*/**" )
457- exclude(" jdk-* /**" )
481+ exclude(" jdk/**" )
458482 exclude(" *.jar" )
459483 exclude(" *.so" )
460484 exclude(" *.dll" )
@@ -489,19 +513,33 @@ tasks.register("signResources"){
489513 }
490514}
491515
516+
517+ tasks.register(" setExecutablePermissions" ) {
518+ description = " Sets executable permissions on binaries in Processing.app resources"
519+ group = " compose desktop"
520+
521+ doLast {
522+ val resourcesPath = layout.buildDirectory.dir(" compose/binaries" )
523+ fileTree(resourcesPath) {
524+ include(" **/resources/**/bin/**" )
525+ include(" **/resources/**/lib/**" )
526+ include(" **/resources/**/*.sh" )
527+ include(" **/resources/**/*.dylib" )
528+ include(" **/resources/**/*.so" )
529+ include(" **/resources/**/*.exe" )
530+ }.forEach { file ->
531+ if (file.isFile) {
532+ file.setExecutable(true , false )
533+ }
534+ }
535+ }
536+ }
537+
492538afterEvaluate {
493539 tasks.named(" prepareAppResources" ).configure {
494- dependsOn(
495- " includeCore" ,
496- " includeJavaMode" ,
497- " includeSharedAssets" ,
498- " includeProcessingExamples" ,
499- " includeProcessingWebsiteExamples" ,
500- " includeJavaModeResources"
501- )
540+ dependsOn(" includeProcessingResources" )
502541 }
503542 tasks.named(" createDistributable" ).configure {
504- dependsOn(" signResources" )
505- finalizedBy(" includeJdk" )
543+ finalizedBy(" setExecutablePermissions" )
506544 }
507545}
0 commit comments