Skip to main content

macOS

macOS-specific properties go in macConfig. Code signing and notarization are explained in the code signing guide.

Maven
<macConfig>
<appId>com.example.myapp</appId>
<icnsFile>assets/mac/MyApp.icns</icnsFile>
<macStartup>UNIVERSAL</macStartup>
<generateDmg>true</generateDmg>
<generatePkg>true</generatePkg>
<infoPlist>
<additionalEntries><![CDATA[
<key>LSUIElement</key>
<true/>
]]></additionalEntries>
</infoPlist>
<developerId>Developer ID Application: Jane Doe (TEAMID1234)</developerId>
<volumeName>MyApp</volumeName>
</macConfig>
Gradle
import io.github.javapackager.model.MacStartup

javapackager {
macConfig {
appId = 'com.example.myapp'
icnsFile = file('assets/mac/MyApp.icns')
macStartup = MacStartup.UNIVERSAL
generateDmg = true
generatePkg = true
infoPlist.additionalEntries = '''
<key>LSUIElement</key>
<true/>
'''
developerId = 'Developer ID Application: Jane Doe (TEAMID1234)'
volumeName = 'MyApp'
}
}
Gradle

infoPlist has no closure: set its fields with infoPlist.additionalEntries = ... and infoPlist.bundlePackageType = .... A macConfig { } block in your own PackageTask replaces the extension's whole macConfig; it isn't merged property by property.

General properties​

PropertyDefaultDescription
appIdmainClassBundle identifier (CFBundleIdentifier). Also the prefix of file association UTIs (${appId}.${extension}) and of the bundled runtime id.
icnsFile${assetsDir}/mac/${name}.icns, or the default iconApp icon in ICNS format. Tools like MacIcns convert a PNG to ICNS.
macStartupUNIVERSALApp launcher: UNIVERSAL, X86_64, ARM64 or SCRIPT. See Launchers.
customLauncherYour own launcher (binary or script). It's copied to Contents/MacOS under its own name and replaces macStartup. Ignored if the file can't be read.
relocateJartruetrue: the JAR and libs/ go in Contents/Resources/Java; false: in Contents/Resources.
generateDmgtrueGenerates ${name}_${version}.dmg (with generateInstaller).
generatePkgtrueGenerates ${name}_${version}.pkg (with generateInstaller).

On macOS, useResourcesAsWorkingDir is always true: the app's working directory is Contents/Resources.

Info.plist properties​

PropertyDefaultDescription
infoPlist.bundlePackageTypeBNDLCFBundlePackageType: BNDL, APPL or FMWK.
infoPlist.additionalEntriesRaw plist XML (<key> and value pairs) appended to the generated Info.plist. It must be well-formed, and must not repeat keys JavaPackager already writes.
customInfoPlistYour own Info.plist, copied as is instead of generating it (infoPlist is then ignored). It must keep the CFBundleExecutable and the JavaX dictionary the launcher reads.
customRuntimeInfoPlistYour own Info.plist for the bundled JRE (Contents/PlugIns/jre.jre/Contents/Info.plist). Only with bundleJre.

Signing and notarization properties​

PropertyDefaultDescription
codesignApptrueSigns the .app with codesign. Only when building on macOS.
developerId-Signing identity. The default - means ad-hoc signing: no certificate needed, but the app can't be notarized.
entitlementsgeneratedEntitlements file. If not set, a default one suitable for a JVM is generated.
hardenedCodesigntrueEnables the hardened runtime (codesign -o runtime), if the build machine runs macOS 10.13.6 or newer.
provisionProfileProvisioning profile, copied to Contents/embedded.provisionprofile before signing.
notarizeAppfalseSubmits the signed app to Apple for notarization and staples the ticket. Needs codesignApp and a real developerId.
keyChainProfileKeychain profile created with xcrun notarytool store-credentials. Required with notarizeApp.

DMG properties​

