How to use JPackage Tool CLI for MacOS apps
As part of Java 14 and 15, a new utility was added to replace the legacy JavaFX app called javapackager. While it is currently part of the incubator, it will be part of the general release of JDK 16 and greater. It allows you to create standalone applications that are OS specific and do not require the Java Runtime Environment to be installed. Additionally, the applications can be cryptographically signed so that they can execute without any security prompts on MacOS.
- Full install of Xcode or the Xcode command line tools
- Open JDK 16
You can install Xcode Command Line Tools via the terminal using the following command:
sudo xcode-select --install
JPackage MacOS Example
The following will allow you to create a standalone Java application which can run on MacOS without needing any Java installs or other related prerequisites.
jpackage --input target/ \ --name MyAppName \ --main-jar MyAppName.jar \ --main-class com.codetinkering.app.MyMain \ --type dmg \ --icon "/user/home/myiconfile.icns" \ --app-version "1.2.3" \ --vendor "code tinkering" \ --copyright "Copyright 2020 whoever" \ --mac-package-name "App Name in Menu" \ --module-path "/opt/javafx/javafx-sdk-14.0.1/lib" \ --add-modules javafx.controls \ #--mac-sign \ #--mac-bundle-identifier "MyAppName-1.2.3" \ #--mac-bundle-name "My App Name" \ #--mac-bundle-signing-prefix "" \ #--mac-signing-keychain "" \ #--mac-signing-key-user-name "" \ --verbose \ --java-options '--enable-preview'
There is a lot to unpack here, lets visit each flag one-by-one.
- name - The name of your application or package you are trying to assemble. This is not the name that will appear in the tray or dock for your application.
- main-jar - References a compiled jar file containing your application. Should your application not be in a jar format, use the -module and -module-path flags instead.
- main-class - If your jar file doesn’t declare a main class via the manifest, or contains multiple classes with main methods, you can provide a fully qualified class name. (Optional)
- type - The type of package you are trying to create. Valid options are msi, exe on Windows, pkg, dmg on MacOS, deb, rpm on Linux.
- icon - This is the icon file you are providing for your application. For MacOS, this is an ICNS file. See below on how to create one. (Optional)
- app-version - Indicates your application’s version number. (Optional)
- vendor - Name of the vendor for your application. (Optional)
- copyright - Copyright information. (Optional)
- mac-package-name - This is a short name for your application which will show in the menu bar while it is running. It is limited to 16 characters. (Optional)
- module-path - Contains a list of modules to include. For example, I am including JavaFX modules and provide a path to the library folder where these JAR files are located. (Optional)
- add-modules - Used in conjunction with module-path. Specifies which modules in particular your application should include. Values are provided in a comma separated like: abc.example,def.example,xyz.example
- mac-sign - This flag indicates your application will be cryptographically signed. It is used in combination with the following Mac signing commands. (See section below on MacOS signing)
- mac-bundle-identifier - This is the unique app identifier which Apple uses for distinguishing applications. This is sometimes referred to as the “Bundle Identifier” within Xcode. Example: com.microsoft.Excel (Optional)
- mac-bundle-name - Specifies your application’s name within the MacOS ecosystem. Example: “My App Name” (Optional)
- mac-bundle-signing-prefix - This is the prefix of files which are to be signed. (Optional)
- mac-signing-keychain - This is a file path to your code signing identity within your Mac system. You may need to run this command as sudo for this to work. Example: /users/username/Library/Keychains/login.keychain-db (Optional)
- mac-signing-key-user-name - This is commonly known as your team name within the Xcode ecosystem. Example: DevID AppName: <team name> (Optional)
- verbose - Prints extra information to the console. (Optional)
- java-options - Since the feature we are attempting to use is currently in the incubator phase, we will need to force Java to enable it. Do not use this with Java 16 or greater as it will already be available.
Notes about MacOS Application Icons
You need to provide an ICNS file, which is a MacOS specific resource file. In short, it’s a bundle of differently sized PNG files. Per Apple’s specs, application icons should be provided in PNG format with a Display P3 (wide-gamut color), sRGB (color), or Gray Gamma 2.2 (grayscale) format. They should be flattened and be square without rounded corners. For maximum quality, provide a 1024×1024 px image. See this article by Apple for more details.
In order to make the icons, create a 1024×1024 pixel PNG file (make sure it has an Alpha Channel) and run the following commands, assuming the icon is named icon1024x1024.png. sips and iconutil are available via the Xcode command line tools.
mkdir icons.iconset sips -z 512 512 icon1024x1024.png --out icons.iconset/icon_512x512.png cp icon1024x1024.png email@example.com sips -z 512 512 icon1024x1024.png --out firstname.lastname@example.org sips -z 256 256 icon1024x1024.png --out icons.iconset/icon_256x256.png sips -z 256 256 icon1024x1024.png --out email@example.com sips -z 128 128 icon1024x1024.png --out icons.iconset/icon_128x128.png sips -z 64 64 icon1024x1024.png --out firstname.lastname@example.org sips -z 32 32 icon1024x1024.png --out icons.iconset/icon_32x32.png sips -z 32 32 icon1024x1024.png --out email@example.com sips -z 16 16 icon1024x1024.png --out icons.iconset/icon_16x16.png iconutil -c icns icons.iconset rm -R icons.iconset
MacOS Signing Parameters
If you are familiar with Xcode, see the below diagram with how Java’s aforementioned signing parameter names correspond with Apple’s terminology.