---
title: 'Xcode Build Settings Part 1: Preprocessing'
teaser: How to debug some Xcode errors related to preprocessing.
tags: ios
author: Gordon Fontenot
published_on: 2012-11-03
---

That screen. You know the one. The table of text. The one with scary sounding
terms such as `Mach-O Type` and `Rez Search Paths`. The one you're probably
avoiding right now, for fear that changing one of the magic incantations will
leave you with an empty husk of an app powered only by sadness and regret.
There's actually a whole ton of useful stuff which you probably didn't know
about. In this multi-part article, we'll go over some of the fun possibilities
once you understand the available settings.

## Disclaimer

Sounds overblown, right? but -- **no, seriously, read this!**

I know I said this wasn't that scary. And I stick by that. _But_ there's one
thing to be aware of. You can't actually undo any changes you make (and might
later regret). So please please please make sure you are working in a clean repo
before playing around with settings you aren't familiar with so that you can
easily reset in case something blows up on you.

With that out of the way, let's go poke it with a stick, shall we?

## Compiler flags

The first thing we're going to play around with is one of the least likely to
blow up in your face. Compiler flags are used to define constants at build time,
that can then be used in your code to do some tricky things to customize your
code for specific build configurations.

There are 3 possible places to set these up:

- `OTHER_CFLAGS` (Other C Flags)
- `GCC_PREPROCESSOR_DEFINITIONS` (Preprocessor Macros)
- `INFOPLIST_PREPROCESSOR_DEFINITIONS` (Info.plist Preprocessor Definitions)

The difference between the Other C Flags setting and the two Preprocessor
settings is that anything you pass into Other C Flags is passed directly to the
compiler as is. This means that if you want to set up a constant named `FOO`,
you would have to format the C Flag as `-DFOO`. This gets passed as is to the
compiler, and defines the `FOO` constant. However, this also means that a
malformed C Flag could potentially blow up your build.

Conversely, anything passed in through one of the Preprocessor settings is
passed to the compiler with `-D` automatically. So that same constant from
before can simply be set up as `FOO`. This means that even if you write a
malformed flag, you will only get a malformed definition in return. Because of
this, I recommend sticking to the Preprocessor macros settings for defining
compiler flags, leaving the Other C Flags setting for times when you actually
want to pass flags directly to the compiler.

Compiler flags can be set either as a value definition (`FOO=1`), or a constant
definition (`FOO`). Constant definitions are essentially boolean. They are
either set, or not set. Value definitions _can_ have value, but you really don't
want the compiler going through complex conditionals to generate your code. If
you want to use a value definition, stick to setting the flag to 1 and simply
checking for its existence.

So how do you use this? The most common use is dynamically swapping out sections
of code based on the build configurations. Once you have your flags set up, you
can do some slick dynamic compiling in your code. As an example, you could swap
out an <abbr title="Application Programming Interface">API</abbr> endpoint based
on the build configuration like so:

```objectivec
#if RELEASE
static NSString *const MY_API_URI = @"https://api.example.com/";
#else
static NSString *const MY_API_URI = @"https://api.staging-example.com/";
#endif
```

Remember Info.plist Preprocessor Definitions? These can be used in conjunction
with the `INFOPLIST_PREPROCESS` (Preprocess Info.plist File) flag to do the same
kind of dynamic compilation for your Info.plist file. The simplest use of this
technique is to swap out your bundle identifiers and modify your product names
so that you can distinguish beta builds from release builds, and be able to keep
both installed at the same time. Right click on your Info.plist file, and choose
Open As -> Source Code. You should now see the plist file in its raw XML. Now
look for the sections you want to modify, and use the same kind of compiler
conditionals used earlier.

```xml
<key>CFBundleDisplayName</key>
#if RELEASE
<string>${PRODUCT_NAME}</string>
#else
<string>${PRODUCT_NAME} Beta</string>
#endif
<key>CFBundleIdentifier</key>
#if RELEASE
<string>com.yourcompany.myapp-appstore</string>
#else
<string>com.yourcompany.myapp-beta</string>
#endif
```

Once you start adding compiler conditionals into your Info.plist, Xcode will
start to tell you that the file has been corrupted, and is unreadable. Don't
worry, it isn't. You can always do the same right click -> Open As -> Source
Code tango you used to add the compiler conditionals in the first place. The one
issue this may cause is that the "Summary" screen in newer versions of Xcode
will become unable to read your Info.plist file. This means that if you want to
change any of the settings contained within the file, you will have to edit the
<abbr title="Extensible Markup Language">XML</abbr> directly, which isn't always
the most pleasant of experiences.

## Bonus round

There are actually some built in flags you can use to help compile your source
code dynamically. The most interesting ones for our purposes are
`TARGET_IPHONE_SIMULATOR` and `TARGET_OS_IPHONE`. These are set as value
definitions, so you should be using `#if` to check the conditional, not
`#ifdef`. This can be used in all sorts of interesting ways. My favorite
use-case is an extension of the dynamic <abbr title="Application Programming
Interface">API</abbr> constant from earlier. When developing against an <abbr
title="Application Programming Interface">API</abbr> for a rails app for which I
have access to the source code I prefer to run the app locally, instead of
dealing with calls to a staging server. So I take the example above, and modify
it like so:

```objectivec
#if TARGET_IPHONE_SIMULATOR
static NSString *const MY_API_URI = @"http://localhost:3000/";
#elif RELEASE
static NSString *const MY_API_URI = @"https://api.example.com/";
#else
static NSString *const MY_API_URI = @"https://api.staging-example.com/";
#endif
```

Now, when building for the simulator, I'm pointing the app at my local Rails
server. But the app is still pointing at the real <abbr title="Application
Programming Interface">API</abbr> for release builds, and the staging <abbr
title="Application Programming Interface">API</abbr> for everything else. Huge
time saver.

In addition, there are a number of variables you can use inside your compiler
flags to create the flags dynamically. Notably, the `CONFIGURATION` variable
corresponds to the build configuration name. That means that setting up a
preprocessor macro with `CONFIGURATION_$(CONFIGURATION)` for all build settings
will resolve to `CONFIGURATION_Debug` for builds under the 'Debug' build
setting, but will resolve to `CONFIGURATION_Release` for builds under the
'Release' setting. [HockeyApp][http://www.hockeyapp.net] recommends using this
same technique to keep their Beta Testing code out of your release builds for
the app store.

## With great power

I'd be remiss if I didn't state that this technique should be used extremely
sparingly. The use cases presented here are examples of how you may want to use
source code preprocessing, but you can quickly go too far. Used correctly and
sensibly however, Preprocessors can be a powerful addition to your workflow. You
just have to know where to find them.
