使用jlink 构建包含JavaFX 模块的Java 运行时。
使用 jpackage(来自 JDK 14 及更高版本)使用该运行时捆绑您的应用程序。这将为您提供 .exe 启动器和特定于平台的安装程序。
Gradle 'Exec' 任务可以轻松地为您运行这两个工具作为构建的一部分。
为使事情变得更简单,您可以考虑使用包含 JavaFX 模块的 JDK,这样您就不必费心配置 JavaFX SDK 和模块路径。
Azul 和 Bellsoft 的 OpenJDK 版本包含 JavaFX。
这是我在 jpackage 中使用的那种任务的示例。我的“appImage”任务复制文件以准备捆绑,我的 jlink 任务创建运行时映像。此任务创建一个可运行的应用程序映像,我将其用于第二次调用 jpackage 以生成安装程序。如果您不需要安装程序,您也可以只压缩此图像,但每个图像都是特定于平台的,因为它包含本机启动器和要使用的 JRE:
task jpackageImage(type: Exec, dependsOn: [jlink, appImage]) {
workingDir = project.projectDir
inputs.property('consoleApp', project.consoleApp)
inputs.property('vendorName', project.vendorName)
if (project.hasProperty('copyright')) {
inputs.property('copyright', project.copyright)
}
// TODO set input directory
inputs.dir "${buildDir}${File.separator}image${File.separator}app"
inputs.dir "${buildDir}${File.separator}image${File.separator}runtime"
// define outputs
outputs.dir "${buildDir}${File.separator}application"
// in a doFirst in case values change (e.g. archive name gets version bump)
// after configuration phase
doFirst {
// Error: Application output directory XXXXXXXXXXXXXX already exists.
def tmpRoot = "$buildDir/tmp/image"
project.delete tmpRoot
project.delete "${buildDir}${File.separator}application"
// resource directories need to exist
project.mkdir resourceDir
//file("${buildDir}/image/app/README.txt").text = "This file should be installed."
def appName = project.applicationName // project.applicationName.replaceAll(" ","")
def copyrightStr = project.hasProperty('copyright') ? project.copyright.toString() : "Copyright (c) ${year} ${vendorName}".toString().trim()
def tmp = [
"${jpackageTool}",
'--type', 'app-image', // Valid values on Windows are: {"app-image", "exe", "msi"}
'--verbose',
'--temp', tmpRoot,
'--app-version', project.version,
'--input', "${buildDir}${File.separator}image${File.separator}app",
'--runtime-image', "${buildDir}${File.separator}image${File.separator}runtime",
'--name', appName,
'--main-jar', "libs${File.separator}${configurations.runtime.artifacts.files.singleFile.name}",
'--main-class', mainClass,
'--resource-dir', resourceDir,
'--icon', iconFileStr,
'--description', project.description,
'--vendor', vendorName,
//'--category', 'Utility',
'--copyright', copyrightStr,
'--dest', "${buildDir}${File.separator}application",
]
// Use a console app for easier debugging (log messages/debug prints are visible)
if (osName.startsWith('windows')) {
// Windows-specific options
//'--win-menu',
//'--win-menu-group', vendorName,
//'--win-upgrade-uuid', project.upgradeUUID,
//'--win-shortcut',
// for a console application
if (project.consoleApp) {
tmp.addAll(['--win-console'])
}
}
if (osName.startsWith('mac')) {
tmp.addAll([
// macOS-specific options
//This name must be less than 16 characters long and be suitable for displaying in the menu bar and the application Info window.
'--mac-package-name', project.macPkgName,
'--mac-package-identifier', project.macPkgIndentifier,
//'--mac-package-signing-prefix', <prefix string>,
//'--mac-sign', // Request that the bundle be signed
//'--mac-signing-keychain', <file path>,
//'--mac-signing-key-user-name', '<team name>'
])
}
commandLine = tmp
println commandLine
}
// workaround https://bugs.openjdk.java.net/browse/JDK-8254920
doLast {
if (osName.startsWith('windows') && jlinkCompression == 2) {
project.copy {
from "${buildDir}\\application\\${project.applicationName}\\runtime\\bin\\zip.dll"
into "${buildDir}\\application\\${project.applicationName}"
}
}
}
}
我真的应该在某个时候为这些东西制作一个合适的 Gradle 插件。
您可以在https://docs.oracle.com/en/java/javase/14/docs/specs/man/jpackage.html了解更多关于 jpackage 的信息