|Home » Learning Curve » Developers Workshop
Building and Packaging Native OS X Applications
The reason for this article should be obvious: too many OS X third party developers do an absolutely terrible job of building and packaging their applications.
Formerly they were called Development and Deployment: with Xcode Apple nodded to Redmond and renamed them Debug and Release. These are the two configurations for building your application.
You almost never need Debug; make Release your default.
Set your build to optimise for size. This should be the default but check anyway. Once upon a time Microsoft had a weird idea about creating lugubrious snippets of code to optimise their AFX; with the advent of Cutler this folly was dashed into oblivion - and any student of the Aho 'dragon books' knows optimisation for size is not only the most compact but the fastest as well.
Add the compiler flag '-no-cpp-precomp'. You shouldn't be using C++ anyway. This will save you a lot of time on builds.
Never choose to put resources in a resource fork. You shouldn't have any anyway. Opt to have them put in separate files.
Never let your project revert to an 'install' directory. Frameworks need a static location but you don't have to set this otherwise.
Unless you're already doing localisations for your application and/or intend to add localisations before release, get rid of your default 'lproj' directory. Select all your resources, delete their references, then move them up to the Resources directory and add them back.
Design your app as 'standard' as you can. This means giving recognition to the so called 'recognition principle': users shouldn't have to hunt around for features in your application but instinctively know where to find them.
This applies to keyboard shortcuts as well. Use only standard shortcuts. And when it comes to fancy 'gizmos' on screen: restrain yourself. Odds are your code will be buggy; it can't have been tested as much or as well as Apple's own; and your user isn't going to appreciate it either. This applies to toolbar glyphs as well: use standard glyphs.
And remember that toolbars hang on document windows - so if you don't need them then don't use them. They're 'malplaced' so to speak. Keep that in mind.
Offer everything you can on the standard 'Edit' menu and don't remove items unless you absolutely have no use for them. Don't think in terms of your application: think in terms of all possible things a user can do, whether in direct connection to your application or not.
Do not keep extraneous items on the 'File' menu - in particular don't keep printing items unless you really intend to print.
And if your app can't open recent, then remove that item; if your app won't be saving files, then remove the corresponding items; and so forth.
And if you don't have 'help' then for heavens sake see you don't have a menu item for it.
If you have a single window application then make sure the user can't close this window without exiting the application. Flag the delegate methods to find out when the window is being closed and then exit.
Make sure your application never saves its 'factory defaults' to its preferences file. If nothing changes in the application's configuration then nothing should be saved. Period. You can also check your internal configuration against your 'factory defaults' before saving and remove any that are identical. Under no circumstances should you willy-nilly just save your 'defaults' at application exit without checking first if you're making a total fool out of yourself - and your end user. You're a 'guest' on your user's machine: treat your user with respect.
Getting Ready for Release
Using a Release configuration to build your application is never good enough: you must build your application from the command line. Apple have sufficient documentation online as to how this is done. Frameworks will revert to a subdirectory under /tmp; ordinary applications will place under ./build.
Pruning Your Final Build
Apple's IDEs will set the modes on your application files in a weird way. This is fine for your end users but it's not so fine for you.
Mask all files with 077 and make sure all your directories are writable. Mark all files that can be 0400 with 0400. Your directories and executables should be 0700 and your files should be 0400. [Your executables can be 0500 but your directories should not be: you need to get in and get out of there as you prune your build.]
Remove the following files.
- PkgInfo. This file wastes 4,088 bytes of disk space. Get rid of it. It's only needed by non-native (Carbon) applications. The exact same info is already found in Info.plist. Just get rid of it.
- Anything resembling 'pbdevelopment.plist'. If you find this file it indicates you've not made a proper final build anyway.
- NIB files such as classes.nib, data.dependency, and info.nib. You must retain objects.nib (or keyedobjects.nib) as this is the 'freeze dried' code your application will use. All other files - aside from graphics files - in a NIB are to be removed. And if you have graphics files inside a NIB - move them up to Resources. The program loader [NSBundle] will have an easier time finding them and such an arrangement is a cleaner and tidier way to go. No file save for objects.nib (or keyedobjects.nib) ever need be in your NIB. Period.
- Never use keyedobjects.nib if you can get away with objects.nib. The former wastes a lot of disk space.
- Do you have embedded frameworks? Why? OK - sidestepping that for a second: do not include header files or the 'Headers' directory in your final build. If they're there then remove them.
- Are those embedded frameworks you shouldn't have anyway coming with localisations your application doesn't support? Then remove them. Make a habit of looking inside the code you're borrowing.
- Embedding frameworks is a mess anyway: you have to set them inside your projects and in no time you've got redundancy all over your end users' disks. Find a suitable place for these frameworks such as /Library/Frameworks and then just copy the appropriate files into your source for the DMG or zip archive you create. [See below.]
- .DS_Store. If you're a developer and using Finder for file management then you're not a real developer. Get a better tool. Make sure you have no .DS_Store nonsense inside your application packages - after all, you might get roasted here and can that be any good?
Distributing Your Application
Don't use Apple's Installer.app unless you really need it. And if you claim you really need it, be prepared to defend that position rigourously. Installer.app is easy to screw up to the point it messes with end user disks. So don't use it unless it's absolutely necessary - and most of the time it definitely is not.
Do not lock your user into a specific install location and do not default to /Applications. Default if you must to ~/Applications and be prepared to create it if it doesn't exist.
DMGs are popular but they're not particularly efficient; consider a zip archive of some sort. But when you do make sure you're not including resource fork ('AppleDouble') cruft in the archive. Here again is why you need better than Finder: you need to see the files you're sending out to people. Use a proper tool to make your zip or DMG and check the source directory for nonsense files before you build.
And for goodness sake: if you really need the user's administrator passphrase to install, tell the user why.
Testing Your Application
Now pretend you're an end user and 'install' your application yourself and run it. Does everything work as you planned? Odds are the first few attempts will have minor snags. Take the time to keep testing until you get it 'just right'.
Software Reviews: The Very Ugly