Mac Developer Roundtable #11
The Mac Developer Network features an excellent series of podcasts aimed at both veteran Mac developers and those new to the platform who are interested in developing for the Mac. If you’re a current Mac coder and haven’t seen them yet, be sure to check them out. I’ve been listening to the podcasts for a long time, and they’re always both informative and entertaining. (Infotainment, baby.)
Well, in yet another case of “Wow, do I really sound like that?”, I became a guest on The Mac Developer Roundtable episode #11, along with Marcus Zarra, Jonathan Dann, Bill Dudney, and our always-eloquent and delightfully British host, Scotty. The primary topic was Xcode 3.1, but we also chatted about the iPhone NDA (c’mon Apple, lift it already!) and… Fortran. I think I even managed to sneak in the words “Haskell” and “Visual Studio” in there, which no doubt left the other show guests questioning my sanity. I do look forward to Fortran support in Xcode 4.0.
It was actually a small miracle that I managed to be on the show at all. Not only was the podcast recording scheduled at the ungodly time of 4am on a Saturday morning in Australian east-coast time, but I was also in transit from Sydney to the amazing alpine village of Dinner Plain the day before the recording took place. While Dinner Plain is a truly extraordinary village that boasts magnificent ski lodges and some of the best restaurants I’ve ever had the pleasure of eating at, it’s also rather… rural. The resident population is somewhere around 100, the supermarket doesn’t even sell a wine bottle opener that doesn’t suck, and Vodafone has zero phone reception there. So, it was to my great surprise that I could get ADSL hooked up to the lodge there, which was done an entire two days before the recording. Of course, since no ADSL installation ever goes smoothly, I was on the phone to iPrimus tech support1 at 10pm on Friday night, 6 hours before the recording was due to start. All that effort for the privilege of being able to drag my sleepy ass out of bed a few hours later, for the joy of talking to other Mac geeks about our beloved profession. But, I gotta say, being able to hold an international conference call over the Intertubes from a tiny little village at 4am in the morning, when snow is falling all around you… I do love technology.
Of course, since I haven’t actually listened to the episode yet, maybe it’s all a load of bollocks and I sound like a retarded hobbit on speed. Hopefully not, though. Enjoy!
1 Hey, I like Internode and Westnet as much as every other Australian tech geeks, but they didn’t service that area, unfortunately.
Xcode Distributed Builds Performance
[Sorry if you get this post twice—let’s say that our internal builds of RapidWeaver 4.0 are still a little buggy, and I needed to re-post this ;)]
Xcode, Apple’s IDE for Mac OS X, has this neat ability to perform distributed compilations across multiple computers. The goal, of course, is to cut down on the build time. If you’re sitting at a desktop on a local network and have a Mac or two to spare, distributed builds obviously make a lot of sense: there’s a lot of untapped power that could be harnessed to speed up your build. However, there’s another scenario where distributed builds can help, and that’s if you work mainly off a laptop and occasionally join a network that has a few other Macs around. When your laptop’s offline, you can perform a distributed build with just your laptop; when your laptop’s connected to a few other Macs, they can join in the build and speed it up.
There’s one problem with idea, though, which is that distributed builds add overhead. I had a strong suspicion that a distributed build with only the local machine was a significant amount slower than a simple individual build. Since it’s all talk unless you have benchmarks, lo and behold, a few benchmarks later, I proved my suspicion right.
- Individual build: 4:50.6 (first run), 4:51.7 (second run)
- Shared network build with local machine only: 6:16.3 (first run), 6:16.3 (second run)
This was a realistic benchmark: it was a full build of RapidWeaver including all its sub-project dependencies and core plugins. The host machine is a 2GHz MacBook with 2GB of RAM. The build process includes a typical number of non-compilation phases, such running a shell script or two (which takes a few seconds), copying files to the final application bundle, etc. So, for a typical Mac desktop application project like RapidWeaver, turning on shared network builds without any extra hosts evokes a pretty hefty speed penalty: ~30% in my case. Ouch. You don’t want to leave shared network builds on when your laptop disconnects from the network. To add to the punishment, Xcode will recompile everything from scratch if you switch from individual builds to distributed builds (and vice versa), so flipping the switch when you disconnect from a network or reconnect to it is going to require a full rebuild.
Of course, there’s no point to using distributed builds if there’s only one machine participating. So, what happens when we add a 2.4GHz 20” Aluminium Intel iMac with 2GB of RAM, via Gigabit Ethernet? Unfortunately, not much:
- Individual build: 4:50.6 (first run), 4:51.7 (second run)
- Shared network build with local machine + 2.4GHz iMac: 4:46.6 (first run), 4:46.6 (second run)
You shave an entire four seconds off the build time by getting a 2.4GHz iMac to help out a 2GHz MacBook. A 1% speed increase isn’t very close to the 40% build time reduction that you’re probably hoping for. Sure, a 2.4GHz iMac is not exactly a build farm, but you’d hope for something a little better than a 1% speed improvement by doubling the horsepower, no? Gustafson’s Law strikes again: parallelism is hard, news at 11.
I also timed Xcode’s dedicated network builds (which are a little different from its shared network builds), but buggered if I know where I put the results for that. I vaguely remember that dedicated network builds was very similar to shared network builds with my two hosts, but my memory’s hazy.
So, lesson #1: there’s no point using distributed builds unless there’s usually at least one machine available to help out, otherwise your builds are just going to slow down. Lesson #2: you need to add a significant amount more CPUs to save a significant amount of time with distributed builds. A single 2.4GHz iMac doesn’t appear to help much. I’m guessing that adding a quad-core or eight-core Mac Pro to the build will help. Maybe 10 × 2GHz Intel Mac minis will help, but I’d run some benchmarks on that setup before buying a cute Mac mini build farm — perhaps the overhead of distributing the build to ten other machines is going to nullify any timing advantage you’d get from throwing another 20GHz of processors into the mix.
Mac OS X Software List Updated
WWDC Craziness

