11import groovy.json.JsonSlurper
22import org.gradle.api.file.DuplicatesStrategy
33import org.gradle.api.publish.maven.MavenPublication
4+ import java.util.zip.ZipFile
45
56plugins {
67 id(" java-library" )
@@ -16,6 +17,38 @@ application {
1617 mainClass.set(" redxax.oxy.remotely.RemotelyInit" )
1718}
1819
20+ val reStudioReleaseJarTasks: List <Any > = if (useReStudioSourceDependencies) {
21+ listOf (
22+ gradle.includedBuild(" ReScreen" ).task(" :jar" ),
23+ gradle.includedBuild(" Remodel" ).task(" :jar" ),
24+ gradle.includedBuild(" Rebase" ).task(" :jar" ),
25+ gradle.includedBuild(" Recast" ).task(" :recast-api:jar" ),
26+ gradle.includedBuild(" Recast" ).task(" :recast-bridge:jar" ),
27+ gradle.includedBuild(" ReSync" ).task(" :ReSyncCore:jar" )
28+ )
29+ } else {
30+ emptyList()
31+ }
32+
33+ val releaseRequiredClasses = listOf (
34+ " restudio/rescreen/config/UiConfigStore.class" ,
35+ " restudio/rebase/Rebase.class" ,
36+ " redxax/restudio/Remodel/Main.class" ,
37+ " dev/restudio/recast/api/FeatureDescriptor.class" ,
38+ " dev/restudio/recast/bridge/BridgeEntry.class" ,
39+ " restudio/resync/network/NetworkFrame.class"
40+ )
41+
42+ fun requireReleaseClasses (archives : Collection <File >, artifactName : String ) {
43+ val jarFiles = archives.filter { it.isFile && it.extension.equals(" jar" , ignoreCase = true ) }
44+ val missingClasses = releaseRequiredClasses.filter { className ->
45+ jarFiles.none { archive -> ZipFile (archive).use { it.getEntry(className) != null } }
46+ }
47+ require(missingClasses.isEmpty()) {
48+ " $artifactName Is Missing Required Classes: ${missingClasses.joinToString()} "
49+ }
50+ }
51+
1952tasks.named<JavaExec >(" run" ) {
2053 if (useReStudioSourceDependencies) {
2154 dependsOn(
@@ -424,81 +457,129 @@ tasks.jar {
424457 archiveFileName.set(" Remotely-App.jar" )
425458}
426459
427- tasks.register<Exec >(" createInstaller" ) {
428- dependsOn(" clean" , " jar" )
460+ tasks.register<Jar >(" fatJar" ) {
461+ group = " build"
462+ dependsOn(reStudioReleaseJarTasks)
463+ duplicatesStrategy = DuplicatesStrategy .EXCLUDE
464+ archiveFileName.set(" Remotely-Fat.jar" )
465+ from(sourceSets.main.get().output)
466+ from({
467+ configurations.runtimeClasspath.get().filter { it.exists() }.map {
468+ if (it.isDirectory) it else zipTree(it)
469+ }
470+ })
471+ exclude(" META-INF/*.SF" , " META-INF/*.DSA" , " META-INF/*.RSA" )
472+ manifest {
473+ attributes[" Main-Class" ] = " redxax.oxy.remotely.RemotelyInit"
474+ attributes[" Implementation-Version" ] = project.version.toString()
475+ attributes[" Automatic-Module-Name" ] = " dev.restudio.remotely.app"
476+ }
477+ doLast {
478+ requireReleaseClasses(listOf (archiveFile.get().asFile), " Remotely Fat Jar" )
479+ }
480+ }
429481
430- val javaToolchains = project.extensions.getByType<JavaToolchainService >()
431- val javaLauncher = javaToolchains.launcherFor {
432- languageVersion.set(JavaLanguageVersion .of(21 ))
433- }.get()
482+ val packageJarName = " Remotely-App.jar"
483+ val cleanVersion = version.toString().substringBefore(' -' ).replace(Regex (" [^0-9.]" ), " " )
484+ val javaLauncher = extensions.getByType<JavaToolchainService >().launcherFor {
485+ languageVersion.set(JavaLanguageVersion .of(21 ))
486+ }
487+ val jpackageExecutable = javaLauncher.map {
488+ val executable = if (System .getProperty(" os.name" ).startsWith(" Windows" , ignoreCase = true )) " jpackage.exe" else " jpackage"
489+ File (it.metadata.installationPath.asFile, " bin/$executable " ).absolutePath
490+ }
434491
435- val jdkHome = javaLauncher.metadata.installationPath.asFile
436- val jpackagePath = File (jdkHome, " bin/jpackage.exe" ).absolutePath
492+ fun preparePackageInput (stagingDir : File , outputDir : File , artifactName : String ) {
493+ outputDir.deleteRecursively()
494+ stagingDir.deleteRecursively()
495+ stagingDir.mkdirs()
496+ copy {
497+ from(tasks.named<Jar >(" fatJar" ).flatMap { it.archiveFile })
498+ into(stagingDir)
499+ rename { packageJarName }
500+ }
501+ requireReleaseClasses(fileTree(stagingDir) { include(" *.jar" ) }.files, artifactName)
502+ }
437503
438- val stagingDir = layout.buildDirectory.dir(" staging" ).get().asFile.absolutePath
439- val inputDir = layout.buildDirectory.dir(" libs" ).get().asFile.absolutePath
440- val outputDir = layout.buildDirectory.dir(" dist" ).get().asFile.absolutePath
441- val jarName = " Remotely-App.jar"
504+ tasks.register<Exec >(" createInstaller" ) {
505+ dependsOn(" fatJar" )
506+
507+ val stagingDir = layout.buildDirectory.dir(" package-input/windows" ).get().asFile
508+ val outputDir = layout.buildDirectory.dir(" dist" ).get().asFile
442509 val iconPath = layout.projectDirectory.file(" packaging/Remotely.ico" ).asFile.absolutePath
443- val cleanVersion = version.toString().split(" -" )[0 ].replace(Regex (" [^0-9.]" ), " " )
444510
445511 doFirst {
446- println (" --------------------------------------------------" )
447- println (" Using jpackage: $jpackagePath " )
448- println (" --------------------------------------------------" )
449-
450- file(outputDir).deleteRecursively()
451- file(stagingDir).deleteRecursively()
452- file(stagingDir).mkdirs()
453-
454- copy {
455- from(inputDir)
456- into(stagingDir)
457- include(jarName)
458- }
459-
460- copy {
461- from(configurations.runtimeClasspath)
462- into(stagingDir)
463- }
464-
465- println (" Staging directory contents:" )
466- file(stagingDir).listFiles()?.forEach { println (it.name) }
512+ preparePackageInput(stagingDir, outputDir, " Remotely Windows Installer" )
467513 }
468514
469515 commandLine(
470- jpackagePath ,
516+ jpackageExecutable.get() ,
471517 " --type" , " exe" ,
472- " --dest" , outputDir,
473- " --input" , stagingDir,
518+ " --dest" , outputDir.absolutePath ,
519+ " --input" , stagingDir.absolutePath ,
474520 " --name" , " Remotely" ,
475- " --main-jar" , jarName ,
521+ " --main-jar" , packageJarName ,
476522 " --main-class" , application.mainClass.get(),
477523 " --app-version" , cleanVersion,
478524 " --icon" , iconPath,
479525 " --win-shortcut" ,
480526 " --win-menu" ,
481527 " --win-menu-group" , " ReStudio" ,
482528 " --win-dir-chooser" ,
483- // "--win-console",
484529 " --java-options" , " -Dfile.encoding=UTF-8 -Xmx4G"
485530 )
486531}
487532
488- tasks.register<Jar >(" fatJar" ) {
489- group = " build"
490- duplicatesStrategy = DuplicatesStrategy .EXCLUDE
491- archiveFileName.set(" Remotely-Fat.jar" )
492- from(sourceSets.main.get().output)
493- from({
494- configurations.runtimeClasspath.get().filter { it.exists() }.map {
495- if (it.isDirectory) it else zipTree(it)
496- }
497- })
498- exclude(" META-INF/*.SF" , " META-INF/*.DSA" , " META-INF/*.RSA" )
499- manifest {
500- attributes[" Main-Class" ] = " redxax.oxy.remotely.RemotelyInit"
501- attributes[" Implementation-Version" ] = project.version.toString()
502- attributes[" Automatic-Module-Name" ] = " dev.restudio.remotely.app"
533+ tasks.register<Exec >(" createLinuxAppImage" ) {
534+ dependsOn(" fatJar" )
535+
536+ val stagingDir = layout.buildDirectory.dir(" package-input/linux" ).get().asFile
537+ val outputDir = layout.buildDirectory.dir(" app-image" ).get().asFile
538+ val iconPath = layout.projectDirectory.file(" packaging/Remotely.png" ).asFile.absolutePath
539+
540+ doFirst {
541+ preparePackageInput(stagingDir, outputDir, " Remotely Linux AppImage" )
542+ }
543+
544+ commandLine(
545+ jpackageExecutable.get(),
546+ " --type" , " app-image" ,
547+ " --dest" , outputDir.absolutePath,
548+ " --input" , stagingDir.absolutePath,
549+ " --name" , " Remotely" ,
550+ " --main-jar" , packageJarName,
551+ " --main-class" , application.mainClass.get(),
552+ " --app-version" , cleanVersion,
553+ " --icon" , iconPath,
554+ " --java-options" , " -Dfile.encoding=UTF-8 -Xmx4G"
555+ )
556+ }
557+
558+ tasks.register<Exec >(" createMacDmg" ) {
559+ dependsOn(" fatJar" )
560+
561+ val stagingDir = layout.buildDirectory.dir(" package-input/macos" ).get().asFile
562+ val outputDir = layout.buildDirectory.dir(" dist-macos" ).get().asFile
563+ val iconPath = providers.gradleProperty(" remotely.packageIcon" ).orElse(
564+ layout.projectDirectory.file(" packaging/Remotely.icns" ).asFile.absolutePath
565+ )
566+ val macVersion = cleanVersion.split(' .' ).take(3 ).joinToString(" ." )
567+
568+ doFirst {
569+ preparePackageInput(stagingDir, outputDir, " Remotely macOS Disk Image" )
503570 }
571+
572+ commandLine(
573+ jpackageExecutable.get(),
574+ " --type" , " dmg" ,
575+ " --dest" , outputDir.absolutePath,
576+ " --input" , stagingDir.absolutePath,
577+ " --name" , " Remotely" ,
578+ " --main-jar" , packageJarName,
579+ " --main-class" , application.mainClass.get(),
580+ " --app-version" , macVersion,
581+ " --icon" , iconPath.get(),
582+ " --mac-package-identifier" , " net.restudiomc.remotely" ,
583+ " --java-options" , " -Dfile.encoding=UTF-8 -Xmx4G"
584+ )
504585}
0 commit comments