The Last Word on Many From One

It turns out that building multiple targets from one source code base is both easy and hard, both simple and complex. It all depends not only on the ultimate products you want to create, but a bit on your workflow and how you like to setup and run your project.

In my last post on this topic I mentioned that the rubber was meeting the road on a project where we had multiple targets defined using a single source base. That post did not end definitively; I still had questions about how to solve my problem having had time to actually try and make it happen. The ensuing comments and discussion were really great and helped me better understand the build process, and more about the distribution process that has been really valuable.

First, here are some truths I have come to recognize:

1. You can re-sign a build. I really didn’t appreciate this, until I read it a few times and someone mentioned it on this blog in a comment. And it turns out, that if your project’s configuration is simple enough, not only does this make perfect sense to be able to do, it makes even more sense from a Best Practices point of view. What this really means is that you can create a “Release” build once, say for QA testing. When you distribute it for testing, as an Ad Hoc build, you would sign it with your Ad Hoc profile. If it clears QA without any issues, you can submit that very same build to Apple simply by re-signing it with your Distribution profile when you submit it. I did this just today for a project. It actually works flawlessly. And this is a Best Practice because you move a build that QA has verified directly to submission without risking any new issues by re-building simply to sign that build with the “right” profile.

2. Using xcodebuild from the command is good for two things (generally):

  • building one or more targets from a single scheme and then performing an action on them, such as Archive, or
  • building one or more targets using a specific configuration (e.g. Release)

Now, these might seem to accomplish the same thing, and with a simple configuration, they probably do. But here’s where my particular project left the beaten path of project development. Neither of these two scenarios worked for me to build all my targets for Release, because my project’s configuration is not simple in one very important respect: Preprocessor Macros

Most folks likely have a Debug and a Release build. They are, for the most part, identical. But in the case of this project, my Release build (which I always like to rename Distribution) has a different set of preprocessor macros. So, you can see that if I built my Ad Hoc build (which is just a Release build that uses an Ad Hoc profile to Archive builds) for testing, and then just re-signed it with my Distribution profile, I would be submitting to Apple a build that had extra functionality (“staging backends” here) that is not intended for production! (We enable our testing builds to change backend servers, but this is not something we expose in production.)

So what did I do? Ultimately, I did have to create what I call a “Distro” scheme for each target (alongside their default scheme) that used the Distribution configuration for the Archive action, rather than the Ad Hoc configuration. Then I was able to write a script that used xcodebuild with the -scheme option and the “archive” action.

Here’s the short Ruby script I used to finally build all my targets for Release using my Distribution profile and preprocessor macros:


lines = %x[xcodebuild -list].split("\n")

found_schemes = false
while (!lines.empty?) do
  line = lines.shift

  unless found_schemes
    found_schemes = true if (line =~ /Schemes:/)

  next unless line =~ /Distro:/

  puts "\n\n##### #{line} ####\n"

  `xcodebuild -scheme "#{line}" -sdk iphoneos5.0 archive`

In the end, I spent more time crafting this script than I did actually creating 6 Distro schemes; that part was actually made pretty easy through the Manage Scheme’s UI of Xcode.

It took a long time to get here, but what a learning process. And it shows just how versatile Xcode really is for what is certainly a complex part of the Mac and iOS software development process.

Posted in: iDevBlogADay, Software Development

Leave a Reply

Your email address will not be published. Required fields are marked *

Prove you are human: *

Read previous post:
Many From One, Again

Several months ago I wrote about some tricks I was using to build many targets from one code base. The...