- Meet new people (✓),
- Catch up with fellow Aussies I haven’t seen in years (✓),
- Go to parties (✓),
- Behave appropriately at said parties (✓),
- Use the phrase “Inconceivable!” inappropriately (✓),
- Work on inspiring new code (✓),
- Keep up with Interblag news (✗),
- Keep up with RSS feeds (✗),
- Keep up with personal email (✗),
- Keep up with work email (✗),
- Installed Leopard beta (✓),
- Port code to work on Leopard (✗),
- Successfully avoid Apple Store, Virgin, Banana Republic et al in downtown San Francisco (✓),
- Keep family and friends at home updated (✓),
- Mention the words “Erlang”, “Haskell” and
“higher-order
messaging” to
puny humansfellow Objective-C programmers (✓), - Write up HoPL III report (✗),
- Find and beat whoever wrote NSTokenField with a large dildo (✗),
- Get food poisoning again (✗),
- Sleep (✗),
- Actually attend sessions at the conference
(
✓✗).
California USA 2007 Tour
Where’s André in June?
- June 7-10: San Diego (for the History of Programming Languages III conference.)
- June 11-20: San Francisco (for Apple’s WWDC 2007 bash)
- June 20-28: Las Vegas
- June 24-28: Los Angeles
If you’ll be in town on any of those dates or going to HoPL or WWDC, drop me an email!
As an aside, HoPL III looks incredible: Waldemar Celes (Lua), Joe Armstrong (Erlang), Bjarne (C++), David Ungar (Self), and the awesome foursome from Haskell: Paul Hudak, John Hughes, Simon Peyton Jones and Phil Wadler. (Not to mention William Cook’s great paper on AppleScript, which I’ve blogged about before.) Soooo looking forward to it.
VMware Fusion Beta 3 vs Parallels
Parallels Desktop for Mac was the first kid on the block to support virtualisation of other PC operating systems on Mac OS X. However, in the past fortnight, I’ve found out that:
- Parallels allocates just a tad too many unnecessary Quartz windows1, which causes the Mac OS X WindowServer to start going bonkers on larger monitors. I’ve personally seen the right half of a TextEdit window disappear, and Safari not being able to create a new window while Parallels is running, even with no VM running. (I’ve started a discussion about this on the Parallels forums.)
- Parallels does evil things with your
Windows XP Boot Camp partition, such as replace
your
ntoskrnl.exeandhal.dllfile and rewriting the crucialboot.inifile. This causes some rather hard-to-diagnose problems with some low-level software, such as MacDrive, a fine product that’s pretty much essential for my Boot Camp use. Personally, I’d rather not use a virtualisation program that decides to screw around with my operating system kernel, hardware abstraction layer, and boot settings, thank you very much.
VMware Fusion does none of these dumbass things, and provides the same, simple drag’n’drop support and shared folders to share files between Windows XP and Mac OS X. I concur with stuffonfire about VMware Fusion Beta 3: even in beta, it’s a lot better than Parallels so far. Far better host operating system performance, better network support, hard disk snapshots (albeit not with Boot Camp), and DirectX 8.1 support to boot. (A good friend o’ mine reckons that 3D Studio runs faster in VMware Fusion on his Core 2 Duo MacBook Pro than it does natively on his dedicated Athlon 64 Windows machine. Nice.) The only major feature missing from VMware Fusion is Coherence, and I can live without that. It’s very cool, but hardly necessary.
Oh yeah, and since VMWare Fusion in beta right now, it’s free as well. Go get it.
1 Strictly speaking, allocating a ton of Quartz windows is Qt’s fault, not Parallels’s fault. Google Earth has the same problem. However, I don’t really care if it’s Qt’s fault, considering that it simply means running Parallels at all (even with no VM open) renders my machine unstable.
Objective-C Accessors
I like Objective-C. It’s a nice language. However, having to write accessor methods all day is boring, error-prone, and a pain in the ass:
- (NSFoo*) foo{ return foo;}- (void) setFoo:(NSFoo* newFoo){ [foo autorelease]; foo = [newFoo retain];}I mean, c’mon. This is Objective-C we’re talking about, not Java or C++. However, until Objective-C 2.0’s property support hits the streets (which, unfortunately, will only be supported on Mac OS X 10.5 and later as far as I know), you really have to write these dumb-ass accessors to, well, access properties in your objects correctly. You don’t need to write accessors thanks to the magic of Cocoa’s Key-Value Coding, but it just feels wrong to access instance variables using strings as keys. I mean, ugh—one typo in the string and you’ve got yourself a problem. Death to dynamic typing when it’s totally unnecessary.
As such, I got totally fed up with this and wrote a little script to generate accessor methods. I’m normally not a fan of code generation, but in this case, the code generation’s actually designed to be one-shot, and it doesn’t alter the ever-picky build process. It’s meant to be used in Xcode, although you can run it via the commandline too if you like.
Given the following input:
int integerThing;NSString* _stringThing;IBOutlet NSWindow* window;It will spit out the following:
#pragma mark Accessors- (int) integerThing;- (void) setIntegerThing:(int)anIntegerThing;- (NSString*) stringThing;- (void) setStringThing:(NSString*)aStringThing;- (NSWindow*) window;- (void) setWindow:(NSWindow*)aWindow;%%%{PBXSelection}%%%#pragma mark Accessors- (int) integerThing{ return integerThing;}- (void) setIntegerThing:(int)anIntegerThing{ integerThing = anIntegerThing;}- (NSString*) stringThing{ return _stringThing;}- (void) setStringThing:(NSString*)aStringThing{ [_stringThing autorelease]; _stringThing = [aStringThing copy];}- (NSWindow*) window{ return window;}- (void) setWindow:(NSWindow*)aWindow{ [window autorelease]; window = [aWindow retain];}There’s a couple of dandy features in the script that I find useful, all of which are demonstrated in the above output:
- It will detect whether your instance variables
start with a vowel, and write out
anIntegerinstead ofaIntegeras the parameter names for the methods. - It will
copyrather thanretainvalue classes such as NSStrings and NSNumbers, as God intended. - For all you gumbies who prefix your instance variables with a leading underscore, it will correctly recognise that and not prefix your accessor methods with an underscore.1
- IBOutlet and a few
other type qualifiers (
__weak,__strong,volatileetc) are ignored correctly. - It will emit Xcode-specific
#pragma markplaces to make the method navigator control a little more useful. - It will emit Xcode-specific
%%%{PBXSelection}%%%markers so that the accessor methods meant to go into your.mimplementation file are automatically selected, ready for a cut-and-paste.
Download the objc-make-accessors
script and throw it into your
“~/Library/Application Support/Apple/Developer
Tools/Scripts” folder. If you don’t have one
yet:
Done. You should now have a Scripts menu in Xcode with a new menu item named “IVars to Accessor Methods”. Have fun.
1 Note that older versions of the Cocoa Coding Guidelines specified that prefixing instance variables with underscores is an Apple-only convention and you should not do this in your own classes. Now the guidelines just don’t mention anything about this issue, but I still dislike it because putting underscores every time you access an instance variable really lowers code readability.
Cocoa Users Group in Sydney
To all the Mac users out there: would you be
interested in a Cocoa Users’ Group in Sydney? If so,
please drop me an email—my address is at the bottom
of the page—and if there’s enough numbers, perhaps we
can organise something. The idea’s to have a local
forum for geekupsmeetups, random
presentations, mailing lists, and all that sort of
fun stuff.
Oh yeah, and please also let me know your self-described level of expertise: none, novice, intermediate, expert.
(For those who closely track the Cocoa scene in Australia: yep, this is the same call for interest that Duncan Campbell has initiated.)
Mac OS X Software for the Uninitiated
I have a lot of friends who’ve switched to Mac OS X from both Windows and Linux in the past few years. I think it’s a good computing platform (duh, otherwise I wouldn’t be using it), but of course it can take a while to find all those handy little bits of software that make life just a bit easier.
So, since I’m a lazy bastard and got sick of regurgitating my list of Mac OS X software to switcher friends in the past few years, I finally made a Mac OS X Resources page with a list of software that I personally use and think kicks ass. There’s also a (small) collection of hints and tips, including some coding tips for those moving across from Linux. (I’m aware that the coding tips really are quite sparse — I’ll hopefully find some time to expand that in the future.) I hope the resources page is useful for someone else out there: if you do find it useful, a very simple one-line email saying thanks is always appreciated! As Larry Wall would say, have the appropriate amount of fun.
For the Mac Vim lovers
Do you like Mac OS X?
Do you like… Vim?
If so, your prayers may just have been answered: see the Vi Input Manager Plugin by Jason Corso. Vi-style key bindings in any Mac OS X text input area? Schyeah baby. As Jason says:
Right now, you should be thinking — “you mean the editor in XCode will behave like Vi?” Answer: Yes.
It’s open source too. Nice work Jason; let the hacking begin!
Insights into AppleScript
I recently encountered a paper written by William Cook about a mysterious little programming language that even many programming languages researchers don’t know about: AppleScript. Yep, that’d be the humble, notoriously English-like Mac scripting language that’s renown to be slow and annoying more than anything else. The paper is a fascinating look at the history of AppleScript, and details many insights and innovations that were largely unknown. Here’s some things that I was pleasantly surprised about.
Cook had never used a Mac before he was employed to work on AppleScript: in fact, he had a very strong UNIX background, and had a great amount of experience with UNIX shell scripting. So, one can instantly dismiss the notion that whoever designed AppleScript had “no idea about the elegance of interoperating UNIX tools”: a remark that I’m sure many would have made about the language (myself included). Cook even remarks that Apple’s Automator tool, introduced in Mac OS 10.4 Tiger, was quite similar to UNIX pipes:
The most interesting thing about Automator is that each action has an input and an output, much like a command in a Unix pipe. The resulting model is quite intuitive and easy to use for simple automation tasks.
More on UNIX pipes, he writes that
the sed stream editor can create the customized text file, which is then piped into the mail command for delivery. This new script can be saved as a mail-merge command, which is now available for manual execution or invocation from other scripts.
He then continues with something seemingly obvious, but is nevertheless something I have never thought about UNIX scripts:
One appealing aspect of this model is its compositionality [emphasis mine]: users can create new commands that are invoked in the same way as built-in commands.”
Indeed! In a way, the ability to save executable shell scripts is the equivalent of writing a named function to denote function composition in a functional programming language: it enables that composed code to be re-used and re-executed. It’s no coincidence that the Haskell scripts used in Don Stewart’s h4sh project are semantically quite similar to their equivalent Bourne shell scripts, where Haskell’s laziness emulates the blocking nature of pipes.
More on UNIX: Cook later writes that
A second side effect of pervasive scripting is uniform access to all system data. With Unix, access to information in a machine is idiosyncratic, in the sense that one program was used to list print jobs, another to list users, another for files, and another for hardware configuration. I envisioned a way in which all these different kinds of information could be referenced uniformly… A uniform naming model allows every piece of information anywhere in the system, be it an application or the operating system, to be accessed and updated uniformly.
The uniform naming model sounds eerily familiar who had read Hans Reiser’s white paper about unified namespaces. Has the UNIX world recognised yet just how powerful a unified namespace can be? (For all the warts of the Windows registry, providing the one structure for manipulating configuration data can be a huge benefit.)
Cook was also quite aware of formal programming language theory and other advanced programming languages: his Ph.D thesis was in fact on “A Denotational Semantics of Inheritance”, and his biography includes papers on subtyping and F-bounded polymorphism. Scratch another urban myth that AppleScript was designed by someone who had no idea about programming language theory. He makes references to Self and Common LISP as design influences when talking about AppleScript’s design. However,
No formal semantics was created for the language, despite an awareness that such tools existed. One reason was that only one person on the team was familiar with these tools, so writing a formal semantics would not be an effective means of communication… Sketches of a formal semantics were developed, but the primary guidance for language design came from solving practical problems and user studies, rather than a-priori formal analysis.
(There’s some interesting notes regarding user studies later in this post.) Speaking of programming language influences,
HyperCard, originally released in 1987, was the most direct influence on AppleScript.
Ah, HyperCard… I still remember writing little programs on HyperCard stacks in high school programming camps when I was a young(er) lad. It’s undoubtedly one of the great programming environment gems of the late 80s (and was enormously accessible to kids at the same time), but that’s an entire story unto itself…
The Dylan programming language is also mentioned at one point, as part of an Apple project to create a new Macintosh development environment (named Family Farm). ICFPers will be familiar with Dylan since it’s consistently in the top places for the judge’s prize each year; if you’re not familiar with it, think of it as Common LISP with a saner syntax.
AppleScript also had a different approach to inter-appication messaging. Due to a design flaw in the classic MacOS, AppleScript had to package as much information into its inter-application data-passing as possible, because context switches between applications on early MacOS systems were very costly:
A fine-grained communication model, at the level of individual procedure or method calls between remote objects, would be far too slow… it would take several seconds to perform this script if every method call required a remote message and process switch. As a result, traditional RPC and CORBA were not appropriate… For many years I believed that COM and CORBA would beat the AppleScript communication model in the long run. However, COM and CORBA are now being overwhelmed by web services, which are loosely coupled and use large granularity objects.
Web Services, eh? Later in the paper, Cook mentions:
There may also be lessons from AppleScript for the design of web services. Both are loosely coupled and support large-granularity communication. Apple Events data descriptors are similar to XML, in that they describe arbitrary labeled tree structures without fixed semantics. AppleScript terminologies are similar to web service description language (WDSL) files. One difference is that AppleScript includes a standard query model for identifying remote objects. A similar approach could be useful for web services.
As for interesting programming language features,
AppleScript also supports objects and a simple transaction mechanism.
A transaction mechanism? Nice. When was the last time you saw a transaction mechanism built into a programming language (besides SQL)? Speaking of SQL and domain-specific languages, do you like embedded domain-specific languages, as is the vogue in the programming language research community these days? Well, AppleScript did it over a decade ago:
The AppleScript parser integrates the terminology of applications with its built-in language constructs. For example, when targeting the Microsoft Excel application, spreadsheet terms are known by the parser—nouns like cell and formula, and verbs like recalculate. The statement tell application “Excel” introduces a block in which the Excel terminology is available.
Plus, if you’ve ever toyed with the idea of a programming language that could be written with different syntaxes, AppleScript beat you to that idea as well (and actually implemented it, although see the caveat later in this note):
A dialect defines a presentation for the internal language. Dialects contain lexing and parsing tables, and printing routines. A script can be presented using any dialect—so a script written using the English dialect can be viewed in Japanese… Apple developed dialects for Japanese and French. A “professional” dialect which resembled Java was created but not released… There are numerous difficulties in parsing a programming language that resembles a natural language. For example, Japanese does not have explicit separation between words. This is not a problem for language keywords and names from the terminology, but special conventions were required to recognize user-defined identifiers. Other languages have complex conjugation and agreement rules, which are difficult to implement. Nonetheless, the internal representation of AppleScript and the terminology resources contain information to support these features. A terminology can define names as plural or masculine/feminine, and this information can be used by the custom parser in a dialect.
Jesus, support for masculine and feminine nouns in a programming language? Hell yeah, check this out:

How cool is that? Unfortunately, Apple dropped support for multiple dialects in 1998:
The experiment in designing a language that resembled natural languages (English and Japanese) was not successful. It was assume that scripts should be presented in “natural language” so that average people could read and write them. This lead to the invention of multi-token keywords and the ability to disambiguate tokens without spaces for Japanese Kanji. In the end the syntactic variations and flexibility did more to confuse programmers than help them out. The main problem is that AppleScript only appears to be a natural language on the surface. In fact is an artificial language, like any other programming language… It is very easy to read AppleScript, but quite hard to write it… When writing programs or scripts, users prefer a more conventional programming language structure. Later versions of AppleScript dropped support for dialects. In hindsight, we believe that AppleScript should have adopted the Programmerís Dialect that was developed but never shipped.
A sad end to a truly innovative language feature—even if the feature didn’t work out. I wonder how much more AppleScript would be respected by programmers if it did use a more conventional programming language syntax rather than being based on English. Cook seems to share these sentiments: he states in the closing paragraph to the paper that
Many of the current problems in AppleScript can be traced to the use of syntax based on natural language; however, the ability to create pluggable dialects may provide a solution in the future, by creating a new syntax based on more conventional programming language styles.
Indeed, it’s possible to write Perl and Python code right now to construct and send AppleEvents. Some of you will know that AppleScript is just one of the languages supported by the Open Scripting Architecture (OSA) present in Mac OS X. The story leading to this though, is rather interesting:
In February of 1992, just before the first AppleScript alpha release, Dave Winer convinced Apple management that having one scripting language would not be good for the Macintosh… Dave had created an alternative scripting language, called Frontier… when Dave complained that the impending release of AppleScript was interfering with his product, Apple decided the AppleScript should be opened up to multiple scripting languages. The AppleScript team modified the OSA APIs so that they could be implemented by multiple scripting systems, not just AppleScript… Frontier, created by Dave Winer, is a complete scripting and application development environment. It is also available as an Open Scripting component. Dave went on to participate in the design of web services and SOAP. Tcl, JavaScript, Python and Perl have also been packaged as Open Scripting components.
Well done, Dave!
As for AppleScript’s actual development, there’s an interesting reference to a SubEthaEdit/Gobby/Wiki-like tool that was used for their internal documentation:
The team made extensive use of a nearly collaborative document management/writing tool called Instant Update. It was used in a very wiki-like fashion, a living document constantly updated with the current design. Instant Update provides a shared space of multiple documents that could be viewed and edited simultaneously by any number of users. Each userís text was color-coded and time-stamped.
And also,
Mitch worked during the entire project to provide that documentation, and in the process managed to be a significant communication point for the entire team.
Interesting that their main documentation writer was the communication point for the team, no?
Finally, AppleScript went through usability testing, a practice practically unheard of for programming languages. (Perl 6’s apocalypses and exegeses are probably the closest thing that I know of to getting feedback from users, as opposed to the language designers or committee simply deciding on everything without feedback from their actual userbase!)
Following Appleís standard practice, we user-tested the language in a variety of ways. We identified novice users and asked them “what do you think this script does?” As an example, it turned out that the average user thought that after the command put x into y the variable x no longer retained its old value. The language was changed to use copy x into y instead.
Even more interesting:
We also conducted interviews and a round-table discussion about what kind of functionality users would like to see in the system.
The survey questions looked like this:

