diff --git a/.gitignore b/.gitignore index dc68d978d2..a108acc98e 100644 --- a/.gitignore +++ b/.gitignore @@ -41,7 +41,6 @@ hs_err_pid* *.wallet *.ser *.sh -.vscode .DS_Store .gradle build diff --git a/apps/desktop/desktop-app-launcher/build.gradle.kts b/apps/desktop/desktop-app-launcher/build.gradle.kts index 02b4c33e25..029af8d6cb 100644 --- a/apps/desktop/desktop-app-launcher/build.gradle.kts +++ b/apps/desktop/desktop-app-launcher/build.gradle.kts @@ -1,4 +1,5 @@ import java.util.Properties +import java.io.File // Function to read properties from a file - TODO find a way to reuse this code instead of copying when needed fun readPropertiesFile(filePath: String): Properties { @@ -11,7 +12,6 @@ plugins { id("bisq.java-library") id("bisq.gradle.desktop.regtest.BisqDesktopRegtestPlugin") application - id("org.kordamp.gradle.jdeps") version "0.20.0" id("bisq.gradle.packaging.PackagingPlugin") alias(libs.plugins.openjfx) } diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/JLinkTask.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/JLinkTask.kt index ab3b81b85b..73ba8634d4 100644 --- a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/JLinkTask.kt +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/JLinkTask.kt @@ -3,19 +3,15 @@ package bisq.gradle.packaging import org.gradle.api.DefaultTask import org.gradle.api.file.DirectoryProperty import org.gradle.api.file.RegularFileProperty -import org.gradle.api.tasks.* -import java.io.BufferedReader -import java.io.InputStreamReader - - -//import java.util.regex.Pattern +import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.InputFile +import org.gradle.api.tasks.Optional +import org.gradle.api.tasks.OutputDirectory +import org.gradle.api.tasks.TaskAction +import java.util.concurrent.TimeUnit abstract class JLinkTask : DefaultTask() { -// companion object { -// val pattern: Pattern = Pattern.compile(".*\\b(java\\..*|javax\\..*)\\b.*\$") -// } - @get:InputDirectory abstract val jdkDirectory: DirectoryProperty @@ -31,105 +27,46 @@ abstract class JLinkTask : DefaultTask() { @TaskAction fun run() { - // Ensure the output directory is clean + // jlink expects non-existent output directory val outputDirectoryFile = outputDirectory.asFile.get() - if (outputDirectoryFile.exists() && outputDirectoryFile.listFiles()?.isNotEmpty() == true) { - // In case you want to run it manually, this will stop the plugin from running the task - logger.lifecycle("custom jre already created, skipping - see: ${jdkDirectory.get()}") - } else { - if (!outputDirectoryFile.canWrite()) { - throw IllegalStateException("Output directory is not writable: ${outputDirectoryFile.absolutePath}") - } - outputDirectoryFile.deleteRecursively() - - logger.lifecycle("JDK path: ${jdkDirectory.get()}") - - // Construct the jlink command - val jLinkPath = jdkDirectory.asFile.get().toPath().resolve("bin").resolve("jlink") - val processBuilder = ProcessBuilder( + outputDirectoryFile.deleteRecursively() + + val jLinkPath = jdkDirectory.asFile.get().toPath().resolve("bin").resolve("jlink") + val processBuilder = ProcessBuilder( jLinkPath.toAbsolutePath().toString(), - "--verbose", + "--add-modules", parseUsedJavaModulesFromJDepsOutput(), - "--include-locales=en,cs,de,es,it,pcm,pt-BR", + "--strip-native-commands", "--no-header-files", "--no-man-pages", - "--compress=2", -// "--strip-debug", // makes jlink fail in some platforms like Ubuntu linux -// "--add-reads", "java.base=ALL-UNNAMED", + "--strip-debug", + "--output", outputDirectoryFile.absolutePath - ) - logger.lifecycle("Executing jlink command: ${processBuilder.command().joinToString(" ")}") - - // Add module path if specified - if (javaModulesDirectory.isPresent) { - val commands = processBuilder.command() - commands.add("--module-path") - commands.add(javaModulesDirectory.asFile.get().absolutePath) - logger.lifecycle("Executing jlink command: ${commands.joinToString(" ")}") - } - - logger.lifecycle("Preparing process builder..") - processBuilder.inheritIO() - - logger.lifecycle("Starting process builder..") - val process = processBuilder.start() - if (System.getProperty("os.name").lowercase().contains("windows")) { - val reader = - BufferedReader(InputStreamReader(process.inputStream)) - while ((reader.readLine()) != null) { - // WORKAROUND: Jlink hangs in windows (11pro) when running from this custom plugin - // This buffer reader is needed jus to get it going and won't affect the rest of the platforms - } - } - logger.lifecycle("Reading errors..") - val errorOutput = process.errorStream.bufferedReader().readText() - val exitCode = process.waitFor() - - if (exitCode != 0) { - logger.error("jlink error output:\n$errorOutput") - throw IllegalStateException("jlink couldn't create custom runtime. Exit code: $exitCode") - } + ) + + if (javaModulesDirectory.isPresent) { + val commands = processBuilder.command() + commands.add("--module-path") + commands.add(javaModulesDirectory.asFile.get().absolutePath) + } + + processBuilder.inheritIO() + + val process = processBuilder.start() + process.waitFor(2, TimeUnit.MINUTES) + + val isSuccess = process.exitValue() == 0 + if (!isSuccess) { + throw IllegalStateException("jlink couldn't create custom runtime.") } } private fun parseUsedJavaModulesFromJDepsOutput(): String { -// TODO instead of hardcoding he modules process the jdeps report and generate the below so we don't need -// to touch this code again in case of needed new jmods in the future -// readLines.filter { pattern.matcher(it).matches() } -// .flatMap { line -> line.split("->").map { it.trim() } } -// .filter { it.startsWith("java.") || it == "bisq.desktop_app_launcher" } -// .flatMap { line -> line.split(",").map { it.trim() } } -// .distinct() -// .joinToString(",") -// val readLines = jDepsOutputFile.asFile.get().readLines() - val modules = listOf( - // base - "java.base", - "java.datatransfer", - "java.desktop", - "java.logging", - "java.xml", - "java.naming", - "java.net.http", - // security - "java.se", - "java.security.jgss", - // javafx - "javafx.base", - "javafx.controls", - "javafx.fxml", - "javafx.graphics", - "javafx.media", - "javafx.swing", -// "javafx.web", - // jdk - "jdk.unsupported", - "jdk.localedata", - "jdk.crypto.cryptoki", - "jdk.crypto.ec" - ).joinToString(",") - logger.lifecycle("Modules to be included: $modules") - return modules + var readLines = jDepsOutputFile.asFile.get().readLines() + if (!javaModulesDirectory.isPresent) { + readLines = readLines.filter { it.startsWith("java.") } + } + return readLines.joinToString(",") } -} \ No newline at end of file +} diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/PackagingPlugin.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/PackagingPlugin.kt index 6ccab14611..813ec53e06 100644 --- a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/PackagingPlugin.kt +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/PackagingPlugin.kt @@ -9,7 +9,8 @@ import org.gradle.api.file.Directory import org.gradle.api.file.RegularFile import org.gradle.api.plugins.JavaApplication import org.gradle.api.provider.Provider -import org.gradle.api.tasks.* +import org.gradle.api.tasks.Sync +import org.gradle.api.tasks.TaskProvider import org.gradle.jvm.tasks.Jar import org.gradle.jvm.toolchain.JavaLanguageVersion import org.gradle.jvm.toolchain.JavaToolchainService @@ -42,30 +43,10 @@ class PackagingPlugin @Inject constructor(private val javaToolchainService: Java val javaApplicationExtension = project.extensions.findByType() checkNotNull(javaApplicationExtension) { "Can't find JavaApplication extension." } - val createCustomJre = project.tasks.register("createCustomJre") { - dependsOn(project.tasks.named("jdepsReport")) - - jdkDirectory.set(getJPackageJdkDirectory(extension)) - jDepsOutputFile.set(getBuildFileOf(project, "reports/jdeps/jdeps-main.txt")) - outputDirectory.set(project.layout.buildDirectory.dir("custom-jre")) - - doLast { - println("JLink configuration:") - println("JDK Directory: ${jdkDirectory.get()}") - println("JDeps Output File: ${jDepsOutputFile.get()}") - println("Output Directory: ${outputDirectory.get()}") - } - } - project.tasks.register("generateInstallers") { group = "distribution" description = "Generate the installer or the platform the project is running" - dependsOn(createCustomJre) - - // Set the runtime image to the output of JLinkTask - runtimeImageDirectory.set(createCustomJre.flatMap { it.outputDirectory }) - val webcamProject = project.parent?.childProjects?.filter { e -> e.key == "webcam-app" }?.map { e -> e.value.project }?.first() webcamProject?.let { webcam -> val desktopProject = project.parent?.childProjects?.filter { e -> e.key == "desktop" }?.map { e -> e.value.project }?.first() @@ -100,6 +81,10 @@ class PackagingPlugin @Inject constructor(private val javaToolchainService: Java val packageResourcesDirFile = File(project.projectDir, "package") packageResourcesDir.set(packageResourcesDirFile) + runtimeImageDirectory.set( + getJPackageJdkDirectory(extension) + ) + outputDirectory.set(project.layout.buildDirectory.dir("packaging/jpackage/packages")) } @@ -142,8 +127,4 @@ class PackagingPlugin @Inject constructor(private val javaToolchainService: Java } return javaVersion.map { JavaLanguageVersion.of(it) } } - - private fun getBuildFileOf(project: Project, relativePath: String): RegularFile { - return project.layout.buildDirectory.file(relativePath).get() - } }