From 5bbc941c2c0b43d9b106240bb620f08d153a9acc Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Fri, 8 Sep 2023 13:02:04 +0200 Subject: [PATCH 1/3] Add Gradle Toolchain Resolver --- gradle/verification-metadata.xml | 26 ++++++++++++++++++++++++++ settings.gradle | 14 ++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/gradle/verification-metadata.xml b/gradle/verification-metadata.xml index 67c9b8bf69d..6f9917f32b1 100644 --- a/gradle/verification-metadata.xml +++ b/gradle/verification-metadata.xml @@ -312,6 +312,14 @@ + + + + + + + + @@ -327,6 +335,11 @@ + + + + + @@ -1260,6 +1273,19 @@ + + + + + + + + + + + + + diff --git a/settings.gradle b/settings.gradle index 5f45142f94f..4f3b196ff9e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -5,6 +5,20 @@ pluginManagement { includeBuild('build-logic') } +plugins { + id("org.gradle.toolchains.foojay-resolver") version "0.7.0" +} + +toolchainManagement { + jvm { + javaRepositories { + repository("foojay") { + resolverClass = org.gradle.toolchains.foojay.FoojayToolchainResolver + } + } + } +} + include 'proto' include 'assets' include 'common' From 7a03bd24bd47fb4be0261b79ca52e767cbbce3c5 Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Fri, 8 Sep 2023 13:03:29 +0200 Subject: [PATCH 2/3] Gradle: Enforce same JDK everywhere --- .github/workflows/build.yml | 2 +- .../commons/src/main/groovy/bisq.java-conventions.gradle | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d272641a214..2a9d58af82d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -13,7 +13,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macOS-latest, windows-latest] - java: [ '11', '11.0.3', '15', '15.0.5'] + java: ['11'] name: Test Java ${{ matrix.Java }}, ${{ matrix.os }} steps: - uses: actions/checkout@v4.0.0 diff --git a/build-logic/commons/src/main/groovy/bisq.java-conventions.gradle b/build-logic/commons/src/main/groovy/bisq.java-conventions.gradle index 08c9fb5d904..99e87d2026f 100644 --- a/build-logic/commons/src/main/groovy/bisq.java-conventions.gradle +++ b/build-logic/commons/src/main/groovy/bisq.java-conventions.gradle @@ -8,8 +8,13 @@ repositories { maven { url "https://jitpack.io" } } -sourceCompatibility = JavaVersion.VERSION_11 -targetCompatibility = JavaVersion.VERSION_11 +java { + toolchain { + languageVersion = JavaLanguageVersion.of(11) + vendor = JvmVendorSpec.AZUL + implementation = JvmImplementation.VENDOR_SPECIFIC + } +} tasks.withType(JavaCompile) { options.encoding = 'UTF-8' From aaaa039b2089de10a4f2ea35f5e1e2ca589deb90 Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Sat, 9 Sep 2023 18:50:20 +0200 Subject: [PATCH 3/3] Implement PackagingPlugin Supported packages: - DEB - DMG - EXE - RPM --- .../bisq/gradle/packaging/JPackageTask.kt | 76 ++++++++++++++----- .../main/kotlin/bisq/gradle/packaging/OS.kt | 32 ++++++++ .../bisq/gradle/packaging/PackagingPlugin.kt | 63 ++++++++++++++- .../packaging/jpackage/JPackageAppConfig.kt | 8 ++ .../packaging/jpackage/JPackageConfig.kt | 12 +++ .../packaging/jpackage/PackageFactory.kt | 50 ++++++++++++ .../JPackagePackageFormatConfigs.kt | 6 ++ .../jpackage/package_formats/LinuxPackages.kt | 36 +++++++++ .../jpackage/package_formats/MacPackage.kt | 12 +++ .../jpackage/package_formats/PackageFormat.kt | 8 ++ .../package_formats/WindowsPackage.kt | 18 +++++ desktop/build.gradle | 1 + .../package/macosx/replace_version_number.sh | 1 + 13 files changed, 303 insertions(+), 20 deletions(-) create mode 100644 build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/OS.kt create mode 100644 build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/JPackageAppConfig.kt create mode 100644 build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/JPackageConfig.kt create mode 100644 build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/PackageFactory.kt create mode 100644 build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/JPackagePackageFormatConfigs.kt create mode 100644 build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/LinuxPackages.kt create mode 100644 build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/MacPackage.kt create mode 100644 build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/PackageFormat.kt create mode 100644 build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/WindowsPackage.kt diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/JPackageTask.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/JPackageTask.kt index 8f705ed9d87..dc00e9370ef 100644 --- a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/JPackageTask.kt +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/JPackageTask.kt @@ -1,13 +1,19 @@ package bisq.gradle.packaging +import bisq.gradle.packaging.jpackage.JPackageAppConfig +import bisq.gradle.packaging.jpackage.JPackageConfig +import bisq.gradle.packaging.jpackage.PackageFactory +import bisq.gradle.packaging.jpackage.package_formats.JPackagePackageFormatConfigs +import bisq.gradle.packaging.jpackage.package_formats.LinuxPackages +import bisq.gradle.packaging.jpackage.package_formats.MacPackage +import bisq.gradle.packaging.jpackage.package_formats.WindowsPackage import org.gradle.api.DefaultTask import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property -import org.gradle.api.tasks.Input -import org.gradle.api.tasks.InputDirectory -import org.gradle.api.tasks.OutputDirectory -import org.gradle.api.tasks.TaskAction -import java.util.concurrent.TimeUnit +import org.gradle.api.provider.SetProperty +import org.gradle.api.tasks.* +import java.io.File abstract class JPackageTask : DefaultTask() { @@ -15,14 +21,23 @@ abstract class JPackageTask : DefaultTask() { abstract val jdkDirectory: DirectoryProperty @get:InputDirectory - abstract val jarsDirectory: DirectoryProperty + abstract val distDirFile: Property - @get:Input - abstract val mainJar: Property + @get:InputFile + abstract val mainJarFile: RegularFileProperty @get:Input abstract val mainClassName: Property + @get:Input + abstract val jvmArgs: SetProperty + + @get:Input + abstract val appVersion: Property + + @get:InputDirectory + abstract val packageResourcesDir: DirectoryProperty + @get:InputDirectory abstract val runtimeImageDirectory: DirectoryProperty @@ -32,20 +47,43 @@ abstract class JPackageTask : DefaultTask() { @TaskAction fun run() { val jPackagePath = jdkDirectory.asFile.get().toPath().resolve("bin").resolve("jpackage") - val processBuilder = ProcessBuilder( - jPackagePath.toAbsolutePath().toString(), - "--dest", outputDirectory.asFile.get().absolutePath, - "--name", "Bisq", - "--input", jarsDirectory.asFile.get().absolutePath, - "--main-jar", mainJar.get(), - "--main-class", mainClassName.get(), + val jPackageConfig = JPackageConfig( + inputDirPath = distDirFile.get().toPath().resolve("lib"), + outputDirPath = outputDirectory.asFile.get().toPath(), + runtimeImageDirPath = runtimeImageDirectory.asFile.get().toPath(), + + appConfig = JPackageAppConfig( + appVersion = appVersion.get(), + mainJarFileName = mainJarFile.asFile.get().name, + mainClassName = mainClassName.get(), + jvmArgs = jvmArgs.get() + ), - "--runtime-image", runtimeImageDirectory.asFile.get().absolutePath + packageFormatConfigs = getPackageFormatConfigs() ) - processBuilder.inheritIO() - val process = processBuilder.start() - process.waitFor(15, TimeUnit.MINUTES) + val packageFactory = PackageFactory(jPackagePath, jPackageConfig) + packageFactory.createPackages() + } + + private fun getPackageFormatConfigs(): JPackagePackageFormatConfigs { + val packagePath = packageResourcesDir.asFile.get().toPath() + return when (getOS()) { + OS.WINDOWS -> { + val resourcesPath = packagePath.resolve("windows") + WindowsPackage(resourcesPath) + } + + OS.MAC_OS -> { + val resourcesPath = packagePath.resolve("macosx") + MacPackage(resourcesPath) + } + + OS.LINUX -> { + val resourcesPath = packagePath.resolve("linux") + LinuxPackages(resourcesPath) + } + } } } diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/OS.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/OS.kt new file mode 100644 index 00000000000..419404234fe --- /dev/null +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/OS.kt @@ -0,0 +1,32 @@ +package bisq.gradle.packaging + +import java.util.* + +enum class OS { + LINUX, MAC_OS, WINDOWS +} + +fun getOS(): OS { + val osName = System.getProperty("os.name").toLowerCase(Locale.US) + if (isLinux(osName)) { + return OS.LINUX + } else if (isMacOs(osName)) { + return OS.MAC_OS + } else if (isWindows(osName)) { + return OS.WINDOWS + } + + throw IllegalStateException("Running on unsupported OS: $osName") +} + +private fun isLinux(osName: String): Boolean { + return osName.contains("linux") +} + +private fun isMacOs(osName: String): Boolean { + return osName.contains("mac") || osName.contains("darwin") +} + +private fun isWindows(osName: String): Boolean { + return osName.contains("win") +} 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 f7f2e546982..18a52b730d3 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 @@ -2,8 +2,69 @@ package bisq.gradle.packaging import org.gradle.api.Plugin import org.gradle.api.Project +import org.gradle.api.file.Directory +import org.gradle.api.plugins.JavaApplication +import org.gradle.api.plugins.JavaPluginExtension +import org.gradle.api.provider.Provider +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 +import org.gradle.jvm.toolchain.JvmImplementation +import org.gradle.jvm.toolchain.JvmVendorSpec +import org.gradle.kotlin.dsl.findByType +import org.gradle.kotlin.dsl.register +import java.io.File +import javax.inject.Inject + +class PackagingPlugin @Inject constructor(private val javaToolchainService: JavaToolchainService) : Plugin { + + companion object { + const val APP_VERSION = "1.9.12" + } -class PackagingPlugin : Plugin { override fun apply(project: Project) { + val installDistTask: TaskProvider = project.tasks.named("installDist", Sync::class.java) + val jarTask: TaskProvider = project.tasks.named("jar", Jar::class.java) + + val javaApplicationExtension = project.extensions.findByType() + checkNotNull(javaApplicationExtension) { "Can't find JavaApplication extension." } + + project.tasks.register("generateInstaller") { + jdkDirectory.set(getJdk17Directory()) + + distDirFile.set(installDistTask.map { it.destinationDir }) + mainJarFile.set(jarTask.flatMap { it.archiveFile }) + + mainClassName.set(javaApplicationExtension.mainClass) + jvmArgs.set(javaApplicationExtension.applicationDefaultJvmArgs) + + appVersion.set(APP_VERSION) + + val packageResourcesDirFile = File(project.projectDir, "package") + packageResourcesDir.set(packageResourcesDirFile) + + runtimeImageDirectory.set(getProjectJdkDirectory(project)) + outputDirectory.set(project.layout.buildDirectory.dir("packaging/jpackage/packages")) + } + } + + private fun getProjectJdkDirectory(project: Project): Provider { + val javaExtension = project.extensions.findByType() + checkNotNull(javaExtension) { "Can't find JavaPluginExtension extension." } + + val toolchain = javaExtension.toolchain + val projectLauncherProvider = javaToolchainService.launcherFor(toolchain) + return projectLauncherProvider.map { it.metadata.installationPath } + } + + private fun getJdk17Directory(): Provider { + val jdk17LauncherProvider = javaToolchainService.launcherFor { + languageVersion.set(JavaLanguageVersion.of(17)) + vendor.set(JvmVendorSpec.AZUL) + implementation.set(JvmImplementation.VENDOR_SPECIFIC) + } + return jdk17LauncherProvider.map { it.metadata.installationPath } } } diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/JPackageAppConfig.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/JPackageAppConfig.kt new file mode 100644 index 00000000000..3a784fb1c83 --- /dev/null +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/JPackageAppConfig.kt @@ -0,0 +1,8 @@ +package bisq.gradle.packaging.jpackage + +data class JPackageAppConfig( + val appVersion: String, + val mainJarFileName: String, + val mainClassName: String, + val jvmArgs: Set, +) diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/JPackageConfig.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/JPackageConfig.kt new file mode 100644 index 00000000000..dd3a8f7c61a --- /dev/null +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/JPackageConfig.kt @@ -0,0 +1,12 @@ +package bisq.gradle.packaging.jpackage + +import bisq.gradle.packaging.jpackage.package_formats.JPackagePackageFormatConfigs +import java.nio.file.Path + +data class JPackageConfig( + val inputDirPath: Path, + val outputDirPath: Path, + val runtimeImageDirPath: Path, + val appConfig: JPackageAppConfig, + val packageFormatConfigs: JPackagePackageFormatConfigs +) diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/PackageFactory.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/PackageFactory.kt new file mode 100644 index 00000000000..a65f0906d6d --- /dev/null +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/PackageFactory.kt @@ -0,0 +1,50 @@ +package bisq.gradle.packaging.jpackage + +import java.nio.file.Path +import java.time.Year +import java.util.concurrent.TimeUnit + + +class PackageFactory(private val jPackagePath: Path, private val jPackageConfig: JPackageConfig) { + + fun createPackages() { + val jPackageCommonArgs: List = createCommonArguments(jPackageConfig.appConfig) + + val packageFormatConfigs = jPackageConfig.packageFormatConfigs + val perPackageCommand = packageFormatConfigs.packageFormats + .map { packageFormatConfigs.createArgumentsForJPackage(it) + listOf("--type", it.fileExtension) } + + val absoluteBinaryPath = jPackagePath.toAbsolutePath().toString() + perPackageCommand.forEach { customCommands -> + val processBuilder = ProcessBuilder(absoluteBinaryPath) + .inheritIO() + + val allCommands = processBuilder.command() + allCommands.addAll(jPackageCommonArgs) + allCommands.addAll(customCommands) + + val process: Process = processBuilder.start() + process.waitFor(15, TimeUnit.MINUTES) + } + } + + private fun createCommonArguments(appConfig: JPackageAppConfig): List = + mutableListOf( + "--dest", jPackageConfig.outputDirPath.toAbsolutePath().toString(), + + "--name", "Bisq", + "--description", "A decentralized bitcoin exchange network.", + "--copyright", "Copyright © 2013-${Year.now()} - The Bisq developers", + "--vendor", "Bisq", + + "--app-version", appConfig.appVersion, + + "--input", jPackageConfig.inputDirPath.toAbsolutePath().toString(), + "--main-jar", appConfig.mainJarFileName, + + "--main-class", appConfig.mainClassName, + "--java-options", appConfig.jvmArgs.joinToString(separator = " "), + + "--runtime-image", jPackageConfig.runtimeImageDirPath.toAbsolutePath().toString() + ) +} diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/JPackagePackageFormatConfigs.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/JPackagePackageFormatConfigs.kt new file mode 100644 index 00000000000..aade9e29de0 --- /dev/null +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/JPackagePackageFormatConfigs.kt @@ -0,0 +1,6 @@ +package bisq.gradle.packaging.jpackage.package_formats + +interface JPackagePackageFormatConfigs { + val packageFormats: Set + fun createArgumentsForJPackage(packageFormat: PackageFormat): List +} diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/LinuxPackages.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/LinuxPackages.kt new file mode 100644 index 00000000000..6fdace38480 --- /dev/null +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/LinuxPackages.kt @@ -0,0 +1,36 @@ +package bisq.gradle.packaging.jpackage.package_formats + +import java.nio.file.Path + +class LinuxPackages(private val resourcesPath: Path) : JPackagePackageFormatConfigs { + override val packageFormats = setOf(PackageFormat.DEB, PackageFormat.RPM) + + override fun createArgumentsForJPackage(packageFormat: PackageFormat): List { + val arguments = mutableListOf( + "--icon", + resourcesPath.resolve("icon.png") + .toAbsolutePath().toString(), + + "--linux-package-name", "bisq", + "--linux-app-release", "1", + + "--linux-menu-group", "Network", + "--linux-shortcut", + + "--linux-deb-maintainer", + "noreply@bisq.network", + ) + + if (packageFormat == PackageFormat.DEB) { + arguments.add("--linux-deb-maintainer") + arguments.add("noreply@bisq.network") + } + + if (packageFormat == PackageFormat.RPM) { + arguments.add("--linux-rpm-license-type") + arguments.add("AGPLv3") + } + + return arguments + } +} diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/MacPackage.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/MacPackage.kt new file mode 100644 index 00000000000..df19c9bfdb3 --- /dev/null +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/MacPackage.kt @@ -0,0 +1,12 @@ +package bisq.gradle.packaging.jpackage.package_formats + +import java.nio.file.Path + +class MacPackage(private val resourcesPath: Path) : JPackagePackageFormatConfigs { + override val packageFormats = setOf(PackageFormat.DMG) + + override fun createArgumentsForJPackage(packageFormat: PackageFormat): List = + mutableListOf( + "--resource-dir", resourcesPath.toAbsolutePath().toString(), + ) +} diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/PackageFormat.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/PackageFormat.kt new file mode 100644 index 00000000000..2769b011acb --- /dev/null +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/PackageFormat.kt @@ -0,0 +1,8 @@ +package bisq.gradle.packaging.jpackage.package_formats + +enum class PackageFormat(val fileExtension: String) { + DEB("deb"), + DMG("dmg"), + EXE("exe"), + RPM("rpm") +} diff --git a/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/WindowsPackage.kt b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/WindowsPackage.kt new file mode 100644 index 00000000000..50a86975462 --- /dev/null +++ b/build-logic/packaging/src/main/kotlin/bisq/gradle/packaging/jpackage/package_formats/WindowsPackage.kt @@ -0,0 +1,18 @@ +package bisq.gradle.packaging.jpackage.package_formats + +import java.nio.file.Path + +class WindowsPackage(private val resourcesPath: Path) : JPackagePackageFormatConfigs { + override val packageFormats = setOf(PackageFormat.EXE) + + override fun createArgumentsForJPackage(packageFormat: PackageFormat): List = + mutableListOf( + "--icon", resourcesPath.resolve("Bisq.ico").toAbsolutePath().toString(), + "--resource-dir", resourcesPath.toAbsolutePath().toString(), + + "--win-dir-chooser", + "--win-per-user-install", + "--win-menu", + "--win-shortcut", + ) +} diff --git a/desktop/build.gradle b/desktop/build.gradle index 48d241d94e6..ea5bb10f492 100644 --- a/desktop/build.gradle +++ b/desktop/build.gradle @@ -1,6 +1,7 @@ plugins { id 'bisq.application' id 'bisq.javafx' + id 'bisq.gradle.packaging.PackagingPlugin' id "com.github.johnrengelman.shadow" version "5.2.0" } diff --git a/desktop/package/macosx/replace_version_number.sh b/desktop/package/macosx/replace_version_number.sh index f72686f009c..3113b1318aa 100755 --- a/desktop/package/macosx/replace_version_number.sh +++ b/desktop/package/macosx/replace_version_number.sh @@ -17,6 +17,7 @@ find . -type f \( -name "finalize.sh" \ \) -exec sed -i '' s/"$oldVersion-SNAPSHOT"/$newVersion/ {} + find . -type f \( -name "Info.plist" \ +-o -name "PackagingPlugin.kt" \ -o -name "SeedNodeMain.java" \ -o -name "Version.java" \ -o -name "copy_dbs.sh" \