Back to the code page

Using Ant to automatically create MacOSX DMG disk images


In order to automatically build DMG packages for SIP Communicator, I've written a target for Ant. The resulting DMG has a custom volume icon, and the mounted image has a background and a symbolic link to the Applications folder: it makes your package really looking great! For example, here is what you'll see if you mount a SIP Communicator DMG:

Prior to using this target, you need to prepare a background image, a volume icon and a .DS_Store file:

  • The backgroung image can be a png image. For SIP Communicator I've created this one. A generic one is also available here (contributed by Patrick Crutchley),
  • The volume icon must be an icns file. You can create such file from the Icon Composer application available in /Developer/Applications/Utilities/. For SIP Communicator I've created this one,
  • The .DS_Store file indicates (among other things) how the icons are placed inside a folder. It is automatically created while you modify the view options of a directory. It's thus a bit more tedious work to create this file, here is the procedure:
    • Use the below Ant target to create a temporary DMG of your application: remove the copy directive for the DS_Store file (as this file does not exist yet), and remove also the last delete directive, as we will work on the temporary image,
    • Mount the resulting ${app.name}-tmp.dmg DMG. If the window of the mounted volume appears in column view, ctrl-click on the window and select View > as Icons,
    • ctrl-click on the window and select Show View Options,
    • In the Background section, check the Picture box and click on select. Your background picture is located in the ${mountdir}/${app.name}/.background directory that you specified in the Ant target. As the directory is hidden, in order to go there you can use the Shift+Command+G combination to open the Go to... panel. Enter here your path to the .background directory of your mounted image. Select the background.png file that should be located there,
    • Back to the View Options panel, select Arrange by: None. Now you can arrange the position of each icon in the volume window by moving each icon to the place where you would like them to be. You can also modify each icon size and the position of the icon's label from the View Options panel.
    • Finally, get the .DS_Store file that was created in the mounted volume (it should be ${mountdir}/${app.name}/.DS_Store). Note that .DS_Store files are hidden files, so you'll need to copy it from a terminal, and I'd advice you to rename it to DS_Store (removing the initial dot). Keep this file preciously and include it to your application repository. The complete Ant target written below will then take care of copying your DS_Store file to a .DS_Store file.

Note 1: the .DS_Store files are not forward-compatible between OS versions. A file created on Snow Leopard will not work properly on Leopard machines. If possible, you may consider creating it on a Leopard computer instead.

Note 2: Several absolute paths of the build system and the username end up in the .DS_Store file. You can edit the file and replace them with X's if you do not want to leave them there.

The following target (invoked with ant dmg) basically creates a temporary image with hdiutil, mounts it, copies inside it the background image, the volume icon and the .DS_Store files. The temporary image is then unmounted and compressed to a ready-to-be-distributed DMG. Copy it in your build.xml file and read the comments for more information on how to adapt it for your application.

Note: the hdiutil of Leopard behaves differently than the one of Snow Leopard. With Leopard, you may get an error if it attempts to create an image too big. It does not appear with Snow Leopard though.


<!-- Create a DMG - This only works on MacOSX (requires hdiutil) -->
<target name="dmg"
        description="Create a DMG package for MacOSX (only works on MacOSX)">

    <!-- Set this property value to your application name -->
    <property name="app.name"
              value="MY_APPLICATION_NAME"/>

    <!-- Set this property value to a directory where you can 
         mount temporarily your images, for example /tmp -->
    <property name="mountdir"
              value="/tmp"/>

    <!-- Delete previously created DMG -->
    <delete file="${app.name}.dmg}"
            quiet="yes" failonerror="false"/>

    <!-- Create a temporary Disk Image -->
    <exec executable="/usr/bin/hdiutil" os="Mac OS X" failonerror="true">
      <arg value="create"/>
      <arg value="-srcfolder"/>
      <arg value="${app.name}.app"/>
      <arg value="-volname"/>
      <arg value="${app.name}"/>
      <arg value="-ov"/>
      <arg value="${app.name}-tmp.dmg"/>
      <arg value="-format"/>
      <arg value="UDRW"/>
    </exec>

    <!-- Attach the temporary image -->
    <exec executable="/usr/bin/hdiutil" os="Mac OS X" failonerror="true">
      <arg value="attach"/>
      <arg value="${app.name}-tmp.dmg"/>
      <arg value="-mountroot"/>
      <arg value="${mountdir}/"/>
    </exec>

    <!-- Copy the background, the volume icon and DS_Store files -->
    <mkdir dir="${mountdir}/${app.name}/.background"/>
    <copy file="background.png"
          tofile="${mountdir}/${app.name}/.background/background.png"
          overwrite="true"/>
    <copy file="VolumeIcon.icns"
          tofile="${mountdir}/${app.name}/.VolumeIcon.icns"
          overwrite="true"/>
    <copy file="DS_Store"
          tofile="${mountdir}/${app.name}/.DS_Store"
          overwrite="true"/>

    <!-- Indicate that we want a custom icon -->
    <exec executable="/Developer/Tools/SetFile" os="Mac OS X">
      <arg value="-a"/>
      <arg value="C"/>
      <arg value="${mountdir}/${app.name}"/>
    </exec>

    <!-- Add a symbolic link to the Applications directory -->
    <symlink link="${mountdir}/${app.name}" resource="/Applications"/>

    <!-- Detach the temporary image -->
    <exec executable="/usr/bin/hdiutil" os="Mac OS X" failonerror="true">
      <arg value="detach"/>
      <arg value="${mountdir}/${app.name}"/>
    </exec>

    <!-- Compress it to a new image -->
    <exec executable="/usr/bin/hdiutil" os="Mac OS X" failonerror="true">
      <arg value="convert"/>
      <arg value="${app.name}-tmp.dmg"/>
      <arg value="-format"/>
      <arg value="UDZO"/>
      <arg value="-o"/>
      <arg value="${app.name}.dmg"/>
    </exec>

    <!-- Delete the temporary image -->
    <delete file="${app.name}-tmp.dmg"
            quiet="yes" failonerror="false"/>
</target>

If you put your DMG online and people download it with Safari, it will automatically mount the DMG on your Desktop. You can choose to have an alternate behaviour, where the content of the DMG will be copied in a directory on the desktop, and the DMG be automatically trashed. This behaviour can be configured with an option for hdiutil. Simply add the following piece of code to the above script, just before the <!-- Delete the temporary image --> section:


    <exec executable="/usr/bin/hdiutil" os="Mac OS X" failonerror="true">
      <arg value="internet-enable"/>
      <arg value="-yes"/>
      <arg value="${app.name}.dmg"/>
    </exec>

Here is the alternate result you'll get once the DMG has been downloaded:


The following people have contributed to this Howto:

  • Yuvi Masory pointed the internet-enabled option for hdiutil, as well as several hints about the .DS_Store file and hdiutil,
  • Patrick Crutchley contributed a generic DMG background image.