Define common macros across Xcode projects

When you develop the module which consists of multiple libraries and/or programs such as SDK, you would like to define the common macros are referenced by multiple projects.

For example, when you develop the SDK for communicating with the specific device, suppose the constants are changed for each target devices. You could switch the target device with the common macros in the header file.

In this case, if the common header files are included by project’s source files, define the macro into it. For example, create the Configuration.h file. But, how about a case where there are multiple projects and it is hard to put the common header file? For example, the Swift doesn’t use the header file.

The build configuration settings file is able to use in this case. If you would like to try on your machine while reading this article, you can download the sample project from following link.

TOC

Create the configuration settings file

For information about how to create and configure the configuration settings file, see following acticle.

As an example, we have created three projects with the following directory structure.

Modules
├── Common.xcconfig
├── Module1
│   ├── Module1
│   │   ├── Debug.xcconfig
│   │   ├── Release.xcconfig
│   │   └── main.swift
│   └── Module1.xcodeproj
├── Module2
│   ├── Module2
│   │   ├── Debug.xcconfig
│   │   ├── Release.xcconfig
│   │   └── main.m
│   └── Module2.xcodeproj
└── Module3
    ├── Module3
    │   ├── Debug.xcconfig
    │   ├── Release.xcconfig
    │   └── main.cpp
    └── Module3.xcodeproj

Module1, Module2 and Module3 are programs built by separate project files and do not reference each other. Each project has two build configuration files, Debug.xcconfig and Release.xcconfig. Debug.xcconfig and Release.xcconfing are written as follows and includes Modules/Common.xcconfig.

#include "../Common.xcconig"

By this, you can change the build configuration settings of Module1.xcodeproj, Modue2.xcodeproj and Module3.xcodeproj by editing Modules/Common.xcconfig.

Code in Swift

Swift could define symbols but not symbols’ value. To define with Xcode, write in form -DSYMBOL at Other Swift Flags of Swift Compiler - Custom Flags in the build settings. Multiple symbols are separated by spaces.

Other Swift Flags
Other Swift Flags

Define in the configuration settings file

You can configure the Other Swift Flags in the configuration settings file by OTHER_SWIFT_FLAGS. For example, if you write the following code in the configuration settings file, the USE_PHYSICAL_DEVICE symbol is defined same as the above screen shot.

OTHER_SWIFT_FLAGS = $(inherited) -DUSE_PHYSICAL_DEVICE

The configuration settings files are also reflected in what is displayed in Xcode.

Branch by symbol in the code

To branch by symbol in the Swift code, you can use #if statement.

#if symbol

The code will be executed when the symbol is defined.

#else

The code will be executed when the symbol is not defined.

#endif

The major difference of the #if and if statements is whether the code will be contained into the binary. The code branched by #if statement and not executed code will not to be compiled. Other hand, the code branched by if statement and not executed code will be compiled, it is contained into the binary and only not executed.

Following code checks whether the USE_PHYSICAL_DEVICE symbol is defined or not.

import Foundation

#if USE_PHYSICAL_DEVICE
print("Module1 DeviceType: Physical Device")
#else
print("Module1 DeviceType: Simulator")
#endif

Code in Objective-C

The symbols used in Objective-C are same as C/C++. You can define them in the Xcode by writting in form -DMacro at Other C Flags of Apple Clang - Custom Compiler Flags in the build settings. Also, writting in form -DMacro=Value assigns the Value to Macro. Multiple macros are separated by spaces.

Other C Flags
Other C Flags

Define in the configuration settings file

You can configure the Other C Flags in the configuration settings file by OTHER_CFLAGS. For example, writting as follows defines USE_PHYSICAL_DEVICE as same as above screen shot.

OTHER_CFLAGS = $(inherited) -DUSE_PHYSICAL_DEVICE

The configuration settings file will also be reflected in the Xcode build settings screen.

Branches in the code

#ifdef or #if defined can branch the code with macros in Objective-C code.

#ifdef Macro

The code will be executed when the macro is defined.

#else

The code will be executed when the macro is not defined.

#endif

The following code branches by whether the USE_PHYSICAL_DEVICE is defined or not.

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
#ifdef USE_PHYSICAL_DEVICE
        NSLog(@"Module2 DeviceType: Physical Device");
#else
        NSLog(@"Module2 DeviceType: Simulator");
#endif
    }
    return 0;
}

Code in C/C++

The code in C/C++ as same as in the Objective-C.

Branches in the code

#ifdef and #if defined branches with macro in C/C++ too. The following code branches with wheter the USE_PHYSICAL_DEVICE is defined or not.

#include <iostream>

int main(int argc, const char * argv[]) {
#ifdef USE_PHYSICAL_DEVICE
    std::cout << "Module3 DeviceType: Physical Device" << std::endl;
#else
    std::cout << "Module3 DeviceType: Simulator" << std::endl;
#endif
    return 0;
}

Execution Result

Run above sample codes with empty Common.xcconfig file then the execution result to be following.

Module1 DeviceType: Simulator
2022-07-19 16:03:43.534012+0900 Module2[3808:159692] Module2 DeviceType: Simulator
Module3 DeviceType: Simulator

Write the following code into Common.xcconfig.

OTHER_SWIFT_FLAGS = $(inherited) -DUSE_PHYSICAL_DEVICE
OTHER_CFLAGS = $(inherited) -DUSE_PHYSICAL_DEVICE

Then run sample code and the program outputs as follows, and you can see that macros in a file are used by multiple projects.

Module1 DeviceType: Physical Device
2022-07-19 16:04:36.900064+0900 Module2[3843:162776] Module2 DeviceType: Physical Device
Module3 DeviceType: Physical Device
Let's share this post !

Author of this article

Akira Hayashiのアバター Akira Hayashi Representative, Software Engineer

I am an application developer loves programming. This blog is a tech blog, its articles are learning notes. In my work, I mainly focus on desktop and mobile application development, but I also write technical books and teach seminars. The websites of my work and books are here -> RK Kaihatsu.

TOC