Easily speed up your Xcode builds

A lot of developers don’t heavily modify the projects they instantiate from Xcode’s templates. This is a shame, because not only is it a great way to learn Xcode in depth, it’s also a great way to ensure your projects build as fast as possible!

To that end, then, here are two simple tips that you can apply to your projects right now that should get them building faster.

Normalize your build settings!

Projects and targets in Xcode have configurations — collections of build settings that influence how a target is built. The Debug configuration, for example, will typically specify the compiler optimization build setting with as low a value as possible. The Release configuration, on the other hand, will typically specify a relatively high value for this build setting. This begs the question: The Debug and Release configuration of what?

When you create a new project from one of Xcode’s templates, the principal target in that project will typically have a number of build settings customized in its configurations. The project itself, on the other hand, won’t have very may customized build settings. For the one-target-per-project case this doesn’t matter much. However, if you create a project with multiple targets, you can wind up with a number of targets that specify the same (or even subtly different!) information.

Instead of leaving your project this way, you can normalize your build settings such that build settings you want to specify for every target in the project — for example, that compiler optimization should be off for the Debug configuration — are specified at the project level rather than at the target level. This takes advantage of the fact that build settings are inherited in Xcode; if a build setting isn’t customized in a target, the value specified in the project is used.

What does this buy you? It ensures that you have a single, consistent set of settings that are passed to the compilers, linkers, and other tools that are used to build your software. That way you won’t wind up with subtle bugs like code built with C++ RTTI turned on calling a plug-in built with C++ RTTI turned off. But just as importantly, it’s enables the next trick, which can have a significant impact on the speed of large, multi-target builds.

Share your precompiled prefix!

Xcode, like many other IDEs, supports prefix files — header files that are included implicitly by every one of your source files when they’re built. Normally, as I described above, these are specified in target configurations. The text in the prefix file that is copied out of Xcode’s templates even mentions that it’s for a specific target.

Don’t be fooled!

Prefix files get precompiled for performance, so they can simply be loaded by the compiler rather than recomputed for every file you build. Precompiling a prefix file takes quite a bit of time though, especially if you use multiple languages in your project (such as C, Objective-C, and C++) because each language needs a separate precompiled prefix due to differences in how they’ll treat “the same” code.

However, just because precompiled prefix files can’t be shared between languages doesn’t mean they can’t be shared between targets. In fact, for performance, Xcode automates this sharing for you — if you meet it halfway. The critical thing that you need to do is to ensure that your prefix files are:

  1. Named the same; and,
  2. Built using the same compiler-related build settings.

That’s where the normalization I talked about above comes in. You can even promote your prefix file-related build settings to your project instead of your targets, so you can be certain that they’re shared.

In fact, if they meet the criteria that Xcode uses to determine whether precompiled prefix files should be shared, even multiple projects will wind up sharing them!

The pause between builds of a target’s dependent targets to generate a new precompiled prefix file is like a pipeline stall: An unwelcome hiccup that holds everything else up until it’s over. If Xcode can precompile a single set of prefix files at the start of your build and then re-use them for the entire rest of your build, it will stream past as quickly as it possibly can with only the occasional pause for linking. For large projects with a lot of dependent targets, this can make a big difference.

Separate your preprocessor macros!

“But Chris,” you say, “I have target-specific preprocessor macros that I can’t get rid of!” That’s OK. As long as you don’t need them in your prefix files, you can set them in the special Preprocessor Macros Not Used in Precompiled Headers build setting. These will be passed to the compiler when your sources are compiled, just like the regular Preprocess Macros will, but they won’t be passed when precompiling a prefix file. So you can have your cake and eat it, too.

Of course, there are macros that you do want to set in your precompiled prefix headers, because they change the behavior. Macros like NDEBUG to turn off C assert or NS_BLOCK_ASSERTIONS to turn off Foundation’s NSAssert are important to specify for your precompiled prefix files. Fortunately these types of macros typically differ only by configuration, and also remain consistent across targets and projects, allowing you to specify them at the project level rather than the target level.

Just these three small changes have the potential to make a dramatic difference in how quickly Xcode builds your project:

  1. Normalizing your build settings, so common settings across all your targets are specified at the project level;
  2. Increasing sharing of your precompiled prefix files by naming them consistently and using consistent compiler-related build settings; and
  3. Specifying separate preprocessor macros for your prefix files than for your targets,

