Home » HowTo » Packaging a Mac OS X Application Using a DMG
      

Packaging a Mac OS X Application Using a DMG

posted by Andy Maloney

I learned early on in my software career that packaging up a release of an application can be a real pain. Not only is it time consuming, but it is quite easy to forget a file or miss something when there are so many steps involved and you have to do it frequently. The solution to this is to automate the process. Putting together scripts to package up a release helps avoid missing steps and speeds up development and deployment of releases and updates.

One of the challenges of automating this on Mac OS X is figuring out how to script the creation of Apple disk image (DMG) files. Getting the arguments to hdiutil correct can be quite a challenge! In this post, I’ll give an example of a script I use to do the following:

  • Copy all the necessary files to a staging area
  • Strip and compress the executable files and libraries
  • Create a DMG of the correct size for the release
  • Add a link to /Applications to the DMG
  • Add a background to the DMG so when it opens up your company logo or application graphic appears
  • Check the background image’s DPI to ensure it is 72. Fix it if it’s not.
  • Resize the window and icons, and position items in the DMG so when it opens everything is in the right place
  • Create a final, compressed DMG

Packaging An Application Using a DMG

Packaging An Application Using a DMG

Let’s take a look…

I like to create a double-clickable file to run the bash script so I can just run it from the Finder instead of using Terminal. To do that, simply name the file with the extension .command and make sure it is executable (run “chmod +x fileName.command” in the terminal).

(These are the files used in this example: Packaging_Example.zip. They are also available at the end of this post.)

This first part of the bash script sets up the names and locations of files we’ll be using throughout. If you are going to use this script for your own project, you’ll need to change several of the variables near the top.

This script assumes that the .command file, SuperCoolApp.app, and Background.png are all in the same folder. It also assumes that the actual executable in the application bundle (in Contents/MacOS ) is the same name as the .app.

After the setup, the first thing we need to do is check the background image’s dots-per-inch (DPI) settings. On the Mac, anything other than 72 DPI will result in a distorted background image when opening the DMG on Mac OS X 10.7+.

Background image with DPI of 90 on Mac OS X 10.8

Background image with DPI of 90 on Mac OS X 10.8

To fix this, we use the built-in scriptable image processing system command line tool (sips) to check the DPI and convert the image file if necessary.

Next we remove any old data, create the staging directory, and copy over all the stuff we want in the final DMG file.

Now we strip the symbols out of our executable and, if we have UPX in our path, we run it on the executable as well. (If you aren’t already using UPX, you should take a look. In most cases it will reduce the file size by quite a bit.)

Next, we figure out how big our temporary DMG needs to be by looking at the size of the staging directory, create the DMG, and mount it. The sleep command at the end simply waits for 2 seconds to make sure it’s mounted.

Now we set up the contents the way we want them to appear when the DMG is mounted by users. We add a link to /Applications so they can simply drag SuperCoolApp.app over to it, add a background image, and tell the Finder to set up the window size, icon sizes, and icon positions the way we want them.

In this final section, we unmount the temporary DMG, convert it to a compressed, final DMG, and clean up our temporary files.

Running this script by double-clicking the .command file opens Terminal and should give results something like this:

As with most developer projects, this could use some more error checking… If you release versions of your software frequently, you might want to read the version number from the .plist file instead of having to change it in this script. This is left as an exercise for the reader.

Please let me know in the comments if you find it useful or have any suggestions for improvements!

9 Nov 14: You may now find it as a gist on github as well.

7 Nov 13: Based on an issue Damien Cassou reported (see comments), added code to check the background image’s DPI and fix it if necessary.

Project Files: Packaging_Example.zip

10 Comments

  1. Comment by Damien Cassou:

    Thank you very much. This script helped me a lot. If you are still making changes to the script, you might want to share a gist (http://gist.github.com/) or something. I have one problem though: I can’t make a PNG that looks good as a background in the Finder: it looks like the finder tries to resize my picture, the finder adds a white margin on the right. I took the exact same resolution as your template, but yours always looks good whereas mine always looks bad.

    • Comment by Andy:

      Damien:

      You’re welcome! Glad you found it useful.

      I haven’t been making any changes, but thanks for the gist suggestion. I’ll take a look.

      I’m not quite sure about the problem you’re seeing. I’ve never had the Finder resize my backgrounds. Maybe you can send me the image you’re using and I can try it here? We can connect through my contact page.

    • Comment by Andy:

      Just a note to point out that the problem Damien was seeing had to do with the background image’s DPI.

      I added code to check the DPI and fix it if necessary and have updated the post and zip file download above.

  2. Comment by Tres Finocchiaro:

    Hi, Thanks for this fantastic script!
    It was working fantastically for me and then suddenly stopped yesterday. This is the cryptic message I get:

    could not access /Volumes/LMMS 1.0.0/LMMS.app/Contents/share/
    lmms/themes/default/stepper-right.png - Operation canceled
    hdiutil: create failed - Operation canceled
    Created DMG: LMMS 1.0.0-temp.dmg
    hdiutil: attach failed - No such file or directory
    Add link to /Applications
    -bash: pushd: /Volumes/LMMS 1.0.0: No such file or directory
    ln: ./Applications: File exists
    -bash: popd: directory stack empty
    mkdir: /Volumes/LMMS 1.0.0: No such file or directory
    cp: directory /Volumes/LMMS 1.0.0/.background does not exist
    69:73: execution error: Finder got an error: Can’t get disk "LMMS 1.0.0". (-1728)
    hdiutil: detach failed - No such file or directory
    Creating compressed image
    hdiutil: convert failed - No such file or directory
    Done.

    • Comment by Andy Maloney:

      Tres:

      It’s hard to tell from that where it’s failing. Obviously this is one of those cases I mention at the end of the article that should have better error checking… Should error out instead of trying to continue.

      Did it create the staging dir, strip, and compress it properly?

      If you contact me through the contact page we can exchange emails and then I can see the entire output of the script. Might help narrow it down.

  3. Comment by Tres Finoccchiaro:

    Ok, the fix was to change + 1.0 to + 5.0 when it’s padding the file size (2.0 may have worked too, but this should work good enough to commit to our master branch) :)

    Thanks again. This script was a huge help without a lot of bloat or reading. :)

    -Tres

  4. Comment by Matthias:

    Hello, Awesome Script!
    We did just run into a problem when running the script on a non english Mac.
    We solved it by adding
    LANG=en_GB
    to the top of the script.
    This info might help some people figuring out why it does not work for them (The calculation of the dmg size fails because we are using , as comma)

    Thanks again,
    Matthias

  5. Comment by Damien Cassou:

    What about putting your work on github so that people can contribute and everyone benefit from updates?

Leave a Reply

Your email address will not be published. Required fields are marked *