Back to the code page

Using Ant and JarBundler to create a MacOSX application


In order to automatically create a MacOSX application for SIP Communicator, I've written a target for Ant. The result is a .app package which can be executed like any other MacOSX application, by double-clicking on it. For example, here is what the SIP Communicator application looks like in the Finder preview:

First, you need to install JarBundler. It is an Ant task which can be used to easily create MacOSX .app packages.

Then, create a specific MacOSX resource directory in your application source tree. We will use it to store the MacOSX-specific files:

  • You need to get the JavaApplicationStub file from a MacOSX computer. It is located in the /System/Library/Frameworks/JavaVM.framework/Resources/MacOS/ directory. Copy it in your newly created MacOSX resource directory. It will allow you to build the MacOSX package from any operating systems (i.e. not only from a MacOSX computer).
  • Create a logo for your application. It must be an icns file. You can create such file from the Icon Composer application available on MacOSX in /Developer/Applications/Utilities/. Name it e.g. logo.icns and store it in your MacOSX resource directory.

The following target for Ant (invoked with ant macosx) automatically creates the directory structure for your application package and copy inside it the necessary libraries. Copy it in your build.xml file. The nice thing is that it can be invoked from any operating systems. Read the comments for more information on how to adapt it to your application.


<target name="macosx"
        description="Create an .app package for MacOSX">

    <!-- Set this property value to the directory where you 
         would like to create the application package -->
    <property name="macosx.app"
              value="PATH_TO_RELEASE_DIRECTORY"/>

    <!-- Create the release directory -->
    <mkdir dir="${macosx.app}"/>

    <!-- Set this property value to your application name.
         Do not include the .app extension -->
    <property name="app.name"
              value="MY_APPLICATION_NAME"/>

    <!-- Set this property value to your MacOSX resource 
         directory (where are stored your JavaApplicationStub 
         and icon files) -->
    <property name="macosx.resrc"
              value="PATH_TO_MACOSX_RESOURCE_DIRECTORY"/>

    <!-- Set this property value to your application 
         resource directory (where are stored your 
         libraries, jar, etc.) -->
    <property name="app.resrc"
              value="PATH_TO_APPLICATION_RESOURCE_DIRECTORY"/>

    <property name="macosx.stubfile"
              value="${macosx.resrc}/JavaApplicationStub"/>

    <taskdef name="jarbundler"
             classname="net.sourceforge.jarbundler.JarBundler"/>

    <!-- Delete the old .app if it exists -->
    <delete dir="${macosx.app}/${app.name}.app"
            quiet="yes" failonerror="false"/>

    <!-- This creates the .app for MacOSX.
         The mainclass property must be set to the name of 
         the main class to run. Consult the JarBundler 
         documentation for more options and information -->
    <jarbundler dir="${macosx.app}"
                name="${app.name}"
                shortname="${app.name}"
                mainclass="APPLICATION_MAIN_CLASS"
                icon="${macosx.resrc}/logo.icns"
                infostring="${app.name}"
                stubfile="${macosx.stubfile}"
                workingdirectory="$APP_PACKAGE/Contents/Resources/Java">

        <!-- The below Java properties can be set to get 
             a better MacOSX look-and-feel -->
        <javaproperty name="apple.laf.useScreenMenuBar" value="true"/>
        <javaproperty name="apple.awt.brushMetalRounded" value="true"/>
        <javaproperty name="apple.awt.showGrowBox" value="true"/>

        <!-- You may need to set here other java properties 
             according to your application needs -->

        <!-- Include all the needed jar, libraries and 
             resources file to your application package. You
             can add as much 'include' directive as you need. 
             You can also use the 'exclude' directive. Consult 
             the JarBundler documentation -->
        <jarfileset dir=".">
            <include name="${macosx.resrc}/logo.icns" />
            <include name="${app.resrc}/*.jar" />
        </jarfileset>
    </jarbundler>
</target>

For debug purposes, note that you can inspect the content of the package once it has been built by right-clicking on the resulting .app file and select Show Package Contents:

Next, if you want to automatically create a DMG disk image for your application, you may also have a look at this tutorial: Using ANT to automatically create MacOSX DMG disk images.