Developer Guide: Build Farms and your iOS Apps


Up front warning: this is a very geek-oriented guide, and is specifically meant for iOS app developers with more than one Mac, if you don’t fall within those requirements you’re probably not gonna get much out of this write-up.  Sorry, if that’s the case, best to just pass this one over for your reading list.

So, you’re working on this massive iOS app, and it takes forever to compile on your main work machine.  Maybe you’re like me and your main work machine is a lowly Intel Core 2 Duo 2.4gHz Mac Mini, or, maybe you’re not even that fortunate.  Maybe your main work machine’s a MacBook Air, those aren’t fast either, but that’s actually kind of the point.  But, if you’re like me, you’ve got more than one Mac.  Imagine how cool it would be to be able to use all of your Macs to distribute (and incredibly increase the performance) of compiling your apps for iOS?

If you’re already familiar with Xcode’s “Distributed Builds” feature in Xcode 4.2, you may or may not know, those settings aren’t actually going to work for your non-Mac app build processes.  However, not to fear either way, this snazzy little guide will quickly walk you through setting up Distributed Builds to work with both Mac and iOS app build operations via Xcode’s interface.


This How-To guide involves Terminal commands.  It is assumed you know how to read the commands I’m giving you to some degree, and that you’re willing to accept the risks of performing these steps, always be sure to make a backup and test that the backup works if you have any concerns about following this guide!


This stuff is only tested with Xcode 4.2.1 (Build 4D502) on Mac OS X Lion 10.7.3 (Build 11D50), and just for sake of completeness, my machine was booted (as forcefully as required) into the 64-bit Mach kernel.  You can probably get away with any Xcode 4.2 and any Mac OS X Lion 10.7 versions, but, I can only attest to this working in my particular setup.

When you see code in monospace that should be your indication that it’s either text in a text file you should enter, a reference to a filename you should be working with, or a command you will need to run.  Additionally, commands you need to run will be prefixed with my shell prompt, which is:

[[email protected] ~]$

Let’s get started.  Don’t worry, this won’t take too long, and it’s worth your 5 or 10 minutes (especially if you’re building an app with a large number of code files)…


NOTE: Steps 1 through 7 are only absolutely required to be done on your main development machine, that is, they’re only needed on machines that start the compile via Xcode, other machines that receive the compile tasks from Xcode and don’t run Xcode directly to start the compiles don’t need those steps done, and as an added bonus you don’t need Xcode open for the other build farm members to receive and process your build tasks.  (You can do the other steps on multiple machines safely if you work or have others do Xcode work on other machines as well!)

1. Figure out how many CPU cores you have available between all the machines you want to use for building with Xcode over the network, then take that number, and add 1 to it for every computer you’ll be sending build tasks to over the network.  In my case, I have two machines I’m using for Distributed Builds, each of which has two CPU cores, so, I come up with 6 total (4 cores plus 2 machines).  Now, we need to set a system-wide default setting, to set the maximum number of build processes Xcode will run at a time.  For my 6-task limit, in my Terminal, I run the following:

[[email protected] ~]$ defaults write IDEBuildOperationMaxNumberOfConcurrentCompileTasks 6

2. We need to wrap Xcode’s standard Distributed Build utility in a script file that takes care of the little bit that Apple forgot to get Distributed Builds working for iOS apps.  Run the following command in Terminal to move the distcc program from Xcode into a place where we can refer to it in the script we’ll create in the next step:

[[email protected] ~]$ mv /Developer/usr/bin/distcc /Developer/usr/bin/distcc.orig

3. Now, you need to make sure you know the hostnames and/or IP addresses, for each of your machines that you’ll use for these Distributed Builds.  In my case, I get to use hostnames, since I’ve got both static IP’s for each machine, plus, I’ve also got proper (internal-only) forward and reverse DNS for each machine.  I’m only going to compile using two machines, including my Mac Mini (Rashtaka), and my MacBook Pro (Bashrata).  We want to create our distcc wrapper script in the file where we moved the actual distcc utility away from, so, run the following to open up a new file in the nano text editor in the Terminal:

[[email protected] ~]$ nano -w /Developer/usr/bin/distcc

4. Now you’ll have a text editor open.  For my case, I used the following script file, paste it into the terminal, and in the next step, I’ll tell you in-brief what you need to edit:

export DISTCC_HOSTS="--randomize localhost bashrata,cpp,lzo"
/Developer/usr/bin/distcc.orig "[email protected]"
exit $?

5. This is a lot simpler than it looks.  The only line you have to edit to change/add more hosts is the line beginning in “export” which sets the list of hosts distcc will attempt to use to compile your projects.  The “localhost” entry indicates that you want to (most definitely) compile using the local machine as part of the Distributed Builds.  The “bashrata,cpp,lzo” portion tells Distributed Builds to use my MacBook Pro as my one network-based compiling machine.  Note that you must put “,cpp,lzo” after each hostname or IP/address to get these entries to work properly as of the time of this writing.

Just to give you an example of adding another host, let’s pretend the day has come when I decide it’s time to get a new Mac, and I want to continue to use Rashtaka (who was localhost in that previous example) as a network-based compiler.  To accomplish that, very simply, we’d change the script to look like so:

export DISTCC_HOSTS="--randomize localhost rashtaka,cpp,lzo bashrata,cpp,lzo"
/Developer/usr/bin/distcc.orig "[email protected]"
exit $?

6. When you’re happy with your host list you’ll need to save the host list by pressing Control+O, Return, and then Control+X.

7. We need to make sure that Xcode can run the script like it’s a program.  Run the following command to make it executable:

chmod +x /Developer/usr/bin/distcc

8. Now, fire up Xcode, open up Preferences from the Xcode menu at the top, then click on Distributed Builds, then click the padlock to unlock it.  Enter your password for your account (if you have one–you shouldit’s the right thing to do!)

9. Almost done–now, check all three checkboxes, and that includes the checkbox next to “Bonjour!”  Quit Xcode, restart Xcode, and this machine should be good to go for distributed iOS app builds over the network.

10. Finally–Run steps 8 and 9 on each machine you’ll be using for Distributed Builds.  Once all that repetition is done, you’re all set, try building your big project (clean it first in Xcode if you want to see the full effect) and be amazed by how much quicker the job gets done!

Enjoy your vastly speedier code compiles!

Happy developing!


UPDATE #1: Forgot to reference the original article.

UPDATE #2: Forgot to tell you guys to make the new wrapper script executable and made one minor grammatical correction.

UPDATE #3: Forgot to point out that the Xcode Preferences steps must be done on each machine in the build farm, also, make sure it’s known that the only machines that need the “special treatment” for distcc are the ones you run Xcode on.

UPDATE #4: Hopefully my final update, since I obviously need to learn to fully proofread, this update adds clarity to the note regarding the steps that only need the “special treatment” from steps 1 to 7.

Leave a Reply

You must be logged in to post a comment.