I’ve been tinkering with Kotlin and JavaFX and the result was a Java jar file that spins up a user interface. OS X will double click open a jar, but I wanted a normal app. I looked around and found App Maker, which did a decent job, but processing the jar manually each build got annoying fast. Looking at the info out there, and what App Maker did, it seemed like I ought to be able to get gradle to do the same without too much pain. I did.
The Simplest App Possible
So, from documentation, and investigating App Maker’s output, the simplest app is:
AppName.app/ Contents/ Info.plist MacOs/ AppName-x.y.z.jar launcher Resources/ application.icns
That’s the basics. So if you’ve a working jar, all you’re lacking it the directory structure, and:
- Info.plist: An Apple plist file, you can use a simple one unaltered.
- launcher: A shell script that launches the jar. This can be 98% templated, with only things like the app name, jar name, and java version needing to be set.
- application.icns: An icon formatted to Apple’s approval.
The Gradle Solution
To generate the app bundle from gradle, I did two things:
- Put the three needed files into src/main/app. The Info.plist and the application.icns are the actual final files. The launcher I modified into a template, using Ant’s templating notation “@VARIABLE_NAME@”.
- Then I added one gradle task to build out the directory structure, and copy the files into place, applying the templating.
Here is the gradle task. I employed some of gradle’s ant support to perform copies and templating.
With the files and task in place all you need to do is run gradle osxApp and you’ll hopefully find build/app/ProjectName.app – a working OS X app.
I could roll this into a Gradle PlugIn but that’s more work then I want to do for this. As it stands, if you want to use this approach, just grab my project that uses it, copy the files in src/main/app and add the task to your build.gradle.