How to work with Macro Preprocessor in Xcode project?

When you work on white branding apps. The target membership is an issue to expand for different UIs and logics which only apply for specific targets. We have to think about how to separate them in the same code base (Xcode Workspace).

Luckily Xcode build compiler supports us variables to do so. It says Macro Preprocessor. We basically use a lot about Macro on top of our header like below:
#define PI 3.1415

And in scope of this post, I’ll limit about target as white branding apps. If you don’t familiar with Macro Preprocessor, I prefer to scroll to the end of page to download sample app and follow up this post for easy understanding.

So, in the end we will have something like this.

#if target
//handle logic for target membership classes
#elif target2
// Handle logic for target 2 membership classes
#else
// handle logic for common, applies for both targets
#endif

What is Target Membership and its issues:

Let say I have 3 classes:

MyCustom -> MacroDemo member

MyCustom2 -> MacroDemo2 member

Common -> MacroDemo and MacroDemo2 member

Target membership

It means that only target member could access and instant to its classes. We absolutely get error from compiler when we try to access from class that non-membership.

Error on wrong target access

How to define macro processor, especially for target?

Xcode -> TARGETS -> Build Settings -> type: Processors Macros -> Type the macro name you expected. And set equal to 1

The name should be unique for each target. For example the MacroDemo2 we will have MacroDemo2_target=1

define macro in xcode

So. In use, this will be like below. Compiler error is gone, it only access to right classes membership inside block

Important: It’s still not enough to make it works perfectly. Especially in Swift, there is an exception that you have to take care:

Inside Xcode -> TARGETS -> Build Settings -> Active Compilation Condition

Set same macro name with Preprocessor. But without equal to 1

Active Compilation Conditions

Those are for Xcode settings. However, if you’re using xcodebuild for doing CI for example, here are variable name:

Macro Preprocessor: GCC_PREPROCESSOR_DEFINITIONS

Active Compilation Conditions: SWIFT_ACTIVE_COMPILATION_CONDITIONS

So, the command will be:

xcodebuild -workspace <your workspace> -scheme <your scheme> GCC_PREPROCESSOR_DEFINITIONS=<your definition> SWIFT_ACTIVE_COMPILATION_CONDITIONS=<your definition>

Notes: It’s a bit tricky to use Macro inside implementation because complier will ignore your classes/files during compile time. In other words, if you’re using a specific class (let say you changes your mind for new white branding to re-use some class but has added to Macro block, your app will crash due to non-accessible. So, make sure you really know which class is used for specific targets only or add #warning on top of function in order to adjust later.

You could find the sample project here: MacroSample

Cheers!

Software Engineer