Try it out and see for yourself!

Steve Yegge describes what’s wrong with Lisp

Steve Yegge, Lisp is Not an Acceptable Lisp:

You’ve all read about the Road to Lisp. I was on it for a little over a year. It’s a great road, very enlightening, blah blah blah, but what they fail to mention is that Lisp isn’t the at the end of it. Lisp is just the last semi-civilized outpost you hit before it turns into a dirt road, one that leads into the godawful swamp most of us spend our programming careers slugging around in. I guarantee you there isn’t one single Lisp programmer out there who uses exclusively Lisp. Instead we spend our time hacking around its inadequacies, often in other languages.

Steve does a very good job of articulating a lot of the things I dislike about Lisp, especially Common Lisp. One interesting thing, though, is that a lot (but not all) of the issues he raises are addressed by Dylan.

One of the more interesting things about Dylan in this context is that, despite not adopting a traditional message-based object system like Smalltalk or Objective-C (or their more static cousins C++ and Java), Dylan does push objects all the way down, but in a functional style. It appears to work pretty well, making it easy to define both nouns and verbs in the combinations a developer might need, and even (through its hygienic macro system) allow developers to extend language syntax too.

“Enterprise” thought leadership?

David Heinemeier Hansson, creator of Rails at 37signals, takes James McGovern — some Java/J2EE author — to task for his über-lame rant against Ruby in the Enterprise in a great post titled Boy, is James McGovern enterprise or what!

> So by Enterprise, Architect, and Enterprise Architect standards, this gent must be the top of the pop. Thus, allow me to make this perfectly clear: I would be as happy as a clam never to write a single line of software that guys like James McGovern found worthy of The Enterprise.

> If Ruby, Rails, and the rest of the dynamic gang we’re lumped together to represent, is not now, nor ever, McGovern Enterprise Readyâ„¢, I say hallelujah! Heck, I’ll repeat that in slow motion just to underscore my excitement: HAL-LE-LU-JAH!

> With that out of the way, we’re faced with a more serious problem. How do we fork the word enterprise? The capitalized version has obviously been hijacked by McGovern and his like-minded to mean something that is synonymous with hurt and pain and torment.

Indeed, McGovern’s rant reads more like a parody of a rant than the real thing:

> 13\. Lets say there is a sixteen week project and the productivity stuff was true and Ruby could save me an entire three weeks which would be significant. Since Ruby is a new vendor and not represented by existing vendors I already do business with, do you think that I will spend more than three weeks in just negotiating the contract?

Yes, because there is some vendor out there named “Ruby that you need to sign a contract with before you can begin a project.

Despite his claims to be agile, McGovern obviously doesn’t know the first thing about agile development. People come first, sure, but agile development doesn’t say that tools aren’t important. Not using good tools makes it harder for good people to do good work.

That’s why I love developing software for Mac OS X and why I love helping people develop software on Mac OS X: We have great tools like Cocoa, Core Data, Interface Builder, OCUnit, WebObjects, and Xcode, and these can be used by great developers to do great things.

Making Better Games with Test-Driven Development

Noel Llopis (Games from Within) and Sean Houghton, Backwards Is Forward: Making Better Games with Test-Driven Development:

> One of the questions we had when we jumped into TDD is
> whether it was going to hold for high-level code. We had
> seen in practice from previous projects that we can
> certainly do TDD to create low-level and intermediate-level
> libraries (math, collision, messaging, etc). But would it
> really work for high-level code that would build on
> low-level code?
>
> The answer is an unconditional yes. We have developed a
> full codebase doing TDD from the start, and we had no
> difficulty writing high-level code with TDD. Things like
> character state machines, game flow, or specific game
> entities were done through TDD without any problems, and
> greatly benefited from the TDD approach.

Noel’s blog is great, and this paper is being presented at the 2006 Game Developers Conference.

Noel and High Moon Studios have been a lot of pioneering work using Extreme Programming in the game development space. Game development can definitely make good use of Extreme Programming to manage the development process, dramatically improve the quality of code, and do wonders for scheduling accuracy and schedule predictability.