The other survey questions in the paper were even more interesting; I’ve omitted them in this article due to lack of space.
So, those were the interesting points that I picked up when I read the paper. I encourage you to read it if you’re interested in programming languages: AppleScript’s focus on pragmatics, ease of use for non-programmers, and its role in a very heavily-based GUI environment makes it a very interesting case study. Thankfully, many Mac OS X applications are now scriptable so that fluent users can automate them effectively with Automator, AppleScript, or even Perl, Python and Ruby and the UNIX shell these days.
Honestly, the more I discover about Apple’s development technologies, the more impressed I am with their technological prowess and know-how: Cocoa, Carbon, CoreFoundation, CoreVideo, QuickTime, vecLib and Accelerate, CoreAudio, CoreData, DiscRecording, SyncServices, Quartz, FSEvents, WebKit, Core Animation, IOKit… their developer frameworks are, for the most part, superbly architectured, layered, and implemented. I used to view AppleScript as a little hack that Apple brought to the table to satisfy the Mac OS X power users, but reading the paper has changed my opinion on that. I now view AppleScript in the same way as QuickTime: incredible architecture and power, with an outside interface that’s draconian and slightly evil because it’s been around and largely unchanged for 15 freaking years.
Pushing the Limits
OK, this is both ridiculous and cool at the same time. I need to write code for Mac OS X, Windows and Linux for work, and I like to work offline at cafes since I actually tend to get more work done when I’m not on the Internet (totally amazing, I know). This presents two problems:
- I need a laptop that will run Windows, Mac OS X and Linux.
- I need to work offline when we use Subversion for our revision control system at work.
Solving problem #1 turns out to be quite easy: get a MacBook (Pro), and run Mac OS X on it. Our server runs fine on Darwin (Mac OS X’s UNIX layer), and I can always run Windows and Linux with Parallels Desktop if I need to.
For serious Windows coding and testing, though, I actually need to boot into real Windows from time to time (since the program I work on, cineSync, requires decent video card support, which Parallels doesn’t virtualise very well yet). Again, no problem: use Apple’s Boot Camp to boot into Windows XP. Ah, but our server requires a UNIX environment and won’t run under Windows! Again, no problem: just install coLinux, a not very well known but truly awesome port of the Linux kernel that runs as a process on Windows at blazing speeds (with full networking support!).
Problem #2 — working offline with Subversion — is also easily solved. Download and install svk, and bingo, you have a fully distributed Subversion repository. Hack offline, commit your changes offline, and push them back to the master repository when you’re back online. Done.
Where it starts to get stupid is when I want to:
- check in changes locally to the SVK repository on my laptop when I’m on Mac OS X…
- and use those changes from the Mac partition’s SVK repository while I’m booted in Windows.
Stumped, eh? Not quite! Simply:
- purchase one copy of MacDrive 6, which lets you read Mac OS X’s HFS+ partitions from Windows XP,
- install SVK for Windows, and
- set the
%SVKROOT%environment variable in Windows to point to my home directory on the Mac partition.
Boom! I get full access to my local SVK repository from Windows, can commit back to it, and push those changes back to our main Subversion server whenever I get my lazy cafe-loving arse back online. So now, I can code up and commit changes for both Windows and the Mac while accessing a local test server when I’m totally offline. Beautiful!
But, the thing is… I’m using svk — a distributed front-end to a non-distributed revision control system — on a MacBook Pro running Windows XP — a machine intended to run Mac OS X — while Windows is merrily accessing my Mac HFS+ partition, and oh yeah, I need to run our server in Linux, which is actually coLinux running in Windows… which is, again, running on Mac. If I said this a year ago, people would have given me a crazy look. (Then again, I suppose I’m saying it today and people still give me crazy looks.) Somehow, somewhere, I think this is somewhat toward the evil end of the scale.
WWDC 2006
Right, I believe I have found a no-frills formula for how to make your body think it’s going to self-destruct in an imminent fashion:
- Attend Apple’s World Wide Developer Conference (WWDC) thing
- Attempt to socialise and meet up with as many people as possible
- Attempt to keep up with all the latest and greatest tech news and world news whilst at WWDC
- Have three to four coffees per day thanks to the surprisingly excellent (and free) espresso service at WWDC
- Combine said three or four coffees per day with beer, wine, and beer (in that order — yes, ouch, me dumb dumb) at night.
- After having coffee, coffee, coffee, beer,
wine, and beer, we then attempt to stay up at night
to:
- catch up on the deluge of urgent email (as opposed to merely the important emails, which I can deal with later),
- install beta Apple operating systems,
- attempt to actually do some coding (ha ha ha),
- catch up with the folks back home, and
- rip those 15 new CDs you bought at Amoeba records to your bling iPod (fo sheezy, yo)
- Repeat everything the next day
It has been a full-on week indeed. This is the third World Wide Developer Conference that I’ve attended, and it’s by far the best one I’ve been to so far. It was interesting seeing the Internet’s lukewarm response to Steve Jobs’s keynote on Monday morning, although the excellent Presentation Zen site gave it some credit. As the Macintosh developers who attended the conference know, there’s actually a monstrous number of changes under the hood not spoken of in Jobs’s keynote that are really cool (which would be all that “top secret” stuff in the keynote); Mac OS X is truly coming into its own, both as a user experience and a developer’s haven. Apple’s confidence is starting to shine; let’s just hope that it doesn’t turn into arrogance. (I’m praying that Windows Vista doesn’t suck too much and actually gives Mac OS X some serious competition.)
And, of course, it wasn’t just the daytime that providing intellectual nourishment: I met up and chatted to dozens of people outside the conference, from successful Mac shareware developers, to low-level Darwin guys, folks from the LLVM and gcc compiler teams, other Australian students from the AUC, passionate open-source developers, visual effects industry folks, a ton of Apple engineers, oldskool NeXTSTEP folks, and even second cousins.
While the food at WWDC wasn’t particularly stellar this year, they did have a ton of these things:

