The Power Of Plist

August 3rd, 2011

Most Mac and iOS developers know that when you build an application, you advertise a number of details about the application in the “Info.plist” file, located inside the application bundle. You can examine any application on your Mac and see what kind of information the developer has conveyed about it:

  1. Navigate to a .app file in the Finder, e.g. /Applications/Mail.app
  2. Control-click the app icon and select “Show Package Contents”
  3. Navigate to Contents/Info.plist
  4. Open with a plist editor or your favorite text editor.

These files advertise a number of interesting attributes including the application’s official version and copyright strings. They also include important clues to the system about what kinds of files the application knows how to read and write, and what its minimum system requirements are.

Minimum System Requirements

Declaring the right Info.plist values not only allows a developer to control which operating systems a product should run on, but which of the application’s architectures should be considered for a particular operating system. For example, Black Ink uses a number of keyed values describing its requirements:

	<key>LSArchitecturePriority</key>
	<array>
		<string>x86_64</string>
		<string>i386</string>
		<string>ppc</string>
	</array>
	<key>LSMinimumSystemVersion</key>
	<string>10.4.0</string>
	<key>LSMinimumSystemVersionByArchitecture</key>
	<dict>
		<key>i386</key>
		<string>10.4.0</string>
		<key>x86_64</key>
		<string>10.6.0</string>
		<key>ppc</key>
		<string>10.4.0</string>
	</dict>

Notice the fidelity of some of these options. Black Ink is an application that is compiled with binary code for three separate architectures embedded into it: 64-bit Intel, 32-bit Intel, and 32-bit PowerPC. In order to give the user the best possible experience after they double-click the application icon, the system consults the Info.plist values to determine which binary is most appropriate to load on the current system.

The options for Black Ink start by indicating that all things being equal, it prefers to run as 64-bit Intel, but will settle for 32-bit Intel or PowerPC in a pinch. Next, it conveys that it should not be run on any operating system earlier than Mac OS X 10.4. Finally, it adds an additional restriction by architecture, stating that in the case of 64-bit Intel, the system should consider Mac OS X 10.6 the minimum required OS.

Why so picky? For example, Mac OS X 10.5 will run on computers that are new enough to support 64-bit Intel code, but the 10.5 operating environment itself doesn’t contain enough compatible libraries to make it very useful to a full-featured Cocoa application. So we need to convince the 10.5 system to ignore our 64-bit Intel code. And this is how it’s done.

Embedding Info.plist

This is all well and good for applications, but what about other code that may be run on a variety of hardware and operating systems? In particular, command-line tools do not come in the same bundled-folder format that applications do. Fortunately, Apple thought of this when they implemented support in their developer tools for embedding the contents of an Info.plist directly into the binary itself. You just have to pass the Info.plist path to Apple’s linker tool when it’s constructing your binary file. (Thanks to Paul Kim for reminding me of this functionality). What this means in practice is adding arguments like this to your Xcode target’s “Other Linker Flags” build setting:

-sectcreate __TEXT __info_plist $(INFOPLIST_FILE)

This instructs the linker to crete a new text segment named “__info_plist” in the resulting binary, and to fill it with the contents of the referenced Info.plist file. To make sure the INFOPLIST_FILE expands correctly, just make sure you set it in the separate build setting for identifying the Info.plist (the one you’d normally use in an app, and that is just ignored by default for a command-line tool target).

I brushed up on all this information because I wanted to help ensure that some recent work I did to create a standalone MultiMarkdown tool would be backward compatible with older systems. This required adding an embedded plist much as I’m describing here.

(Note: I have gotten some feedback to the effect that the __info_plist segment’s minimum system version requirements may not actually be consulted properly on Mac OS X 10.5. This would be a bummer, and in fact sort of reject the whole point of embedding the Info.plist in this case. I’m going to see if I can confirm whether it doesn’t in fact work.)

You could technically embed all kinds of stuff in the binary, with different section names. But the contract in this case is that when Mac OS X is determining information about an executable, it will consult the bundle’s Info.plist file, if it happens to be an executable in a bundle, or the binary’s __info_plist segment, if it happens to have one.

Another common reason for needing to embed Info.plist information into a standalone binary is if you are using Apple’s code signing mechanism to sign an individual binary tool. Code signing uses information from the Info.plist of a product, and in the case of standalone binaries, the only product-cohesive place to put this is in the binary itself.

Examining Binary Info.plists

After you’ve performed the magic above, you’ll probably be keen to inspect your command-line tool’s Info.plist to see if it worked. To do this, you can use the otool command from the Finder. If you run otool with the “-l” option to show all load commands, it will include the load command that identifies the __info_plist segment. Use grep to narrow it down to the part you’re interested in:

otool -l ./yourTool | grep info_plist -B1 -A10

Any results at will confirm that there is Info.plist information in the binary, but how does it look? The “-s” option to otool lets you examine the contents of a specific segment in a binary, but it dumps it out as hex code. Fortunately, another system-bundled tool called “xxd” is capable of easily converting between hex-dump and text formats. As it turns out, some of Apple’s bundled developer tools (at least on my Mac) contain these embedded __info_plist sections, so if you don’t have a command line tool of your own to try this on, you can peek at what the “atos” tool has to say for itself:

