Introduction
The badass-jlink plugin allows you to create custom runtime images for modular applications with minimal effort. It also lets you create an application installer with the jpackage tool.
For non-modular applications use the Badass-Runtime plugin. |
Many modular applications have one or more non-modular dependencies, which are treated as automatic modules by the Java platform. However, jlink cannot work with automatic modules. The typical way to solve this problem is to convert the non-modular jars to explicit modules, by adding an appropriate module descriptor to each non-modular jar. This is a tedious process if your application has lots of non-modular dependencies.
The badass-jlink plugin takes a more pragmatic approach by combining all non-modular dependencies into a single jar. This way, only the resulting merged module needs a module descriptor.
The plugin provides several tasks. The most frequently used are jlink
, which creates a custom runtime image in a given directory,
and jlinkZip
, which in addition creates a zip archive of the custom runtime image.
With the jpackage
task you can create a platform-specific installer for your application.
The current version of this plugin requires Java 17 and Gradle 7.4 or newer. While it might work with some combinations of older Java and Gradle versions, these are not officially supported. If you are forced to work with an older Gradle release, you should use the version 2.25.0 of this plugin. |
To use the plugin, include the following in your build script:
plugins {
id 'org.beryx.jlink' version '3.1.1'
}
Applying the Badass-JLink plugin also implicitly applies the Application plugin.
The plugin uses an extension named jlink
.
The sample below shows a few configuration options.
jlink {
options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
launcher{
name = 'hello'
jvmArgs = ['-Dlog4j.configurationFile=./log4j2.xml']
}
}
The next sections provide detailed information on how to configure the plugin.
The source code is available on GitHub and is licensed under the Apache-2.0 license. |
User Guide
Creating a custom runtime image can be a challenging task if your application has many non-modular dependencies.
To let you address all possible issues, badass-jlink allows you to configure the jlink
extension using various properties, methods and script blocks.
The operations required to create a custom runtime image are grouped in several tasks.
This gives you the possibility to tweak a particular step by hooking into the corresponding task
(via doFirst
, doLast
, TaskExecutionListener
or TaskActionListener
).
Tasks
- prepareMergedJarsDir
-
Unpacks all non-modular dependencies in a designated directory.
depends on:jar
- createMergedModule
-
Creates the merged module using the content of the directory prepared by the previous task and adding a module descriptor to it.
depends on:prepareMergedJarsDir
- createDelegatingModules
-
For each non-modular dependency, it creates a delegating module, which is an open module consisting only of a module descriptor. The module descriptor specifies that the delegating module
requires transitive
the merged module.
depends on:createMergedModule
- prepareModulesDir
-
Copies all modules needed by jlink to a designated directory.
depends on:createDelegatingModules
- jlink
-
Uses the jlink tool to create the custom runtime image.
depends on:prepareModulesDir
- jlinkZip
-
Creates a zip archive of the custom runtime image.
depends on:jlink
- suggestMergedModuleInfo
-
Displays the
mergedModule
block that will be used if yourjlink
extension doesn’t include one. You can use the suggested block as a starting point for your custommergedModule
block.
depends on:prepareMergedJarsDir
- jpackageImage
-
Uses the jpackage tool to create a platform-specific application image.
depends on:prepareModulesDir
- jpackage
-
Uses the jpackage tool to create a platform-specific application installer.
depends on:jpackageImage
A detailed description of these tasks is given in Task details
Properties
- imageDir
-
The directory into which the custom runtime image should be generated.
(If you use thetargetPlatform
method to generate images for other platforms, the corresponding images will be created in subdirectories ofimageDir
.)
defaultValue:buildDir/image
usage example:imageDir = file("$buildDir/myapp-image")
- imageZip
-
The file into which a zip archive of the custom runtime image should be created.
defaultValue:buildDir/image.zip
usage example:imageZip = file("$buildDir/myapp-image.zip")
- imageName
-
Convenience property for setting the values of both
imageDir
andimageZip
as follows:
imageDir ←buildDir/imageName
imageZip ←buildDir/imageName.zip
usage example:imageName = 'hello'
- jlinkBasePath
-
The path to the base directory that will be used by the plugin to store intermediate outputs.
defaultValue:buildDir/jlinkbase
usage example:jlinkBasePath = "$buildDir/my-jlinkbase"
- mainClass
-
The main class to be provided as part of the
--launcher
option of jlink.
defaultValue:application.mainClass
(from the Application plugin)
usage example:mainClass = 'org.example.MyApp'
- moduleName
-
The module name of this application.
defaultValue: the module name specified in this application’s module-info.java
usage example:moduleName = 'org.example.myapp'
- mergedModuleName
-
The name of the merged module.
defaultValue:moduleName.merged.module
usage example:mergedModuleName = 'org.example.myapp.merged.module'
- mergedModuleJarName
-
The base name of the jar containing the merged module.
defaultValue:archiveBaseName.merged.module
usage example:mergedModuleJarName = 'my-merged-module'
- mergedModuleJarVersion
-
The version of the merged module.
This property is deprecated and it will be removed in a future release. Use the version property of the mergedModule block instead. If both this property and the version property of the mergedModule block are used, version takes precedence.
defaultValue:project.version
usage example:mergedModuleJarVersion = '2.1.7'
- options
-
A list of options to be passed to jlink.
defaultValue: empty list
usage example:options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
- javaHome
-
The path to the JDK providing the tools needed by the plugin (javac, jar, jlink etc.).
defaultValue: the first non-empty value from:
- thebadass.jlink.java.home
system property
- theBADASS_JLINK_JAVA_HOME
environment variable
- the Java toolchain configured in the Gradle script
- thejava.home
system property (only if it points to a JRE containing thejavac
,jar
, andjlink
tools)
- theJAVA_HOME
environment variable
usage example:javaHome = '/usr/lib/jvm/open-jdk'
- configuration
-
The name of the Gradle dependency configuration used to execute your application.
defaultValue:'runtimeClasspath'
usage example:configuration = 'myAppRuntime'
Methods
- addOptions(String… options)
-
Adds options to be passed to jlink. It is an alternative way of setting the
options
property. You can call this method multiple times.
usage example:addOptions '--no-header-files', '--no-man-pages'
- forceMerge(String… jarPrefixes)
-
Instructs the plugin to include all dependencies matching the given prefixes into the merged module. (Note that these are prefixes of the names of the JAR files to be merged.)
This method is useful when the plugin should handle one or more modular jars as non-modular. You can call this method multiple times.
usage example:forceMerge 'slf4j'
- addExtraDependencies(String… jarPrefixes)
-
Instructs the plugin to treat all jars matching the given prefixes as dependencies of the merged module.
A typical situation where this method is needed involves libraries using JavaFX. Some libraries do not specify their JavaFX dependencies, because JavaFX was part of the JDK before being removed in Java 11.
IncludingaddExtraDependencies("javafx")
into thejlink
block solves this problem. - addExtraModulePath(String modulePath)
-
Instructs the plugin to include the specified
modulePath
in the list of paths passed to the--module-path
option of jlink.
You can call this method multiple times.
usage example:addExtraModulePath '/usr/lib/jmods'
- jarExclude(String jarPrefix, String… excludePatterns)
-
Instructs the
prepareMergedJarsDir
task to exclude some files and/or directories when unpacking the non-modular dependencies.
jarPrefix: prefix of the names of the JAR files for which the excludePatterns apply.
excludePatterns: ANT like exclude patterns.
usage example:jarExclude("netty", "**/license/")
- targetPlatform(String name, String jdkHome, List<String> options = [])
-
Instructs the plugin to generate an application image for a specific platform.
This method is not for configuring the installable packages produced by jpackage. See details
By default, the plugin generates an image for the platform it runs on. To create images for other platforms, you need to call thetargetPlatform
method (one call per target platform).
name: an identifier of your choice that will be appended to theimageDir
andimageZip
properties to determine the location of the image directory and of the image archive.
jdkHome: the path to the target platform JDK.
options: an optional list of platform-specific options. These options will pe passed to jlink in addition to those provided by theoptions
property of thejlink
extension.
NOTE: This is only a convenience method. There is a more powerfultargetPlatform
method (described below), which allows configuring additional parameters of the target platform.
Usage example
For a project named |
- targetPlatform(String name, Action<TargetPlatform> action)
-
This more powerful version of the
targetPlatform
method allows configuring the target platform parameters using a script block.
This method is not for configuring the installable packages produced by jpackage. See details
name: an identifier of your choice that will be appended to theimageDir
andimageZip
properties to determine the location of the image directory and of the image archive.
action: a script block for configuring the target platform parameters.
Parameters:
jdkHome: the path to the target platform JDK.
options: an optional list of platform-specific options.
Methods:
addOptions(String… options): an alternative way of setting theoptions
property.
addExtraModulePath(String path): pass the specified path to the--module-path
option of jlink.
This method can be used to specify the location of the platform-specific OpenJFX modules.
jdkDownload(String downloadUrl, Closure downloadConfig=null): helper method for setting jdkHome.
It downloads and unpacks a JDK distribution from the given URL.
The optional closure allows configuring the following parameters:
- downloadDir: the directory in which the distribution is downloaded and unpacked.
defaultValue:buildDir/jdks/targetPlatform-name
- archiveName: the name under which the archived distribution should be saved.
defaultValue:jdk
- archiveExtension: accepted values:tar.gz
andzip
.
defaultValue:null
(inferred from the URL)
- pathToHome: the relative path to the JDK home in the unpacked distribution.
defaultValue:null
(inferred by scanning the unpacked distribution)
- overwrite: iftrue
, the plugin overwrites an already existing distribution.
defaultValue:false
Usage example
|
- enableCds(Action<CdsData> action = null)
-
Experimental - requires Java 13 or newer
Enables Class Data Sharing (CDS).
action: an optional script block for configuring the class data sharing.
Parameters:
sharedArchiveFile: the path and name of the class data sharing archive file.
It supports the Mustache syntax and placeholders described in the launcher section.
defaultValue:
lib/server/<appName>.jsa
on Unix-like systems
bin\server\<appName>.jsa
on Windows
Usage example
or
When the When the NOTE: Start scripts are not included in the installable packages generated by |
Script blocks
The jlink
extension can also contain the script blocks detailed below.
mergedModule
The mergedModule
block allows you to configure the module descriptor of the merged module.
It provides a DSL that matches the syntax of the directives in a module declaration file (module-info.java),
but it requires quotes around the names of modules, services, and service implementation classes.
The plugin automatically exports all packages found in the merged module, therefore the DSL does not support exports
directives.
If a mergedModule
block appears in your build script, the generated module descriptor will contain the clauses specified in this block.
Otherwise, the module descriptor is created using the algorithm implemented by the suggestMergedModuleInfo
task.
- version
-
The version of the merged module.
defaultValue: the version of the main module, if available; otherwise, the project version
usage example:version = "1.0.0"
- additive
-
In many cases the suggested descriptor is just the right one for your merged module, so you don’t need to provide a
mergedModule
block. In some other cases the suggested descriptor is almost right, in the sense that it only misses one or a few clauses. In these cases you are allowed to configure only the missing clauses in themergedModule
block and instruct the plugin to add them to the suggested descriptor by setting the attributeadditive
to true.
defaultValue:false
usage example:additive = true
There are also situations where the suggested descriptor contains some unwanted clauses. The plugin provides a few methods that allow excluding these clauses:
- excludeRequires(String… modules)
-
Instructs the plugin to not generate
requires
clauses for the specified modules.
usage example:excludeRequires 'java.rmi', 'java-compiler'
- excludeUses(String… services)
-
Instructs the plugin to not generate
uses
clauses for the specified services.
usage example:excludeUses 'java.nio.file.spi.FileSystemProvider'
- excludeProvides(Map constraints)
-
Instructs the plugin to not generate
provides
clauses that match the specified constraints.
The following keys are allowed in the constraints map:
service: the qualified name of the service
implementation: the qualified name of the implementation class
servicePattern: the regular expression to be matched by the qualified name of the service
implementationPattern: the regular expression to be matched by the qualified name of the implementation class
usage example:excludeProvides servicePattern: 'org.codehaus.stax2.*'
By calling one of the above methods you automatically enable the additive mode.
This means that it’s no longer necessary to explicitly set the additive
property to true
.
Usage example
jlink {
...
mergedModule {
additive = true // redundant, because excludeXXX() methods are also present
requires 'java.desktop'
requires transitive 'java.sql'
uses 'java.sql.Driver'
provides 'java.sql.Driver' with 'org.hsqldb.jdbc.JDBCDriver'
excludeRequires 'java.compiler', 'java.rmi'
excludeUses 'org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory'
excludeProvides servicePattern: 'org.apache.logging.*'
}
...
}
jlink {
...
mergedModule {
additive = true // redundant, because excludeXXX() methods are also present
requires("java.desktop")
requiresTransitive("java.sql")
uses("java.sql.Driver")
provides("java.sql.Driver").with("org.hsqldb.jdbc.JDBCDriver")
excludeRequires("java.compiler", "java.rmi")
excludeUses("org.apache.logging.log4j.message.ThreadDumpMessage.ThreadInfoFactory")
excludeProvides(mapOf("servicePattern" to "org.apache.logging.*"))
}
...
}
launcher
The plugin generates script files for launching your application.
These script files can be customized by configuring the launcher
block.
Environment variables can be included by using the Mustache syntax,
that is, by enclosing their name between {{
and }}
.
Additionally, you can use the following placeholders:
-
{{BIN_DIR}}
- the bin directory of the custom runtime image -
{{HOME_DIR}}
- user’s home directory ($HOME
on Unix-like systems,%USERPROFILE%
on Windows)- name
-
The base name of the script files used to launch your application.
defaultValue:project.name
- jvmArgs
-
list of JVM arguments to be passed to the java executable.
defaultValue: the arguments configured in theapplicationDefaultJvmArgs
property of theapplication
extension - args
-
list of arguments to be passed to the application.
defaultValue: the arguments configured in theargs
property of therun
task - noConsole
-
This boolean property has an effect only on Windows. It is ignored on other platforms.
If true, the application will be launched without an associated console window (usingjavaw
instead ofjava
).
defaultValue: false - unixScriptTemplate
-
the template for generating the script file for Unix-like systems.
defaultValue: null (the plugin uses its own template) - windowsScriptTemplate
-
the template for generating the script file for Windows-based systems.
defaultValue: null (the plugin uses its own template)
The plugin uses Groovy’s SimpleTemplateEngine to parse the templates, with the following variables available:
-
moduleName
-
mainClassName
-
jvmArgs
-
args
Usage example
jlink {
...
launcher {
name = 'my-app'
jvmArgs = [
'-Dlog4j.debug=true', '-Dlog4j.configurationFile={{BIN_DIR}}/log4j2.xml',
'-DdbHost', '{{PGHOST}}'
]
args = ['--user', 'alice']
unixScriptTemplate = file('unixStartScript.txt')
windowsScriptTemplate = file('windowsStartScript.txt')
}
...
}
jlink {
...
launcher {
name = "my-app"
jvmArgs = listOf(
"-Dlog4j.debug=true", "-Dlog4j.configurationFile={{BIN_DIR}}/log4j2.xml",
"-DdbHost", "{{PGHOST}}"
)
args = listOf("--user", "alice")
unixScriptTemplate = file("unixStartScript.txt")
windowsScriptTemplate = file("windowsStartScript.txt")
}
...
}
secondaryLauncher
The plugin can generate script files for additional applications besides the main one.
For each additional application you configure a secondaryLauncher
block.
This block supports all properties of the launcher
block and also the following ones:
- mainClass
-
the main class of this additional application.
- moduleName
-
the module containing the main class of this additional application.
defaultValue: the value of themoduleName
property in the enclosingjlink
extension
The following properties affect only the launchers produced by jpackage:
- icon
-
the path to the icon used for this additional launcher.
defaultValue: null (the icon of the main launcher is used) - winConsole
-
boolean value specifying whether Windows should start the application in a console window.
defaultValue: null (the win-console settings of the main launcher are used)
Usage example
jlink {
...
secondaryLauncher {
name = 'my-additional-app'
mainClass = 'org.example.MyAdditionalApp'
args = ['--user', 'emma']
}
...
}
jlink {
...
launcher {
name = "my-additional-app"
mainClass = "org.example.MyAdditionalApp"
args = listOf("--user", "emma")
}
...
}
customImage
By default, all application modules are included in the custom runtime image. This block allows you to create a custom runtime image containing only some of the application modules.
If the customImage
block is empty, the plugin will create a JRE containing only the JDK modules required by your application.
The plugin figures out by itself which JDK modules are needed, but you can use the below property to request a different set of modules.
- jdkModules
-
list of JDK modules to be included in the generated image.
defaultValue: null (the plugin figures out by itself which JDK modules are needed) - jdkAdditive
-
if true, the custom image will contain both the modules in the
jdkModules
list and the JDK modules identified as required by the plugin itself. defaultValue: false - appModules
-
list of application modules to be included in the generated image.
Modules required by those in this list will be automatically included.
defaultValue: null (no application modules are included)
Usage example
jlink {
...
mergedModuleName = 'my.merged.module'
customImage {
jdkModules = ['java.desktop', 'java.xml', 'jdk.unsupported']
appModules = ['my.merged.module']
}
...
}
jlink {
...
mergedModuleName = "my.merged.module"
customImage {
jdkModules = listOf("java.desktop", "java.xml", "jdk.unsupported")
appModules = listOf("my.merged.module")
}
...
}
jpackage
This script block allows you to customize the jpackage-based generation of platform-specific application images and installers.
- jpackageHome
-
The path to the JDK providing the jpackage tool.
defaultValue: the first non-empty value from:
- thebadass.jlink.jpackage.home
system property
- theBADASS_JLINK_JPACKAGE_HOME
environment variable
- the Java toolchain configured in the Gradle script
- thejava.home
system property (only if it points to a JRE containing thejpackage
tool)
- theJAVA_HOME
environment variable
usage example:jpackageHome = "/usr/lib/jvm/jdk16"
- outputDir
-
Convenience property for setting both
imageOutputDir
andinstallerOutputDir
with the value buildDir/outputDir.
defaultValue:"jpackage"
usage example:outputDir = "my-packaging"
- imageOutputDir
-
the directory passed as argument to the
--output
option ofjpackage
when executing thejpackageImage
task . defaultValue:buildDir/outputDir
usage example:imageOutputDir = file("$buildDir/my-packaging-image")
- imageName
-
the argument passed to the
--name
option when executing thejpackageImage
task.
defaultValue: thename
value configured in thelauncher
block orproject.name
usage example:imageName = "MyApp"
It’s recommended to use the same value as for the installerName property. - imageOptions
-
list of additional options to be passed to the
jpackage
executable when executing thejpackageImage
task.
defaultValue: empty list
usage example:imageOptions = ["--win-console"]
- resourceDir
-
the directory passed as argument to the
--resource-dir
option when runningjpackage
to create an application installer. It is also applicable when creating an application image when you want your own application image instead of the default java image.
usage example:resourceDir = file("$buildDir/my-packaging-resources")
- skipInstaller
-
boolean value that lets you generate only the platform-specific application image and skip the generation of the platform-specific application installer.
defaultValue: false
usage example:skipInstaller = true
- installerType
-
the type of installer to be generated.
defaultValue: null (all supported types for the current platform will be generated)
usage example:installerType = "rpm"
- installerOutputDir
-
the directory passed as argument to the
--output
option when runningjpackage
when executing thejpackage
task. defaultValue:buildDir/outputDir
usage example:installerOutputDir = file("$buildDir/my-packaging-installer")
- installerName
-
the argument passed to the
--name
option when runningjpackage
when executing thejpackage
task.
defaultValue: thename
value configured in thelauncher
block orproject.name
usage example:installerName = "MyApp"
It’s recommended to use the same value as for the imageName property. - appVersion
-
the argument passed to the
--app-version
option when runningjpackage
when executing thejpackage
andjpackageImage
tasks.
defaultValue: the project version
usage example:appVersion = "1.0.0"
- icon
-
the path to the custom application icon.
This is a convenience property equivalent to configuring--icon
in theimageOptions
list.
defaultValue: null (the default icon is used) - vendor
-
the vendor name.
This is a convenience property equivalent to configuring--vendor
in theimageOptions
list.
defaultValue:Unknown
- jvmArgs
-
list of JVM arguments to be passed to the virtual machine.
defaultValue: thejvmArgs
value configured in thelauncher
block, or the arguments configured in theapplicationDefaultJvmArgs
property of theapplication
extension - args
-
list of arguments to be passed to the application.
defaultValue: theargs
value configured in thelauncher
block, or the arguments configured in theargs
property of therun
task
NOTE: If args or jvmArgs is not set, and the default value is taken from the launcher
block, it may contain the placeholder {{BIN_DIR}}
.
The plugin replaces this placeholder with $APPDIR/..
when passing the arguments to jpackage
.
This is the correct approach in most cases. If not, you need to explicitly configure args or jvmArgs in the jpackage
block.
Currently, jpackage doesn’t support environment variables in --java-options
.
Therefore, you cannot use environment variable names enclosed between {{
and }}
in jvmArgs
.
- installerOptions
-
list of additional options to be passed to the
jpackage
executable when executing thejpackage
task.
defaultValue: empty list
usage example:installerOptions = ["--win-console"]
- targetPlatformName
-
This property is required only when using the
targetPlatform
method. It specifies which of the images produced by jlink should be used as runtime image by jpackage. Its value must match the name provided in one of the calls to thetargetPlatform
method.
defaultValue: null
usage example:targetPlatformName = "linux"
In contrast to jlink, jpackage is not able to produce installers for other platforms. For example, to create an installer for Linux, you must run jpackage on a Linux machine. You cannot do it on a Windows or Mac platform. |
If you need to create installers for more than one platform, it’s probably better not to use targetPlatform. Instead, you run the same build on different machines. If your project is on GitHub, you can automate this by using GitHub Actions, as seen in this example. |
Usage example
jlink {
...
jpackage {
jpackageHome = '/usr/lib/jvm/jdk16'
outputDir = 'my-packaging'
// imageOutputDir = file("$buildDir/my-packaging-image")
// installerOutputDir = file("$buildDir/my-packaging-installer")
imageName = 'MyApp'
imageOptions = ['--win-console']
skipInstaller = false
installerName = 'MyApp'
installerType = 'msi'
installerOptions = ['--win-console', '--win-menu', '--win-shortcut']
}
...
}
jlink {
...
jpackage {
jpackageHome = "/usr/lib/jvm/jdk16"
outputDir = "my-packaging"
// imageOutputDir = file("$buildDir/my-packaging-image")
// installerOutputDir = file("$buildDir/my-packaging-installer")
imageName = "MyApp"
imageOptions = listOf("--win-console")
skipInstaller = false
installerName = "MyApp"
installerType = "msi"
installerOptions = listOf("--win-console", "--win-menu", "--win-shortcut")
}
...
}
How it works
The plugin combines all non-modular dependencies into a single jar to which it adds a module descriptor.
If the jlink
extension contains a mergedModule
block, its directives will be used to generate the module descriptor.
Otherwise, a module descriptor is created using the algorithm implemented by the suggestMergedModuleInfo
task.
If the attribute additive
is set to true in the mergedModule
block, the generated module descriptor adds the clauses
specified in this block to the "suggested" descriptor.
The non-modular dependencies appear as automatic modules in the original module graph.
The plugin replaces them with delegating modules, which are dummy modules containing only a module descriptor that
requires transitive
the merged module.
The figure below illustrates this process.
In some situations, the above approach would lead to cyclic dependencies between modules. For example, in the module graph below the automatic module org.example.mod1 requires the proper module org.example.mod2. Because the content of org.example.mod1 gets merged into the merged module, the merged module must require org.example.mod2. This in turn requires the delegating module org.example.mod3 and hence the merged module.
To prevent such problems, the plugin automatically detects the modular jars that would be involved in a cycle and treats them as if they were non-modular. This means that it also merges these modular jars into the merged module and replaces them with delegating modules. The figure below shows the resulting module graph.
Sometimes, you may want to have a modular jar treated as non-modular, even if it is not affected by a cyclic dependency problem.
You can do this using the forceMerge
method.
Task details
The following properties denote files and directories used by the plugin tasks:
-
imageDir - the directory into which the custom runtime image should be generated.
-
imageZip - the file into which a zip archive of the custom runtime image should be created.
-
jlinkBasePath - the path to the base working directory of the plugin. The table below shows the variable names of the subdirectories created here and their relative path to the base working directory:
Variable name | Path relative to jlinkBasePath |
mergedJarsDir | mergedjars |
tmpMergedModuleDir | tmpmerged |
jlinkJarsDir | jlinkjars |
tmpJarsDir | tmpjars |
tmpModuleInfoDir | tmpmodinfo |
delegatingModulesDir | delegating |
prepareMergedJarsDir
- clean jlinkBasePath - copy modular jars required by non-modular jars to jlinkJarsDir - copy non-modular jars to nonModularJarsDir - unpack all jars from nonModularJarsDir into mergedJarsDir - create MANIFEST.MF in mergedJarsDir
createMergedModule
- archive mergedJarsDir into tmpMergedModuleDir/mergedModuleName.jar - generate module-info.java for the above merged jar into - clean tmpModuleInfoDir and unpack the merged jar in it - compile the generated module-info.java into tmpModuleInfoDir using jlinkJarsDir as module-path - copy mergedJarsDir into tmpModuleInfoDir - re-create tmpMergedModuleDir/mergedModuleName.jar by archiving tmpModuleInfoDir
createDelegatingModules
- delete nonModularJarsDir: - create delegating module-info.java into /<current-module-name> - clean tmpModuleInfoDir and create MANIFEST.MF in it - compile module-info.java into tmpModuleInfoDir with jlinkJarsDir as module-path - create a jar of tmpModuleInfoDir into delegatingModulesDir- for each file in
prepareModulesDir
- copy delegating modules from delegatingModulesDir to jlinkJarsDir - copy modular jars not required by non-modular jars to jlinkJarsDir - copy the main module jar from project.jar.archivePath to jlinkJarsDir - adjust all module descriptors containing qualified exports or opens clauses referring to modules integrated in the merged module. These clauses will be changed to also refer to the merged module.
jlink
- delete imageDir - create custom runtime image in imageDir by executing jlink with modules from jlinkJarsDir
jlinkZip
- zip imageDir to imageZip
suggestMergedModuleInfo
- determine the modules required by the merged module - determine the services used by the merged module - determine the services provided by the merged module - print the suggested `mergedModule` block
- Options
language
-
the DSL for which the mergedModule block should be displayed.
default value:groovy
accepted values:groovy
,kotlin
,java
usage example:./gradlew suggestMergedModuleInfo --language=kotlin
jpackageImage
- create a platform-specific application image in imageOutputDir by executing: jpackage --type app-image --runtime-image imageDir --module-path jlinkJarsDir ...
The properties imageOutputDir and imageDir
can be configured in the jpackage
script block.
jpackage
- if skipInstaller is false: create a platform-specific application installer in installerOutputDir by executing: jpackage --type installerType --app-image=imageOutputDir/imageName ...
The properties installerOutputDir, installerType, imageOutputDir, and imageName
can be configured in the jpackage
script block.
If no installerType has been configured, the plugin will run jpackage
several times, one for each type supported by the current platform.
Examples
The following projects illustrate how to use this plugin to create custom runtime images:
-
badass-jlink-example - a 'Hello world' application using slf4j and logback.
-
badass-jlink-example-log4j2-javafx - a 'Hello world' JavaFX application using log4j2.
-
badass-jlink-example-javafx-multiproject - A 'Hello world' JavaFX application with a Gradle multi-project build.
-
badass-jlink-example-kotlin-javafx - a 'Hello world' JavaFX application written in Kotlin.
-
badass-jlink-example-richtextfx - A RichTextFX project that shows how to configure splash screens and file associations when using jpackage.
-
badass-jlink-example-kotlin-tornadofx - a 'Hello world' application written in Kotlin using tornadofx.
-
badass-jlink-spring-petclinic - creates a custom runtime image of the Spring PetClinic application.
-
fxgl-sliding-puzzle - a sliding puzzle game using the FXGL library.
-
copper-modular-demo - creates a custom runtime image of a COPPER 5 modular application.
-
javafx-jlink-starter-gradle - A JavaFX starter project with an Azure Pipelines setup that produces binaries for Windows, Mac, and Linux.
-
javafx-springboot-badass-jlink - A modular JavaFX application with Spring Boot.
-
pdf-decorator - A JavaFX tool to add stamps and backgrounds to PDF documents. There’s also a related article explaining how to migrate to this plugin.