Extreme Programming in game development also presents special challenges due to the exploratory nature of a lot of the work, as well as the highly-interactive nature of the software itself. As Noel points out, you wind up writing much more finely-factored code when doing TDD, which will be alien to a lot of game developers but will help greatly with maintenance, debugging, and the ever-more-important portability. (Not just between Windows and Mac OS X, but also between Xbox and PlayStation 2 and Nintendo GameCube and Xbox 360 and PlayStation 3 and Nintendo Revolution…)

Cooperative User Threads vs. Preemptive Kernel Threads

James Robertson, Cooperative Threading:

> Well, in Cincom Smalltalk, this model gives you predictability –
> you know exactly what a thread is going to do. The issue with runaway
> threads rarely comes up for a simple reason – most processes end up
> pausing for I/O (user input, db access, file access, sockets –
> what have you). That wait for I/O state is what prevents a problem
> from arising.

This is a classic problem and I’m honestly surprised to find out that Cincom Smalltalk implements cooperative user-level threads rather than supporting preemptive kernel threads.

Here’s what I posted in response to James, unattributed thanks to the torturous comment interface on his blog:

> One issue with cooperative threads relative to preemptive
> OS-supplied threads is that you get far less opportunity
> for true concurrency within an application. In an era when
> multi-core processors are becoming significantly more common,
> this is becoming exceptionally important to application
> developers. It’s not just about doing I/O concurrently with
> other operations or allowing an application to perform
> multiple tasks at once; it’s about allowing a task to be
> completed faster because more efficient use is being made
> of machine resources. This is why I take an extremely
> skeptical view of user-level threading packages, especially
> in software built on platforms that have reasonable
> kernel-level threading.

You’ll note that the various threading APIs in Mac OS X are all built on kernel threads.

Furthermore, the Mach microkernel schedules exclusively in terms of threads. The microkernel doesn’t even have a conception of processes! It only knows about collections of resources — *tasks* — such as address spaces and IPC ports, and flows of control — *threads* — that it can schedule on processors.

Xcode: Unit Testing

Xcode 2.1 introduced integrated unit testing to the Xcode IDE. Xcode includes two unit testing frameworks, target templates for setting up test bundle targets, and infrastructure for running unit tests every time you build your project and reporting their results in the Build Results window just like compilers and linkers do.

With Xcode unit testing, you group your test cases into test bundles which are built by separate targets. This means that you don’t need to build two versions of your software — one with tests and one without tests — and can run your tests against the actual software you want to deliver.

Xcode 2.1 and later include OCUnit for unit testing of Objective-C Cocoa software, and it includes a new framework called CPlusTest for unit testing of C++ software. Using either you should be able to test C code with relative ease. Corresponding target templates are included for creating unit test bundles appropriate for Cocoa and Carbon applications and frameworks, and file templates are included for creating OCUnit and CPlusTest test case classes.

The test bundle target templates have a shell script build phase at the very end that invokes /Developer/Tools/RunUnitTests. RunUnitTests looks at the build settings it’s passed via its environment and determines from that information how to run the tests in your test bundle.

If you’re testing a framework, RunUnitTests will run the appropriate test rig and tell it to load and run the tests in your bundle. Since your test bundle should link against your framework, your framework will be loaded when the test rig loads your bundle.

If you’re testing an application, you need to specify the application as the Test Host and Bundle Loader for your test bundle in its configuration’s build settings. The Bundle Loader setting tells the linker to link your bundle against the application that’s loading it as if the application were a framework, allowing you to refer to classes and other symbols within the application from your bundle without actually including them in the bundle. The Test Host setting tells RunUnitTests to launch the specified application and inject your test bundle into it in order to run its tests.

There’s even support in RunUnitTests for invoking a test rig of your own, rather than the test rig for one of the supplied frameworks. You just need to specify the Test Rig build setting for your test bundle; this should be the path to a tool to run. It will be passed the path to your test bundle as its first argument, and if it needs to generate failure information it can just generate it in a gcc/compiler-like format on stderr:

FailingTest.c: 10: error: (1 == 0) failed

This will cause it to show up in the Build Results window as an error, just like a compiler or linker error. You can see the RunUnitTests manpage for more information on the environment in which your test rig will be run.

There’s a great Unit Testing Guide on the Apple Developer Connection web site that has lots of information on getting started with Xcode unit testing. Check it out!