Carbon vs. Cocoa

Yesterday I posted a link to Todd Bishop’s More on Mac BU. Among the comments to Todd’s article is a question I’ve seen and heard before: When is Microsoft going to port Office to Cocoa? The question, the frequency with which it gets asked in various venues and the common tone that suggests Carbon is a second-class citizen to Cocoa’s aristocratic blood-lines, all suggest that there’s still a great deal of misunderstanding out there regarding these two technologies.

Application Environments

That Carbon plays second fiddle to Cocoa’s first chair in the orchestra is a serious misconception. To understand why, we first need to discuss what constitutes an application environment. Apple’s System Overview offers a summary view of the application environments available on Mac OS X. They further provide a definition of application environment as “the frameworks, libraries, and services (along with associated API) necessary for the runtime execution of programs developed with that API. The application environments have dependencies on all underlying layers of system software.” The full discussion can be found here.

While the two environments involve different system frameworks, the primary difference between the two is the extent to which the application programmer is responsible for mundane, house-keeping tasks. Under Carbon, for example, the application programmer is responsible for implementing various carbon event handlers that respond to user actions like mouse clicks, key presses and menu selections. Under Cocoa, much of these low-level house-keeping tasks are handled by the Objective-C framework, freeing the application programmer to concentrate on overall application logic.

The downside of Cocoa is that it’s extensively tied to the Objective-C language. Carbon, on the other hand, is largely language independent. If a programmer is implementing a new application from scratch, Cocoa makes sense. If, on the other hand, the programmer is porting thousands, or, in the case of Office, millions of lines of C and C++ code, then Carbon is the obvious choice. There’s little benefit to be gained from rewriting those millions of lines of code to work within Objective-C, particularly the C++ code.

In this regard, it’s worth noting that Apple chose to implement the OS X Finder as a Carbon application. Project Builder, and XCode for Panther, on the other hand, are Cocoa applications. It made sense to write them in Cocoa because there wasn’t an existing code base already tied to older APIs.

Despite the nature of the APIs and/or object-oriented support in the two environments, the choice between Carbon and Cocoa is really a matter of the programmer’s preference. Those preferences are not necessarily limited by an existing code base. Familiarity with a given set of APIs and/or relevant programming languages (e.g. RealBASIC) also play a role in any given developer’s choice to write for Carbon or Cocoa. What doesn’t play a factor in the decision, however, is the quality of the user experience.

Executable Formats

Carbon isn’t the only technology Apple has implemented in OS X in order to facilitate the porting of legacy applications from Mac Classic. The other technology is the Code Fragment Manager (CFM). CFM is the Mac Classic method of using shared libraries, and is based on the Preferred Executable Format (PEF). However, the native technology for linking separate executables at runtime is the dynamic link editor (dyld), and that’s based on the Mach.o (pronounced “Mach-Oh”) executable format.

Apple has a fairly complete description of both technologies which can be found here. I’ll only point out two things:

1) The Carbon application environment is not tied to CFM. In fact, Carbon is implemented as a set of Mach.o binaries that use dyld to resolve symbol addresses. CFM applications resolve references to the Carbon APIs through a set of thunking libraries that implement CFM on top of dyld.

2) Despite its name the Preferred Executable Format is not the “preferred” executable format on OS X. Among other things PEF employs something called a TVector to implement function pointers and what are known as cross-TOC calls while Mach.o doesn’t. You don’t need to know the details of either of those. All you really need to know is that the same code in the PEF format will be slower than if it had been complied to the Mach.o format. For this reason, Apple strongly recommends that applications be compiled to use dyld and Mach.o.

Mac Office and PEF vs. Mach.o

For a number of reasons, Mac Office is still a PEF executable. The primary reason is that we didn’t have time to both port Office from Classic to Carbon and deal with all the issues, many of them unknown until such time as you actually undertake the change, involved in also converting from PEF to Mach.o.

The second reason is that, until recently, converting from PEF to Mach.o would have also necessitated a change in our build environment. Metrowerks’ support for Mach.o is relatively recent, and, for Office 2004, we decided that converting to Mach.o was simply too great of a risk. As I mentioned, you really don’t know what problems you’re going to run into while making such a conversion until you try it. The work is certainly more involved than just flipping a compiler switch and rebuilding the code.

In any event, the legitimate question is, when will Mac Office be converted to the Mach.o executable format? Unfortunately, I really don’t know. It’s on the horizon, and we’ve conducted some preliminary investigation (enough to get a reasonable handle on how much work is involved). However, at the moment, we’re really focused on shipping Office 2004. For now, the effort is on the back burner, and the decision to move it to the front burner rests in the hands of people who have job titles that end with either “Development Lead” or “Development Manager”. My job title ends with neither.

Rick

Further reading: