Qt, OSX app bundles, and you

Perhaps Qt’s biggest selling point (among others), is the ability to write an application once and run it just about anywhere. Distribution for each of these environments has it’s own challenges. Lets talk about OSX for a moment, the bundles generated by Qt have a generic icon when viewed in Finder (or the dock). Once the application loads, it appears to get it’s icon from the window icon. This doesn’t look terribly professional, so how about we fix it?

Icon-less App

As a C++ developer primarily working in Linux / Windows, everything about distribution on Mac is quite strange. Instead of executing binaries, you’re opening app bundles. You don’t know what a bundle is, you can’t execute it from the command line, all your libraries are compiling in some weird format, so by this point you’re having a really bad day and you don’t like it one bit. An application bundle, as it turns out, is merely a set of directories containing your binary, frameworks, and configuration. You can execute the bundle from the command line by running ‘open bundle.app’, or by double clicking it in Finder.

After you compile a Qt application in OSX, explore the bundle in Finder, or use the terminal. Inside you will find something called an info.plist (see Apple’s documentation for more). Long story short, this file lets you set a bunch of important meta data about your application (name, developer, version, etc). Among these, you can set the icon for your application! Huzzah! When creating the application bundle, Qt generates a default plist file. In a moment, I’ll show you how to specify your own custom plist file and include it in the app bundles. The default plist file generated by Qt

Property List

We want to show our users how happy our Qt application is going to make them, so I’ve created a tonally appropriate 512 x 512 icon in GIMP.

Smile Icon

Our application icon exists in png format, but as it turns out the app bundle is looking for a very specific image format. You’ll want to convert your png to icns using iconutil, a command line program provided with XCode. Documentation can be found at Apple’s website, but here’s an abbreviated run down.

Create a directory whose name follows the convention of .iconset . Rename your png file using the following convention: icon_x.png. In my case, I named the icon “icon_512x512.png”. The utility is expecting one of a number of different sizes (specified in the documentation), meaning it specifically looks for one or more of 10 known file names. Apple’s documentation encourages you to generate assets for the different variations, so that your application bundle will look nice under any number of different scenarios (presumably retina vs. non retina, different resolutions, etc). Having renamed your icon, move it to the .iconset directory. From the command line, navigate to the directory where the iconset resides. My iconset was named smile.iconset, therefore the command I ran was iconutil -c icns smile.iconset.

Tada! You now have an icns file ready for your application bundle. Move it into the same directory as your Qt project (*.pro) file.

Now’s a good time to grab one of those default plist files Qt generates from an application bundle. Copy it to the same directory as your Qt project file, so we can make the desired modifications. qmake can cleverly set some plist values on your behalf, items like the application executable name, version number (useful for any crash logs that get generated!), and the icon. Take a peek at the qmake documentation, specifically the QMAKE_INFO_LIST section. Modify the plist file to take advantage of the qmake functionality, and manually fiddle with the bits that suit your fancy. Apple’s documentation has a list of the various property keys you can set in your plist file.

Now let’s modify your qmake project file to use your custom plist file. Having copied the plist and icns files to the same directory as my project file, I can add the following block to myapp.pro:

macx {
     QMAKE_INFO_PLIST = Info.plist
     ICON = smile.icns

Run qmake and compile. Your application bundle should now have a custom icon in Finder and when in the dock. Congratulations!

Icon-full App

Since we’re on the topic of application bundles, Qt Project documentation has a great article on the additional hurdles required to get Qt apps packaged correctly on Mac. If you’re interested in getting an app packaged for the app store, I would recommend taking a look at Digia’s blog on the topic.

As a disclaimer, I’m using OSX Mountain Lion w/ XCode 4.5. For earlier versions of XCode, the tool to generate the iconset is different. Do a google search for Icon Composer.