PropertyDefaultDescription
backgroundImagebuilt-in imageDMG window background.
windowX10X coordinate of the DMG window on screen.
windowY60Y coordinate of the DMG window on screen.
windowWidth540Width of the DMG window.
windowHeight360Height of the DMG window.
iconSize128Icon size.
textSize16Label text size.
iconX52X coordinate of the app icon, relative to the window.
iconY116Y coordinate of the app icon, relative to the window.
appsLinkIconX360X coordinate of the Applications link, relative to the window.
appsLinkIconY116Y coordinate of the Applications link, relative to the window.
volumeIconthe app iconIcon of the mounted DMG volume (ICNS).
volumeNamenameName of the mounted volume. Whitespace is removed.

DMG properties explained

Launchers​

The launcher is the executable macOS runs when the app is opened. It reads the JavaX dictionary of Info.plist (main class, class path, VM options, arguments) and starts the JVM, the bundled one if there is any.

macStartupLauncher
UNIVERSALNative launcher, universal binary: runs natively on Apple Silicon and Intel. Default since 2.0.0.
X86_64Native launcher, Intel only.
ARM64Native launcher, Apple Silicon only.
SCRIPTBash script (universalJavaApplicationStub.sh). Default up to 1.7.6.

The native launcher is maintained in javapackager/nativeJavaApplicationStub. Whatever the type, it's written as Contents/MacOS/universalJavaApplicationStub.

To keep the launcher used up to 1.7.6, set <macStartup>SCRIPT</macStartup> (Gradle: macStartup = MacStartup.SCRIPT).

App bundle layout​

${name}.app/
└── Contents/
├── Info.plist
├── MacOS/
│ ├── universalJavaApplicationStub # launcher
│ └── startup # only with administratorRequired
├── Resources/
│ ├── ${name}.icns
│ ├── scripts/ # only with a bootstrap script
│ └── Java/ # with relocateJar (default)
│ ├── ${name}-${version}-runnable.jar
│ └── libs/
└── PlugIns/ # only with bundleJre
└── jre.jre/Contents/Home/ # the JRE

Info.plist holds the bundle keys (CFBundleIdentifier from appId, CFBundleName and CFBundleDisplayName from displayName, CFBundleShortVersionString and CFBundleVersion from version, NSHumanReadableCopyright from organizationName), the file associations, LSEnvironment (JAVA_HOME of the bundled JRE, PATH from envPath), and the JavaX dictionary:

JavaX keyValue
MainClassmainClass
ClassPathThe app JAR, followed by the classpath entries
VMOptionsvmArgs
ArgumentsappArgs
JVMVersion${jreMinVersion}+, when no JRE is bundled
WorkingDirectoryContents/Resources
JVMOptionsFileContents/Resources/${name}.l4j.ini (see runtime JVM options)
BootstrapScriptThe bootstrap script, if any

Running as administrator​

With administratorRequired, CFBundleExecutable is a startup script that runs the launcher through osascript ... with administrator privileges. macOS asks for an administrator's user name and password every time the app starts, and the app runs as root.

DMG​

The DMG is built with hdiutil and laid out in Finder with AppleScript: the app icon, a link to /Applications, the background image and the positions above. It needs the Xcode command line tools (SetFile) and permission for the build to control Finder.

The image uses APFS when the build runs on an Apple Silicon JVM, and HFS+ otherwise.

PKG​

The PKG is built with pkgbuild and installs the app in /Applications. Its install location, identifier and scripts can't be configured.

Building on other platforms​

With platform=mac you can build the .app, zipball and tarball on GNU/Linux or Windows; to bundle a JRE, set jdkPath to a macOS JDK (see bundling a JRE). Code signing, notarization, the DMG and the PKG need macOS and are skipped elsewhere.

caution

An app built off macOS isn't signed, and Apple Silicon Macs refuse to run unsigned apps. Sign it on a Mac before distributing it (at least ad-hoc: codesign --force --deep -s - MyApp.app).