jar2app is a Python 2/3 script that can easily convert any jar file into a Mac OS X app file. It seeks simplicity, and in fact can be run just like
jar2app input.jar
creating input.App
in the process. No third-party libraries. No cruft.
Though simple and easy to use, there are loads of configurable options, such as setting icons, bundle names or bundling your own JRE/JDK.
Install instructions can be found here. Example usage can be found here.
It should run in any operating system (Windows, Mac OS X, Linux), but of course you'll only test the results in a Mac OS X system.
- Aren't there other tools that do this? Why another one?
- Can I submit bundles created with jar2app to the Appstore?
- How do I install/uninstall it?
- How does it work?
- What exactly can I change?
- Does jar2app bundle its own JRE/JDK? Can I bundle my own?
- Does jar2app figure the main class of my jar automatically? Can I change it?
- Apple defines several keys for its App format. How does jar2app figure them out?
- If I only pass the jar and no other options, what are the defaults used by jar2app?
- How is the App name determined?
- Where did this idea come from?
- Is there a GUI?
- Does it work on retina screens?
- Should I use jar2app for my commercial application?
- jar2app doesn't do what I want. Are there other alternatives?
- Example Usage
- What are all the options?
(TOC created with the help of gh-md-toc)
There are other tools that do this. I acknowledge them and even have several links to them.
However, this project was born out of the need to do something easily and without much cruft. Most solutions out there require a gazillion arguments, or installing ant and memorizing lots of conventions. jar2app, however, tries to keep the power of those utilities while providing high simplicity in the process. Really, isn't it wonderful to have such an easy-to-use interface?
If you're also considering why these contributions weren't just sent to one of the other projects, it is because this could not be done easily. Packr uses a custom launcher and is meant to pack things for Mac OS X, Windows and Linux. Most of the other alternatives require third-party tools that embed other functionality and which simply cannot be stripped. The solution I was left with was just rolling out my own. If you think that's just a strong case of NIH, feel free to grab what you want from me and send a patch to the other projects :) Just follow the GPL!
jar2app may bundle your jar, but there are several steps you further need to take to submit your application to the Appstore. This is not a limitation of jar2app, it's just how the Appstore requires you to do things. For more information on how to submit bundles to the appstore, see here and here.
Just clone the repository and run install.sh
, or uninstall.sh
to remove it. It will install to /usr/bin, but you can change this by passing your desired prefix to install.sh, as an argument. This will install the jar2app application/script and make it available for you to run.
git clone https://github.com/Jorl17/jar2app
cd jar2app
chmod +x install.sh uninstall.sh
sudo ./install.sh
git clone https://github.com/Jorl17/jar2app
cd jar2app
chmod +x install.sh uninstall.sh
sudo ./install.sh /usr/local/bin
./uninstall.sh
./uninstall.sh /usr/local/bin
jar2app relies on JavaAppLauncher (although you don't need to install anything). This application, officially provided by Oracle (previously Apple), acts as wrapper that starts a JVM with a set of options. The JVM can be bundled with the App file, or the system-wide-one can be used. Essentially, all that jar2app has to do is create a directory structure (app files are just directories), pack JavaAppLauncher and your application in it and set appropriate values in an Info.plist file. Additionally, if you so wish, your own JDK or JRE can be bundled and the Info.plist file will be updated to reflect this.
I know that there are other solutions that write their own wrapper, but the provided wrapper seems to work great (it's also bundled by Weka). The other wrapper I saw out there was from the Packr project and it really depended on their way of doing this.
You can change many things, but more specifically, you can change the icon, the display name (the one that appears on the menu bar), the version and copyright information, the bundled JDK/JRE and the JVM options. For a full list of options, see here
By default, jar2app doesn't bundle any JRE or JDK, and the default will be used on each system. You can, however, pass it a JRE/JDK with the -r
,--runtime
option. It can be supplied as a folder or as a zipfile. This JRE/JDK should match the directory structure found in Oracle's JDK (i.e. the first folder should be named Contents, etc).
Yes it does. It looks inside your jar file for the MANIFEST.MF file and extracts the name of the main class. You can change this behavior, and pass in another main class with the -m
, --main-class
option.
There are several keys that Apple defines, and you might want to check them out. jar2app assigns values to the following keys:
- CFBundleDevelopmentRegion: This is fixed at English
- CFBundleExecutable: This is internally defined to JavaAppLauncher (from oracle)
- CFBundleIconFile: This is set to whichever icon you passed in, and ignored if no icon is used
- CFBundleIdentifier: This is chosen from the following, in order:
- What you supplied (
-b
,--bundle-identifier
) - The default: com.jar2app.example.
application name
- What you supplied (
- CFBundleDisplayName: This is chosen from the following, in order:
- What you supplied as display name (
-d
,--display-name
) - What you supplied as bundle name (
-n
,--name
) - The name of the app (passed as outputfile argument)
- The name of the jar (excluding extension)
- What you supplied as display name (
- CFBundleName: This is chosen from the following, in order:
- What you supplied as bundle name (
-n
,--name
) - What you supplied as display name (
-d
,--display-name
) - The name of the app (passed as outputfile argument)
- The name of the jar (excluding extension)
- What you supplied as bundle name (
- CFBundleVersion: This is chosen from the following, in order:
- What you supplied as version (
-v
,--version
) - What you supplied as short version (
-s
,--short-version
) - The default: 1.0.0
- What you supplied as version (
- CFBundleShortVersionString: This is chosen from the following, in order:
- What you supplied as short version (
-s
,--short-version
) - What you supplied as version (
-v
,--version
) - The default: 1.0.0
- What you supplied as short version (
- CFBundleSignature: This is chosen from what you supply or the string "????".
- NSHumanReadableCopyright: This is set to what you supply or the empty string
The info.plist
file will contain additional keys, but there are used to pass information to JavaAppLauncher (JVM arguments, JDK/JRE, etc)
jar2app assumes that you want to create an app file with the same basename as your jar file and in your current working directory. It assumes no JRE/JDK is to be bundled, and that no special arguments have to be passed to the JVM. The remaining options, such as the Icon, display name and others, are figured out as described in here. The short version is that all names get set to the basename of your jar, and that versions are set to 1.0.0.
You are probably also interested in this question and this question. The app name is determined as so:
- What you supplied as app name (it is the last unnamed argument, e.g.
jar2app in.jar outname
). You don't need to append.App
, as jar2app does it for you. - What you supplied as bundle name (
-n
,--name
) - What you supplied as display name (
-d
,--display-name
) - The name of the jar (excluding extension)
Well, you should probably check this FAQ entry first. I originally went looking for an application like jar2app because I noticed that spotlight didn't like showing me .jar files. This meant that whenever I wanted to launch applications bundled as jars (and that happens very often), I'd have to break my workflow and wait while spotlight figured itself out. To fix this, I decided to just package the jar in an app. "It must be easy, right"? Turns out it wasn't so easy and most tools weren't straightforward, so, here's jar2app. Have fun, report bugs and add features as you wish!
This tool is so simple to use that it seems pointless to add a GUI. Nevertheless, for all your command line aversion needs, I might implement a really simple optional GUI in the future (probably using PyQt).
Yes it does. It adds specific entries in the Info.plist file to ensure that retina screen is enabled by default. You can change that by passing -l
,--low-res-mode
.
You can, but don't expect a one-liner to do the trick. There are several parameters that you have to configure, including special unique keys and signatures. jar2app has many defaults that should not be used if you intend to distribute your application in very serious fashion. Use it with the default values for simple, easy and straightforward redistribution.
jar2app tries to do most of what the other tools do. It's lacking mostly in JRE/JDK minimizing support, and it hasn't really been thoroughly tested when bundling things for the app store.
If it's not your cup of tea, don't worry! There are other alternatives, such as the wonderful Packr, the official Oracle documentation, the official Apple documentation and the AppBundler project, part of which is used in jar2app. You can also read more about the cumbersome nature of packaging jars in app files here.
Even if jar2app didn't help, come back and open an issue, or send your own patches!
Here are a couple of examples on how to change the settings of jar2app. For a full list of options, see here.
jar2app test.jar
You should now have a test.App
in your directory.
This can be done in several ways. The most straightforward one is just:
jar2app test.jar out
You should now have a out.App
in your directory. Note how jar2app automatically appends the .App
extension (this can be disabled with -a
,--no-append-app-to-name
). You can also do
jar2app test.jar out.App
Lastly, You can also do
jar2app test.jar test/out.App
And jar2app will create the test subdirectory for you. It only creates the parent directory of the target .app file, though!
Also note that the app output name is pre-determined based on other options. For instance, if you pass in a bundle name, that will be used. See this question for more details.
jar2app test.jar -i icon.icns
You should now have a test.App
in your directory with the provided icon. -i
can be a full path, e.g.
jar2app test.jar -i /awesomeicons/icon.icns
The name that appears in menu bars will be given by the Bundle Display Name. You can se this with -d
,--display-name
, but I'd really recommend that you change the bundle name itself with -n
,--name
(the Bundle Display Name will assume this value). This can be done with
jar2app test.jar -n "Amazing Application"
Note that since in the above example, no output .App name is given, the .App file will also be named "Amazing Application" (see here). You can change this by doing any of:
jar2app test.jar out -n "Amazing Application"
jar2app test.jar out.app -n "Amazing Application"
jar2app test.jar -n "Amazing Application" out
jar2app test.jar -n "Amazing Application" out.app
Any of those commands will have the same effect: the app file will be out.app
, but the display name (shown in menus) will be "Amazing Application".
Say you want to bundle your own JDK/JRE. For instance, assume you want to bundle the one located at /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk
. This is trivial to do (-r
, --runtime
), just run:
jar2app test.jar -r /Library/Java/JavaVirtualMachines/jdk1.8.0_40.jdk
You can also pass the JDK/JRE as a zip file. Assume you have it in compressed form in /compressedJDKs/jdk1.8.0_40.jdk.zip
, just do:
jar2app test.jar -r /compressedJDKs/jdk1.8.0_40.jdk.zip
-h, --help show this help message and exit
-n BUNDLE_NAME, --name=BUNDLE_NAME
Package/Bundle name.
-d BUNDLE_DISPLAYNAME, --display-name=BUNDLE_DISPLAYNAME
Package/Bundle display name.
-i ICON, --icon=ICON Icon (in .icns format). (Default: None)
-b BUNDLE_IDENTIFIER, --bundle-identifier=BUNDLE_IDENTIFIER
Package/Bundle identifier (e.g. com.example.test)
(Default is application name prefix by
com.jar2app.example..
-v BUNDLE_VERSION, --version=BUNDLE_VERSION
Package/Bundle version (e.g. 1.0.0) (Default: 1.0.0).
-s SHORT_VERSION_STRING, --short-version=SHORT_VERSION_STRING
Package/Bundle short version (see Apple's
documentation on CFBundleShortVersionString) (Default:
1.0.0).
-c COPYRIGHT_STR, --copyright=COPYRIGHT_STR
Package/Bundle copyright string (e.g. (c) 2015 Awesome
Person) (Default: empty)
-u SIGNATURE, --unique-signature=SIGNATURE
4 Byte unique signature of your application (Default:
????)
-m MAIN_CLASS_NAME, --main-class=MAIN_CLASS_NAME
Jar main class. Blank for auto-detection (usually
right).
-r JDK, --runtime=JDK
JRE/JDK runtime to bundle. Can be a folder or a zip
file. If none is given, the default on the system is
used (default: None)
-j JVM_OPTIONS, --jvm-options=JVM_OPTIONS
JVM options. Place one by one, separated by spaces,
inside inverted commas (e.g. -o "-Xmx1024M -Xms256M)
(Default: None)
-a, --no-append-app-to-name
Do not try to append .app to the output file by
default.
-l, --low-res-mode Do not try to report retina-screen capabilities (use
low resolution mode; by default high resolution mode
is used).
-o, --use-osx-menubar
Use OSX menu bar instead of Java menu bar (Default:
False).
-e EXECUTABLE, --executable-name=EXECUTABLE
Name of the internal executable to launch (Default:
JavaAppLauncher).
-x EXECUTABLE_FILE, --executable-file=EXECUTABLE_FILE
Internal executable to launch. By default,
JavaAppLauncher provided by jar2app is used.
-w WORKING_DIRECTORY, --working-directory=WORKING_DIRECTORY
Set current working directory (user.dir) on launch
(Default: $APP_ROOT/Contents).