Yeah baby, bananas! $12/kg back at home? How about take-as-many-as-you-frigging-stuff-into-your-backpack over here. I’m sure it was the Australians that were responsible for the entire table of bananas vanishing in around 90 seconds. (Not to mention the free Ghirardelli chocholate :).
There was something to keep me occupied every night of the week: even before WWDC started, there were Australia and New Zealand drinks organised on Sunday night, where I met up with a huge host of other Australian students and professional developers (some of whom got really, really drunk, and weren’t representing Australiasia particularly well in the international arena, I might add). On Monday I headed out to have the best burritos ever at La Taqueria on 25th and Mission with Dominic and Zoe, headed to the Apple Store and Virgin Megastore (oh dear Lord they are such evil shops to have in such near proximity to the conference centre), and met up with the one and only Chuck Biscuits from my old demogroup along with the Darbat crew to catch up on old times. Tuesday and Wednesday night was spent heading to dinner with some fellow RapidWeaver developers that featured some bloody good steak, and Thursday was the big-ass Apple Campus Bash, where I had wine, bananas and chocolate for dinner, and then proceeded to raid the Apple Mothership Store of far too many goods. (Put it this way: I travelled to the USA with one half-full bag, and now, uhh, I have two bags that are kinda full… oops.)
During the week I ended up discovering the totally awesome Samovar Tea Lounge in the Yerba Buena gardens thanks to Isaiah, where I not only had some Monkey Picked Iron Goddess of Mercy tea (seriously, how freakin’ awesome is that name?), but also snarfed up a handful of Scharffen Berger chocolate. (Hey RSR/RSP folks back home, have you guys finished those damn chocolate blocks on my office desk yet? Of course you have!) Amit Singh of Mac OS X Internals fame was also at the Apple Store at Thursday lunchtime giving a talk about his excellent 3kg 1600-page book, which I briefly attended before deciding that an afternoon of live true American jazz with Dominic was a much more tasty option on the platter.
And, just as I thought the outings were about to calm down when the conference finished on Friday at midday, I end up meeting a like-minded video metadata fellow in the lobby of the W Hotel San Francisco of all places (swanky as hell lobby, by the way), and ended up hanging out of a cablecar on the way to Fisherman’s Wharf and Ghirardelli Square, where a bunch of NeXTSTEP folks were having dinner. I seriously don’t understand how my body’s managed to cope with all the activity so far. But hey, at least I managed to avoid San Francisco’s rather dodgy Tenderloin district (warning: highly amusing but possibly offensive image on that page) :).
So, now that the week’s over, I currently have 31 draft emails that I need to finish writing: time to get cracking (sorry friends and enemies, I’ll get to you shortly!). Of course, clever me managed to get an entire hour of sleep before heading off to SFO airport for the next stop in my trip: Los Angeles. Stay tuned, same bat time, same bat channel…
Ejecting a stuck CD
If your CD won’t eject from your Mac (for example, say, if you’re running the Leopard developer preview and the stupid mdimport process is locking files inappropriately…), the good ol’ -f (force) flag on umount will be your saviour:
sudo umount -f /Volumes/"AUDIO CD"(or whatever the volume name is)- Press the Eject key
/etc/rc.local on Mac OS X
I’ve been wanting to run a couple of trivial commands during my system startup, which would’ve been perfect if Mac OS X had an /etc/rc.local file. Of course, since Mac OS X uses the (kick-ass) launchd and the nice StartupItems infrastructure, I didn’t quite expect it to have an rc.local file — Google wasn’t much help with this either.
Of course, after I actually looked at the /etc/rc file (which launchd invokes), lo and behold, I find this near the end of the file:
if [ -f /etc/rc.local ]; then
sh /etc/rc.local
fi
So, Mac OS X does indeed have an rc.local, contrary to what I first expected. Hopefully this saves at least one other UNIX geek a couple of minutes of Googling around on the Web…
Subclassing a non-existent Objective-C class
Let’s say you’re a Mac OS X developer, and you have the following scenario:
- You have an application that’s required to start up without a particular Mac OS X class, framework or function definition, because it may not be installed yet on the user’s system, or they’re running an older version of Mac OS X that doesn’t have the relevant library installed. (Note that this requirement may only be there so that you can check for the presence of a particular framework, and throwing up a simple error message to the user when your application starts that tells the user to install the framework, rather than simply terminate with some obscure output to stderr.)
- On the other hand, your application also uses
some features of the potentially missing
class/framework/function on Mac OS X. This is
normally pretty easy to do by using
weak linking and
checking for undefined functional calls (or
using Objective-C’s
-respondsToSelectormethod), except when… - You need to subclass one of the Cocoa classes that may not be present on the user’s system.
The problem here is that if you subclass an existing class that may not be present on the user’s system, the Objective-C runtime terminates your application as it starts up, because it tries to look up the superclass of your subclass when your application launches, and then proceeds to panic when it can’t find the superclass. The poor user has no idea what has happened: all they see is your application’s icon bouncing in the dock for the short time before it quits.
Here’s some examples where I’ve needed to do this in real-life applications:
- You use Apple’s QTKit framework, and you’re subclassing one of the QTKit classes such as QTMovie or QTMovieView. QTKit is installed only if the user has QuickTime 7 or later installed, and you’d like to tell the user to install QuickTime 7 when the application starts up, rather than dying a usability-unfriendly death.
- You need to use all-mighty
+poseAsClass:in a+loadmethod to override the behaviour of existing class, but the class you’re posing as only exists on some versions of Mac OS X.
There are several potential solutions to this (skip past this paragraph if you just want a solution that works): the first one I thought of was to use a class handler callback, which gets called when the Objective-C runtime tries to lookup a class and can’t find it. The class handler callback should then be able to create a dummy superclass so that your subclass will successfully be loaded: as long as you don’t use the dummy superclass, your application should still work OK. Unfortunately this approach encountered SIGSEGVs and SIGBUSs, and I ended up giving up on it after half an hour of trying to figure out what was going on. Another method is to actually make your subclass a subclass of NSObject, and then try to detect whether the superclass exists at runtime and then swizzle your class object’s superclass pointer to the real superclass if it does. This causes major headaches though, since you can’t access your class’s instance variables easily (since the compiler thinks you’re inheriting from NSObject rather than the real superclass)… and it doesn’t work anyway, also evoking SIGSEGVs and SIGBUSs. One other possibility is to simply create a fake superclass with the same name as the real Objective-C class, and pray that the runtime choses the real superclass rather than your fake class if your application’s run on a system that does have the class.
The solution that I eventually settled on is far less fragile than all of the above suggestions, and is actually quite elegant: what you do is compile your subclass into a loadable bundle rather than the main application, detect for the presence of the superclass at runtime via NSClassFromString or objc_getClass, load up your bundle if it’s present, and finally call your class’s initialisers.
Practically, this means that you have to:
- add a new target to your project that’s a Cocoa loadable bundle,
- compile the relevant subclass’s source code files into the bundle rather than the main application,
- ensure that the bundle is copied to your application’s main bundle, and
- detect for the presence of the superclass at
runtime, and if it’s present, load your bundle, and
then initialise the classes in the bundle via the
+initializemethod.
Here’s some example code to load the bundle assuming it’s simply in the Resources/ directory of your application’s main bundle:
NSString* pathToBundle = [[NSBundle mainBundle] pathForResource:@"MyExtraClasses"
ofType:@"bundle"];
NSBundle* bundle = [NSBundle bundleWithPath:pathToBundle];
Class myClass = [bundle classNamed:@"MyClass"];
NSAssert(myClass != nil, @"Couldn't load MyClass");
[myClass initialize];
You will also have to end up specifying using the
-weak* parameters to the linker (such as
-weak_framework or -weak-l)
for your main application if you’re still using
normal methods from that class. That’s about it
though, and conceptually this technique is quite
robust.
Credit goes to Josh Ferguson for suggesting this method, by the way, not me. I’m merely evangelising it…
MacBook Pro First Impressions
It’s been about a week since I got my shiny new MacBook Pro. Since then, I’ve used it for both work and play, so I think it’s about time I put more crap on the Internet and blogged about my very important personal feelings on this issue.
First, this thing screams. It’s fast as hell. Mac OS X zips along even more smoothly than the Dual 2.3GHz Power Mac G5 I have at work, and the interface generally feels snappier than a G5, which is already reasonably teh snappy. To my amazement, some stuff on the MacBook Pro is way faster than on the G5. As an example, here’s how long it took to compile a debug version of cineSync, our little project at work:
- Dual 2.3GHz Power Mac G5: 5m10s
- MacBook Pro: 1m40s
That’s a 3x speed improvement — versus a
2.3GHz G5, which is a pretty blazing fast
machine already. (I didn’t believe the performance
difference that I ran the test three times!) I really
don’t understand the performance discrepancy here:
the G5 is at least the equal of the fastest x86 chips
in raw processing power, so where’s this 3x
difference coming from? Even fork(2)/exec(2)
speed in Darwin is an order of magnitude quicker on
the MacBook Pro than on the G5, so running those one terabyte
./configure scripts finally doesn’t look
so paltry compared to Linux. My only thought is that
x86 code generator for gcc is an order of magnitude
better than the code generator for the PPC. I guess this is a feasible
possibility, but it does seem somewhat unlikely. Can
a compiler that generates better code really be
responsible for that much of a speed
difference? Maybe indeed (quiet you Gentoo fanboys
down the back)… thoughts on this issue would be
welcome!
Rosetta, the JIT PPC-to-x86 code translator, also works amazingly well. While the technology in Rosetta is already an extremely remarkable achievement, its greatest achievement is that you don’t have to worry about it: I downloaded some Mac OS X binaries of Subversion a while ago, and only realised later that they were PPC binaries. So Rosetta works completely transparently, even for UNIX command-line programs. I suspect that part of the reason Apple haven’t open-sourced the Intel xnu kernel for Mac OS X/Darwin is because Rosetta may be tightly integrated with the kernel, and it’s technology that they don’t want to (or perhaps cannot legally) give away.
The whole Windows-on-Mac thing also works rather well. Windows XP running via Boot Camp is, well, the same as Windows XP running on a vanilla PC, except that it’s running on a very pretty silver box (with very pretty ambient keyboard lighting). It does have some slightly annoying issues (such as Fn-Delete on the internal keyboard not functioning as a proper Del key), but those issues will be solved with time. (Unfortunately, Counter-Strike isn’t all that playable with a trackpad :).
Parallels Workstation is equally impressive: hardware-assisted virtualisation really does fly. It’s remarkable to see Windows XP running in a window inside Mac OS X, and have it run at more-or-less native CPU speed. Setting breakpoints in Visual C++ Express also works fine, so Parallels appears to be virtualising hardware breakpoints correctly too. There’s still a lot of work to be done in virtualising drivers, however: it would be mighty cool to see a virtualised PC game running at nearly native speeds, since that requires virtualised accelerated video and sound support.
The upshot of the successful Windows-on-Mac stories are that I’ll never be buying a generic PC yum-cha box ever again. On the road, I finally have a machine that can actually run Mac OS X, Windows and Linux all side-by-side, both virtualised and “for real”. For my family, that means that I can actually buy them an iMac even though they need to run Windows. (The iMac really is a beautiful machine: there’s no single-box-with-built-in-display solution like an iMac at all in the PC world. Yeah, I’m sure there’s some cheapass Taiwanese knockoff of an iMac, but that certainly doesn’t count.)
One nice touch to end of this story is that my local AppleCentre offered me no less than A$1000 to trade-in my faithful old 1GHz Titanium Powerbook, which I intend to follow-up on. (I’d have done it already if I didn’t have to head out-of-town so soon.) If you’re thinking about upgrading an old Mac to a new ICBM model, see whether your AppleCentre will accept trade-ins. I was very pleasantly surprised that I could get a four-digit figure from a trade-in of a three-and-a-bit year old laptop.
So, overall first impressions of a MacBook Pro? I’m a pretty happy boy indeed. The only regret I have is that I already used the name shodan for another computer that’s much less deserving of the name. Seriously, I called a Dell box shodan? What the hell crack was I on?
MacBook Pro Fun
I suspect that if you don’t know that Apple released their Boot Camp tool to enable normal PC operating systems to be installed on their shiny new ICBMs, you’re probably not a geek, and this article doesn’t really concern you…
Since there have been plenty of other articles written about Boot Camp and its implications for the future of the Macintosh, I won’t say any more about it here. I just wanted to say the following:
- Tuesday, April 4: Pick up shiny new MacBook Pro from my local AppleCentre.
- Wednesday, April 5, ~8pm Australian CST: Apple announces Boot Camp.
- Thursday, April 5, ~2am Australian CST: Windows XP SP2 installs on my Mac.
- Thursday, April 5, ~3am Australian CST: Visual C++ Express 2005 and Counter-Strike are installed (the latter running at a rather nice 72.7fps in Valve’s Video Stress Test).
- Thursday, April 5, sometime later: Parallels announces a beta of their Workstation product, enabling Macs to virtualise running guest operating systems. Hooray for x86 hardware virtualisation technology.
Not bad for the first three days of owning a MacBook Pro, really. Bring on the tech!
iTunes Video Quality vs DivX
I finally found some free time this week to watch the modern Battlestar Galactica TV series, which I bought from the iTunes Music (neÈ video) Store. (As an aside, Battlestar Galactica is absolutely awexome — but that’s a whole ‘nother story).
I actually have DivX versions of the episodes that can be obtained from the usual places where people obtain DivX versions of TV episodes. I decided to buy the episodes from iTunes anyway, to see how they’d compare in quality to the DivX ones. I’m not particularly surprised to say that the quality of the iTunes videos are slightly worse than the DivX versions floating around: there are some people who are pretty damn crazy and spend weeks tweaking their DivX video encoding parameters to make them look really good. Thanks to the rabid fanbase on P2P distribution networks that demand very high video quality, you also generally find that most videos on P2P networks have been lovingly hand-tweaked and encoded quite well.
(Note: I’m using the term DivX to mean the whole plethora of MPEG-4 video codecs, such as the “real” DivX, xvid, 3ivx, etc. You can start endless debates about which codec is better than the rest for encoding particular types of motion video, and that’s not my goal here.)
However, even though the iTunes video versions aren’t quite as good quality as the DivX versions that you find floating around on the ‘net, it’s not quite that simple:
- First, I was playing the videos on a 1GHz Powerbook G4, which may not quite be powerful enough to do decent post-processing on the H.264-encoded video. iTunes uses QuickTime for its video playback, and QuickTime is a pretty adaptable beast: if your CPU isn’t powerful enough to perform decent post-processing, it simply will make the frames look worse rather than dropping frames, even resorting to simple linear sampling to perform scaling if absolutely necessary. It’s entirely possible that the videos would look much better on a high-end computer such as a modern Athlon system or a Power Mac G5.
- The iTunes videos were encoded at 320×240, which is much lower than typically encoded DivXs (the Galactica DivXs that I had were encoded at 640×352). This also means that the iTunes videos weren’t widescreen, for those of you lucky punks who have 16:9 screens.
- I was playing the videos on a TV, which has a lower resolution than on a computer monitor. The raw resolution of the videos don’t make such a big difference because of this, which partially negates the last point. I should point out that the TV I was watching it on was pretty big (42”), so it’s still very easy to see encoding artefacts.
- The iTunes videos were much more colour-accurate than the DivX versions: all the DivX encodes I’ve seen were far less saturated. (I’m sure that it’s possible to get DivX versions that are more colour-correct; I’m just going on the DivX videos that I have.) A/B’ing the iTunes video and the DivX on the TV, I’d actually say that the richer colour on the iTunes version more than compensated for the DivX’s increased resolution, and made the ‘feel’ of the video better overall. Except…
- There were some very visible blockiness during the space combat sequences of Battlestar Galactica: outer space is quite black, and the H.264 encoder that Apple uses on its videos decided to serious
