Настройка макросов препроцессора в Xcode

Редкое приложение обходится без конфигурационных параметров. Проекты для iOS не исключение. То URL сервера надо указать, то режим отладки или демонстрационный параметр. Обычно их указывают через макросы препроцессора в настройках проекта.

Далее мы добавим свой параметр и посмотрим как им управлять через xcodebuild.

Пару слов о препроцессорах, директивах и макросах

Препроцессор С/С++ (англ. pre processor, предобработчик) — программа, подготавливающая код на языке C/C++ к компиляции.

Директивой препроцессора называется строка в исходном коде, имеющая следующий формат: #ключевое_слово параметры

Наверняка встречали в коде следующие директивы:

  • #include — вставка (включение) содержимого произвольного файла;
  • #define — макроподстановки;
  • #if, #ifdef, #elif, #else, #endifусловная компиляция;

Макрос — фрагмент код, которому дали имя. Где бы имя не использовалось, оно заменяется на содержимое макроса. Есть два типа макросов: object-like и function-like. Различие в основном в их форме. Одни похожи на объекты, другие на функции.

Пример object-like макроса

#define BUFFER_SIZE 1024

Пример function-like макроса

#define lang_init()  c_init()

Макрос препроцессора в настройках проекта Xcode

Чтобы объявить свой макрос препроцессора в настройках Xcode для этого надо:

Объявить User-Defined параметр

  • Если для всех target’ов сразу — то в project setting, если для определенного target’a то в него.
  • Выбрать вкладку Build Settings
  • Найти Заголовок User Defined
  • Добавить нужную настройку

UserDefinedMacros

Указать макрос для Apple LLVM 7.0 -Preprocessing

  • Ищем Apple LLVM 7.0 -Preprocessing
  • В строке с Processor Macros  добавляем имя макроса и присваиваем ему значение параметра API_URL=${API_URL}. В данном случае имя макроса совпадает с именем параметра(User-Defined).

PreprocessorMacrosForDebug

В окне сразу подхватится указанная настройка для макроса

PreprocessorMacrosForDebugEnd

Для Debug и Release укзаывайте отдельно.

Теперь в коде мы можем использовать данный макрос

self.firebase = [[Firebase alloc] initWithUrl:API_URL];

Но данный код не скомпилируется т.к. значения макроса не является NSString.

Preprocessor macros string

Тут два решения:

  • Модифицировать значения макроса (привести к  NSString)
  • Использовать макрос для перевода значения в NSString

Для первого решения необходимо «забекслешить» значение макроса — \@\»https://firebaseio.com\»

Preprocessor macros string

Для второго написать еще один макрос:

#define STRINGIZE(x) #x
#define STRINGIZE2(x) STRINGIZE(x)
#define API_URL_LITERAL @ STRINGIZE2(API_URL)
...
self.firebase = [[Firebase alloc] initWithUrl:API_URL_LITERAL];

Но для второго варианта опять не все гладко. Двойной слеш (\\) в URL не распознается и получается строка вида «http:» — урезанная.

С двойным слешем бороться не так просто. Предлагают различные варианты эскейпа:

  • https:/$()/firebaseio.com
  • https:\/\/firebaseio.com

Но у меня ни один не заработал

Можно доработать макрос перевода

#define STRINGIZE(x) "https://" #x

Но этот код как-то «попахивает».

Чтобы избавиться от запаха добавим флаг -traditional для Info.plist Other Preprocessor Flags. Это описано в технической записке от apple — предотвращение конвертирования URL в комментарии

Проброс макросов через xcodebuild

Если у вас есть  CI сервер (TeamCity или другой), то вы возможно сталкивались с консольной сборкой проекта. Типичная сборка выглядит так:

xcodebuld --workspace projectName.xcodeproj/project.workspace --sheme projectNameScheme clean build archive ARCHS="armv7 armv7s arm64" ONLY_ACTIVE_ARCH=NO

В очередной сборке мы хотим поменять API_URL, как это сделать?

Существуют несколько параметров для макросов согласно XCODE BUILD SETTING REFERENCE

Вот GCC_PREPROCESSOR_DEFINITIONS нам и нужны. Теперь команда сборки будет выглядит так:

xcodebuld --workspace projectName.xcodeproj/project.workspace --sheme projectNameScheme clean build archive ARCHS="armv7 armv7s arm64" ONLY_ACTIVE_ARCH=NO GCC_PREPROCESSOR_DEFINITIONS = "API_URL='another.url' DEMO = 'NO'" 

Список макросов указывается через пробел.

Настройка info.plist?

Если вы решили поменять номер сборки, имя приложения и многое другое, что указывается в info.plist, то это все можно сделать через USER-DEFINED settings. Прописываете свой параметр и добавляете его при сборке

RELEASE_VERSION = 1.1

И добавляете его в info.plist — ${RELEASE_VERSION}

Отличи GCC_PREPROCESSOR_DEFINITIONS от USER_DEFINED settings?

GCC_PREPROCESSOR_DEFINITIONS доступны в коде, а USER_DEFINED settings — нет

 

Добавить комментарий