如何基于Kotlin Gradle DSL创建平台无关的JavaFX可执行Jar
JavaFX项目Gradle配置问题:无法运行Main类及生成平台无关Jar包
我们团队维护着一个以Swing为核心的大型遗留Java应用,我负责开发一个独立分支项目:基于Temurin JDK 21(未捆绑JavaFX)、采用Kotlin Gradle DSL管理的JavaFX项目,包含UI面板、业务逻辑,以及两个用于独立测试的main方法(分别位于Main.java和Planner.java中)。
我需要将该项目发布到公司的Artefactory,但当前的build.gradle.kts配置无法满足以下两个需求:
- 无法运行带有main方法的类;
- 无法生成不依赖平台特定JavaFX实现的Jar包。
当前配置代码如下:
import org.gradle.internal.os.OperatingSystem plugins { java application `maven-publish` // I can't imagine this is necessary but my module isn't able to import JavaFX without it. id("org.openjfx.javafxplugin") version "0.0.14" } java { toolchain { languageVersion.set(JavaLanguageVersion.of(21)) } } val isRelease = project.hasProperty("release") val appVersion = "0.1" + if (isRelease) "" else "-SNAPSHOT" val modulePath by lazy { "${configurations.runtimeClasspath.get().asPath}:build/classes/java/main" } val moduleString by lazy { javafx.modules.joinToString(separator = ",") } application { version = appVersion group = "my.organization.subproject" mainClass.set("my.organization.subproject.fx.Main") mainModule.set("AutoMosaic") } repositories { mavenCentral() } javafx { version = "21" modules("javafx.controls", "javafx.swing") // When this is enabled, I cannot run the classes with Main methods. configuration = "compileOnly" } val javafxPlatform: String = when { OperatingSystem.current().isMacOsX && System.getProperty("os.arch") == "aarch64" -> "mac-aarch64" // ARM Mac OperatingSystem.current().isMacOsX && System.getProperty("os.arch") == "x86_64" -> "mac" // Intel Mac OperatingSystem.current().isWindows -> "win" OperatingSystem.current().isLinux -> "linux" else -> throw GradleException("Unsupported OS for JavaFX") } dependencies { // In an attempt to only rely on platform-neutral dependencies. compileOnly("org.openjfx:javafx-base:21") compileOnly("org.openjfx:javafx-controls:21") compileOnly("org.openjfx:javafx-graphics:21") compileOnly("org.openjfx:javafx-swing:21") // To execute Main and Planner locally. runtimeOnly("org.openjfx:javafx-base:21:$javafxPlatform") runtimeOnly("org.openjfx:javafx-controls:21:$javafxPlatform") runtimeOnly("org.openjfx:javafx-graphics:21:$javafxPlatform") runtimeOnly("org.openjfx:javafx-swing:21:$javafxPlatform") } // To create the Main and Planner Gradle tasks that can be run. fun createJavaExecTask(taskName: String, mainClassName: String) { tasks.register<JavaExec>(taskName) { group = "application" mainClass.set(mainClassName) jvmArgs = listOf( "--module-path", modulePath, "--add-modules", moduleString ) classpath = sourceSets["main"].runtimeClasspath } } // To run these through IDEA, configure Gradle tasks with Tasks and Arguments: // 1. Main: main // 2. Planner: planner // Then they should be runnable via IDEA. The issue is that the module path for the JavaFX jars // managed by the plugin are incredibly obtuse and can change, so even grabbing them and // hard-coding them in an Application task yields issues. createJavaExecTask("main", "my.organization.subproject.fx.Main") createJavaExecTask("planner", "my.organization.subproject.fx.Planner") // Print the arguments necessary to configure an IDEA task. tasks.register("jvmOpts") { doLast { println("JVM opts required to make an IDEA task:") println("--module-path $modulePath --add-modules $moduleString") } } val repositoryUrl = "https://jfrog.organization.edu/artifactory/apt-maven" val sourcesJar by tasks.registering(Jar::class) { from(sourceSets.main.get().allSource) archiveClassifier.set("sources") } publishing { publications { create<MavenPublication>("mavenJava") { groupId = "my.organization.mainproject" from(components["java"]) artifact(sourcesJar.get()) } } repositories { maven { val repoPassword: String? by project val repoUsername: String? by project url = uri(repositoryUrl + (if (project.hasProperty("release")) { "-releases" } else { "-snapshots" })) credentials { username = repoUsername password = repoPassword } } } }
内容的提问来源于stack exchange,提问作者Sebastian
相关产品推荐
相关产品推荐