otool -X -s __TEXT __info_plist /usr/bin/atos | xxd -r

In Summary

Info.plist values are important for conveying information about your product, from the crudest, most obvious stuff like version number, to the most nuanced details such as which architectures are supported. Knowing how to specify an application or tool’s requirements as precisely as possible will ensure that the product performs optimally on whatever supported system your user happens to be using. I’ve barely scratched the surface here with a few common deployment keys that control execution behavior on Mac OS X. Be sure to skim Apple’s Information Property List Key Reference to see if there are other useful bits of information you can share for your application or for your command-line tool.

Windowless Skyscraper

August 3rd, 2011

One of the thrills of software development is how much power is placed into the hands, literally, of a single engineer. Software takes work, and lots of it. But thanks to frameworks of reusable code, individuals are consistently able to “outbuild” the work of our predecessors, while exerting the same or less effort.

Consider the work that went into the first word processors and web browsers, whose work can now be mimicked by a Mac developer who knows how to embed NSTextView or or WebView. Imagine the time that early game developers invested in rudimentary sprite drawing, animation, and collision, which is now achieved easily in iOS games with open source packages such as cocos2d.

Still, building truly great software continues to elude most developers. It’s easy to assume that a large amount of time invested in a project, combined with an impressive outcome, is the key to a successful product. But it’s not so simple.

The ninety-ninety rule is often cited when describing the challenge of finessing a product after most of the hard work has seemingly been done:

“The first 90 percent of the code accounts for the first 90 percent of the development time. The remaining 10 percent of the code accounts for the other 90 percent of the development time.” — Tom Cargill

I agree with this perspective, and I cite it often when discussing software with others. The rule as stated is in terms of “code” but is also applicable to all the visual design, user experience, marketing, and positioning of a product. I think the rule is also recursive: whatever is missing can always be split up such that an “easy” 90% of the job can be done, leaving an elusive 10% of finesse work.

Many developers mistakenly assume that after they’ve put a ton of work into a project, and it achieves some impressive feat, that their work is done. When you focus on the enormity of work completed thus far, it’s tempting to pat yourself on the back and call it a day.

But customers don’t care about the hard work that went into the 90%. They only notice the flaws or omissions in the 10%. Imagine if Michelangelo’s statue of David was perfect in every detail, except that where David’s face should be, a clump of ragged, unfinished marble lay crudely in its place. Instead of marveling at the exquisite details of David’s feet, torso, and arms, viewers would reject it as unfinished and clumsy.

An important takeaway for software developers is that the missing 10%, or the missing one-tenth of 10%, may be something that will take a great deal of work to get right, but it may be something you simply overlooked the importance of.

You might build an impressive skyscraper projecting 40 stories into the sky. The architecture, interior design, plumbing, and electrical work may all be superior to that of your peers. But if some blindness in your product vision prevents you from adding windows, the product will never sell. It doesn’t matter how much time or effort went into this masterpiece: nobody will live in a windowless skyscraper.

Facebook’s Design Vacuum

August 2nd, 2011

Facebook has acquired Push Pop Press, the tablet-oriented publishing company that was co-founded by one of the Mac community’s most successful young designers: Mike Matas.

I learned about the news via Lessien on Twitter, a woman about whom I know little, except that she offers reliably intelligent opinion about the tech world, and the mobile industry in particular. She shared the news with some curiosity about Facebook’s role in the deal:

Wow, although I’m a bit surprised by the buyer. Congrats to the @pushpoppress team.

It does seem a little unusual for Facebook to acquire a publishing company. But Facebook has made at least one similar acquisition recently: Sofa, the Dutch Mac developer and design firm. What interest did Facebook have in a company that sells Mac-only point of sale and developer software tools? They didn’t.

Facebook bought Sofa for their world-class design team. I expect the situation is similar when it comes to Push Pop Press. I can imagine Facebook putting Push Pop’s publishing software to some good use, but that’s just the icing on the Mike Matas cake.

Who will Facebook acquire next? Don’t let product scope cloud your crystal ball. Look for the most consistently polished user experiences in the software you use in any industry, on any platform. If it’s on Facebook’s radar, don’t be surprised to see them acquired next.

This speaks well to Facebook’s product priorities, especially as they are increasingly framed as a competitor to Google, whose design is famously underwhelming. For Facebook, setting themselves apart as purveyors of finely crafted interfaces will become a huge competitive advantage.

MarsEdit 3.3.2: Fixed Spell Checking

August 2nd, 2011

MarsEdit 3.3.2 is now available as a free update for registered MarsEdit 3 customers. New customers may purchase via the Mac App Store or directly from the Red Sweater Store.

This update addresses an annoying issue that popped up with Lion 10.7 and on Snow Leopard 10.6 when Safari 5.1 is installed: continuous spell-checking stopped working. It also improves the effectiveness of font-style changes in the rich editor, and includes a couple other minor enhancements.

  • Fix for continuous spell-checking in Rich Text editor when Safari 5.1 is installed
  • Fix a bug that prevented Font Panel size changes from applying to text
  • Fix autoconfiguration to fail more gracefully on unrecognized blog systems
  • Add “Edit With” external editor item to post list contextual menu