|
1 | 1 | import org.gradle.internal.jvm.Jvm |
2 | 2 | import org.gradle.internal.os.OperatingSystem |
3 | 3 | import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform |
| 4 | +import org.gradle.process.ExecOperations |
4 | 5 | import org.jetbrains.compose.desktop.application.dsl.TargetFormat |
5 | 6 | import org.jetbrains.compose.desktop.application.tasks.AbstractJPackageTask |
6 | 7 | import org.jetbrains.compose.internal.de.undercouch.gradle.tasks.download.Download |
7 | 8 | import java.io.FileOutputStream |
8 | 9 | import java.util.zip.ZipEntry |
9 | 10 | import java.util.zip.ZipOutputStream |
| 11 | +import javax.inject.Inject |
10 | 12 |
|
11 | 13 | // TODO: Update to 2.10.20 and add hot-reloading: https://github.com/JetBrains/compose-hot-reload |
12 | 14 |
|
| 15 | +abstract class SignResourcesTask : DefaultTask() { |
| 16 | + @get:Inject |
| 17 | + abstract val execOperations: ExecOperations |
| 18 | + |
| 19 | + @get:InputDirectory |
| 20 | + abstract val resourcesPath: DirectoryProperty |
| 21 | + |
| 22 | + @TaskAction |
| 23 | + fun signResources() { |
| 24 | + val resourcesDir = resourcesPath.get().asFile |
| 25 | + val jars = mutableListOf<File>() |
| 26 | + |
| 27 | + // Copy Info.plist if present |
| 28 | + project.fileTree(resourcesDir) |
| 29 | + .matching { include("**/Info.plist") } |
| 30 | + .singleOrNull() |
| 31 | + ?.let { file -> |
| 32 | + project.copy { |
| 33 | + from(file) |
| 34 | + into(resourcesDir) |
| 35 | + } |
| 36 | + } |
| 37 | + |
| 38 | + project.fileTree(resourcesDir) { |
| 39 | + include("**/*.jar") |
| 40 | + exclude("**/*.jar.tmp/**") |
| 41 | + }.forEach { file -> |
| 42 | + val tempDir = file.parentFile.resolve("${file.name}.tmp") |
| 43 | + project.copy { |
| 44 | + from(project.zipTree(file)) |
| 45 | + into(tempDir) |
| 46 | + } |
| 47 | + file.delete() |
| 48 | + jars.add(tempDir) |
| 49 | + } |
| 50 | + |
| 51 | + project.fileTree(resourcesDir) { |
| 52 | + include("**/bin/**") |
| 53 | + include("**/*.jnilib") |
| 54 | + include("**/*.dylib") |
| 55 | + include("**/*aarch64*") |
| 56 | + include("**/*x86_64*") |
| 57 | + include("**/*ffmpeg*") |
| 58 | + include("**/ffmpeg*/**") |
| 59 | + exclude("jdk/**") |
| 60 | + exclude("*.jar") |
| 61 | + exclude("*.so") |
| 62 | + exclude("*.dll") |
| 63 | + }.forEach { file -> |
| 64 | + execOperations.exec { |
| 65 | + commandLine("codesign", "--timestamp", "--force", "--deep", "--options=runtime", "--sign", "Developer ID Application", file) |
| 66 | + } |
| 67 | + } |
| 68 | + |
| 69 | + jars.forEach { file -> |
| 70 | + FileOutputStream(File(file.parentFile, file.nameWithoutExtension)).use { fos -> |
| 71 | + ZipOutputStream(fos).use { zos -> |
| 72 | + file.walkTopDown().forEach { fileEntry -> |
| 73 | + if (fileEntry.isFile) { |
| 74 | + val zipEntryPath = fileEntry.relativeTo(file).path |
| 75 | + val entry = ZipEntry(zipEntryPath) |
| 76 | + zos.putNextEntry(entry) |
| 77 | + fileEntry.inputStream().use { input -> |
| 78 | + input.copyTo(zos) |
| 79 | + } |
| 80 | + zos.closeEntry() |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | + } |
| 85 | + file.deleteRecursively() |
| 86 | + } |
| 87 | + |
| 88 | + File(resourcesDir, "Info.plist").delete() |
| 89 | + } |
| 90 | +} |
| 91 | + |
13 | 92 | plugins{ |
14 | 93 | id("java") |
15 | 94 | kotlin("jvm") version libs.versions.kotlin |
@@ -49,14 +128,17 @@ compose.desktop { |
49 | 128 | application { |
50 | 129 | mainClass = "processing.app.ProcessingKt" |
51 | 130 |
|
52 | | - jvmArgs(*listOf( |
53 | | - Pair("processing.version", rootProject.version), |
54 | | - Pair("processing.revision", findProperty("revision") ?: Int.MAX_VALUE), |
55 | | - Pair("processing.contributions.source", "https://contributions.processing.org/contribs"), |
56 | | - Pair("processing.download.page", "https://processing.org/download/"), |
57 | | - Pair("processing.download.latest", "https://processing.org/download/latest.txt"), |
58 | | - Pair("processing.tutorials", "https://processing.org/tutorials/"), |
59 | | - ).map { "-D${it.first}=${it.second}" }.toTypedArray()) |
| 131 | + jvmArgs( |
| 132 | + "--enable-native-access=ALL-UNNAMED", // Required for Java 25 native library access |
| 133 | + *listOf( |
| 134 | + Pair("processing.version", rootProject.version), |
| 135 | + Pair("processing.revision", findProperty("revision") ?: Int.MAX_VALUE), |
| 136 | + Pair("processing.contributions.source", "https://contributions.processing.org/contribs"), |
| 137 | + Pair("processing.download.page", "https://processing.org/download/"), |
| 138 | + Pair("processing.download.latest", "https://processing.org/download/latest.txt"), |
| 139 | + Pair("processing.tutorials", "https://processing.org/tutorials/"), |
| 140 | + ).map { "-D${it.first}=${it.second}" }.toTypedArray() |
| 141 | + ) |
60 | 142 |
|
61 | 143 | nativeDistributions{ |
62 | 144 | modules("jdk.jdi", "java.compiler", "jdk.accessibility", "java.management.rmi", "java.scripting", "jdk.httpserver") |
@@ -421,82 +503,14 @@ tasks.register("includeProcessingResources"){ |
421 | 503 | finalizedBy("signResources") |
422 | 504 | } |
423 | 505 |
|
424 | | -tasks.register("signResources"){ |
| 506 | +tasks.register<SignResourcesTask>("signResources") { |
425 | 507 | onlyIf { |
426 | 508 | OperatingSystem.current().isMacOsX |
427 | 509 | && |
428 | 510 | compose.desktop.application.nativeDistributions.macOS.signing.sign.get() |
429 | 511 | } |
430 | 512 | group = "compose desktop" |
431 | | - val resourcesPath = composeResources("") |
432 | | - |
433 | | - // find jars in the resources directory |
434 | | - val jars = mutableListOf<File>() |
435 | | - doFirst{ |
436 | | - fileTree(resourcesPath) |
437 | | - .matching { include("**/Info.plist") } |
438 | | - .singleOrNull() |
439 | | - ?.let { file -> |
440 | | - copy { |
441 | | - from(file) |
442 | | - into(resourcesPath) |
443 | | - } |
444 | | - } |
445 | | - fileTree(resourcesPath) { |
446 | | - include("**/*.jar") |
447 | | - exclude("**/*.jar.tmp/**") |
448 | | - }.forEach { file -> |
449 | | - val tempDir = file.parentFile.resolve("${file.name}.tmp") |
450 | | - copy { |
451 | | - from(zipTree(file)) |
452 | | - into(tempDir) |
453 | | - } |
454 | | - file.delete() |
455 | | - jars.add(tempDir) |
456 | | - } |
457 | | - fileTree(resourcesPath){ |
458 | | - include("**/bin/**") |
459 | | - include("**/*.jnilib") |
460 | | - include("**/*.dylib") |
461 | | - include("**/*aarch64*") |
462 | | - include("**/*x86_64*") |
463 | | - include("**/*ffmpeg*") |
464 | | - include("**/ffmpeg*/**") |
465 | | - exclude("jdk/**") |
466 | | - exclude("*.jar") |
467 | | - exclude("*.so") |
468 | | - exclude("*.dll") |
469 | | - }.forEach{ file -> |
470 | | - exec { |
471 | | - commandLine("codesign", "--timestamp", "--force", "--deep","--options=runtime", "--sign", "Developer ID Application", file) |
472 | | - } |
473 | | - } |
474 | | - jars.forEach { file -> |
475 | | - FileOutputStream(File(file.parentFile, file.nameWithoutExtension)).use { fos -> |
476 | | - ZipOutputStream(fos).use { zos -> |
477 | | - file.walkTopDown().forEach { fileEntry -> |
478 | | - if (fileEntry.isFile) { |
479 | | - // Calculate the relative path for the zip entry |
480 | | - val zipEntryPath = fileEntry.relativeTo(file).path |
481 | | - val entry = ZipEntry(zipEntryPath) |
482 | | - zos.putNextEntry(entry) |
483 | | - |
484 | | - // Copy file contents to the zip |
485 | | - fileEntry.inputStream().use { input -> |
486 | | - input.copyTo(zos) |
487 | | - } |
488 | | - zos.closeEntry() |
489 | | - } |
490 | | - } |
491 | | - } |
492 | | - } |
493 | | - |
494 | | - file.deleteRecursively() |
495 | | - } |
496 | | - file(composeResources("Info.plist")).delete() |
497 | | - } |
498 | | - |
499 | | - |
| 513 | + resourcesPath.set(composeResources("")) |
500 | 514 | } |
501 | 515 | tasks.register("setExecutablePermissions") { |
502 | 516 | description = "Sets executable permissions on binaries in Processing.app resources" |
|
0 commit comments