.xcconfig — що це, синтаксис і змінні в Xcode

Автор: IT Sectr Опубліковано: 2026-05-30 Час читання: 8 хв

.xcconfig — це конфігураційний файл Xcode у форматі «ключ=значення», який централізовано керує Build Settings проекту. Замість того щоб вручну змінювати параметри в UI Xcode для кожної конфігурації, розробники описують їх у текстовому файлі, який можна версіонувати та перевикористовувати між проектами. Згідно з Apple Developer Documentation, 2025, використання .xcconfig скорочує час налаштування проекту на 70% та усуває розбіжності в конфігураціях між розробниками. Файли .xcconfig можуть успадковувати один одного, утворюючи ланцюг конфігурацій.

Головне

  • .xcconfig — текстовий файл із Build Settings у форматі ключ=значення.
  • Успадкування через #include дозволяє будувати ланцюги конфігурацій (Dev → Staging → Production).
  • Умовні директиви платформи (iOS/macOS) та архітектури керуються через конфігурацію.
  • Build Settings у .xcconfig перевизначають значення за замовчуванням у проекті Xcode.
  • Керування версіями — .xcconfig зберігається в Git разом із проектом у xcshareddata.

Що таке .xcconfig?

.xcconfig (файл конфігурації Xcode) — це звичайний текстовий файл, який містить Build Settings у форматі PARAMETER_NAME = value. Файли .xcconfig використовуються для централізованого керування конфігураціями збірки Xcode: вони замінюють ручне редагування полів в інтерфейсі Build Settings. Кожен .xcconfig прив'язаний до Build Configuration (Debug, Release) або до проекту в цілому та може перевизначати будь-яку build setting: SWIFT_VERSION, IPHONEOS_DEPLOYMENT_TARGET, PRODUCT_BUNDLE_IDENTIFIER, CODE_SIGN_STYLE, PROVISIONING_PROFILE_SPECIFIER.

До появи .xcconfig налаштування збірки зберігалися лише в project.pbxproj — двійковому/plist файлі, який важко читати в diff'ах і неможливо коментувати. .xcconfig вирішив цю проблему: розробники можуть коментувати параметри, групувати їх за змістом, створювати версіоновані файли для різних середовищ та успадковувати параметри між файлами. Це зробило .xcconfig стандартом де-факто для керування конфігураціями в iOS-проектах.

Файли .xcconfig розташовуються всередині проекту, зазвичай у папці Configurations/ або BuildConfig/. Кожен файл відповідає одній Build Configuration: Debug.xcconfig, Release.xcconfig, Staging.xcconfig. Додатково створюється спільний файл Shared.xcconfig, який підключається до всіх конфігурацій через #include. Це дозволяє визначити спільні параметри один раз і перевизначати специфічні в конфігураційних файлах.

Переваги перед UI Build Settings

Читабельність diff: зміни .xcconfig видно в Git diff як звичайні рядки. На відміну від project.pbxproj, де через зміну порядку полів diff показує 50 рядків змін при правці одного параметра. Коментарі: у .xcconfig можна пояснити, навіщо потрібен кожен параметр. Успадкування: можна створити базову конфігурацію зі спільними налаштуваннями та перевизначати лише потрібні параметри для Debug і Release.

Синтаксис і структура .xcconfig

Змінні та підстановки

Синтаксис .xcconfig максимально простий: кожен рядок — це параметр, ім'я та значення через знак рівності. Пробіли навколо = ігноруються. Значення можуть містити змінні у форматі $(VARIABLE_NAME) або ${VARIABLE_NAME}. Коментарі починаються з // або # і діють до кінця рядка. Рядки продовжуються на наступному рядку за допомогою оберненої скісної риски \. Порожні рядки ігноруються.

Змінні в .xcconfig можуть посилатися на інші змінні, створюючи композитні значення. Наприклад: PRODUCT_NAME = MyApp, PRODUCT_BUNDLE_IDENTIFIER = com.example.$(PRODUCT_NAME). Xcode обчислює значення на етапі збірки, підставляючи актуальні значення змінних. AGP підтримує і системні змінні: ARCHS, SDK_NAME, CONFIGURATION, PLATFORM_NAME, які задаються середовищем збірки.

Для умовної конфігурації використовуються директиви платформи в квадратних дужках: PARAMETER[sdk=iphoneos*] = value. Наприклад, SUPPORTED_PLATFORMS[sdk=iphoneos*] = iphoneos задає параметр лише для iOS-збірки. Підтримуються маски: * (будь-які символи), ? (один символ). Умовні директиви дозволяють мати один .xcconfig для кількох платформ і задавати різні значення для iOS та macOS в одному файлі.

text
// Shared.xcconfig — спільні налаштування проекту
SWIFT_VERSION = 5.0
IPHONEOS_DEPLOYMENT_TARGET = 16.0
SDKROOT = iphoneos
TARGETED_DEVICE_FAMILY = 1,2

// Ідентифікатор Bundle — збирається з префікса та імені
BUNDLE_ID_PREFIX = com.example
PRODUCT_NAME = MyApp
PRODUCT_BUNDLE_IDENTIFIER = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME)

// Умовне налаштування для macOS
SUPPORTED_PLATFORMS[sdk=macosx*] = macosx
PRODUCT_BUNDLE_IDENTIFIER[sdk=macosx*] = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME).mac

// Версіонування
MARKETING_VERSION = 2.4.1
CURRENT_PROJECT_VERSION = 37

Успадкування конфігурацій через #include

#include — це директива препроцесора .xcconfig, яка підключає вміст іншого .xcconfig файлу. Директиви можна вкладати: Shared.xcconfig може #include «Base.xcconfig», Debug.xcconfig — #include «Shared.xcconfig». Ланцюг успадкування дозволяє будувати ієрархію конфігурацій, де кожен рівень перевизначає параметри попереднього. #include працює за принципом останнього запису: якщо один і той самий параметр визначений у підключеному та основному файлі, пріоритет має значення з основного.

Правильна ієрархія для типового iOS-проекту: Base.xcconfig (найзагальніші параметри) → Shared.xcconfig (налаштування проекту) → Debug.xcconfig або Release.xcconfig. Base.xcconfig визначає стандарти (SWIFT_VERSION, DEPLOYMENT_TARGET), Shared.xcconfig — специфіку проекту (PRODUCT_NAME, PREPROCESSOR_DEFINITIONS), Debug/Release — середовище (DEBUG_INFORMATION_FORMAT, OPTIMIZATION_CFLAGS). #include не допускає циклів — Xcode видасть помилку при виявленні циклічної залежності.

Приклад: Config/Base.xcconfigConfig/iOS/Shared.xcconfigConfig/iOS/Debug.xcconfig. Така структура дозволяє перевикористовувати Base для iOS, macOS та tvOS проектів, а Shared — лише для iOS. Зверніть увагу: #include використовує ім'я файлу або відносний шлях від розташування кореневого .xcconfig. Абсолютні шляхи не рекомендуються — вони ламають збірку на інших машинах та в CI/CD.

text
// --- Config/Base.xcconfig ---
SWIFT_VERSION = 5.0
ENABLE_MODULE_VERIFIER = YES
CLANG_ENABLE_MODULES = YES

// --- Config/iOS/Shared.xcconfig ---
#include "../Base.xcconfig"
IPHONEOS_DEPLOYMENT_TARGET = 16.0
PRODUCT_BUNDLE_IDENTIFIER = com.example.myapp

// --- Config/iOS/Debug.xcconfig ---
#include "Shared.xcconfig"
OPTIMIZATION_CFLAGS = -O0
DEBUG_INFORMATION_FORMAT = dwarf
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG
ENABLE_TESTABILITY = YES

// --- Config/iOS/Release.xcconfig ---
#include "Shared.xcconfig"
OPTIMIZATION_CFLAGS = -Osize
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
SWIFT_COMPILATION_MODE = wholemodule

Підключення .xcconfig у проекті Xcode

Конфігурації на рівні проекту та на рівні цілі

Підключення .xcconfig до проекту виконується в Project Info → Configurations. Для кожної Build Configuration (Debug, Release, AdHoc) у випадному списку «Based on Configuration File» вибирається відповідний .xcconfig. Якщо конфігурація не прив'язана до файлу, Xcode використовує значення з project.pbxproj. Після вибору .xcconfig всі параметри з файлу стають активними для даної конфігурації.

Важливо розрізняти конфігурації на рівні проекту та на рівні цілі. .xcconfig на рівні проекту задає параметри за замовчуванням для всіх цілей. .xcconfig на рівні цілі перевизначає їх для конкретної цілі. Якщо параметр не заданий у .xcconfig на рівні цілі, використовується значення з рівня проекту. Якщо не заданий і там — з project.pbxproj. Практичне правило: у рівень проекту поміщайте спільні параметри (збірка, версії), у рівень цілі — специфіку цілі (bundle identifier, provisioning).

При конфлікті між .xcconfig та UI Build Settings пріоритет має значення з UI (воно перевизначає .xcconfig). Це може призвести до плутанини: розробник змінює Build Setting в UI, не підозрюючи, що в .xcconfig вказано інше значення. Рекомендується повністю перейти на .xcconfig і не чіпати UI Build Settings. Для перевірки, який параметр застосовується, використовуйте xcrun xcodebuild -showBuildSettings — команда покаже фінальні значення всіх параметрів після вирішення всіх рівнів.

Приклад: середовища Dev, Staging, Production

Розглянемо трирівневу конфігурацію: Dev (локальна розробка), Staging (тестовий сервер), Production (реліз). Для кожного середовища створюється окремий .xcconfig, який визначає різні значення API_URL, логування та сертифікатів. Dev використовує localhost, Staging — staging.api.example.com, Production — api.example.com. Всі три успадковують спільний Shared.xcconfig через #include.

Ключовий параметр, який відрізняється між середовищами — PRODUCT_BUNDLE_IDENTIFIER. Для Dev: com.example.myapp.dev, для Staging: com.example.myapp.staging, для Production: com.example.myapp. Різні bundle ID дозволяють встановити всі три версії на один пристрій одночасно. Також відрізняються CODE_SIGN_IDENTITY (Apple Development для Dev, Apple Distribution для Production) та PROVISIONING_PROFILE_SPECIFIER.

Для передачі значень у код використовується INFOPLIST_PREFIX_HEADER або OTHER_SWIFT_FLAGS із -D препроцесором. У Swift немає препроцесора, тому використовуються Active Compilation Conditions: SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEV. У коді: #if DEV; #elseif STAGING; #else; #endif. Для Objective-C використовується GCC_PREPROCESSOR_DEFINITIONS. Це дозволяє компілювати різний код для різних середовищ без зміни вихідних файлів.

text
// --- Config/Dev.xcconfig ---
#include "Shared.xcconfig"

PRODUCT_BUNDLE_IDENTIFIER = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME).dev
CODE_SIGN_IDENTITY = Apple Development
PROVISIONING_PROFILE_SPECIFIER = Dev Profile

SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG DEV
OTHER_SWIFT_FLAGS = -D DEV

// API URL через Info.plist — значення підставляється
API_BASE_URL = http://localhost:3000/api

// --- Config/Staging.xcconfig ---
#include "Shared.xcconfig"

PRODUCT_BUNDLE_IDENTIFIER = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME).staging
CODE_SIGN_IDENTITY = Apple Development
PROVISIONING_PROFILE_SPECIFIER = Staging Profile

SWIFT_ACTIVE_COMPILATION_CONDITIONS = STAGING
OTHER_SWIFT_FLAGS = -D STAGING
API_BASE_URL = https://staging.api.example.com/v2

// --- Config/Production.xcconfig ---
#include "Shared.xcconfig"

PRODUCT_BUNDLE_IDENTIFIER = $(BUNDLE_ID_PREFIX).$(PRODUCT_NAME)
CODE_SIGN_IDENTITY = Apple Distribution
PROVISIONING_PROFILE_SPECIFIER = AppStore Distribution

SWIFT_ACTIVE_COMPILATION_CONDITIONS = RELEASE
API_BASE_URL = https://api.example.com/v3

.xcconfig та Info.plist: передача значень

Значення з .xcconfig можна передавати в Info.plist через змінні $(PARAMETER_NAME). Якщо параметр визначений у .xcconfig (наприклад, API_BASE_URL), його можна використовувати в Info.plist: <key>ApiBaseUrl</key><string>$(API_BASE_URL)</string>. На етапі збірки Xcode замінює $(API_BASE_URL) на значення з .xcconfig. Це дозволяє налаштовувати конфігурацію застосунку без зміни коду — достатньо переключити схему.

Параметри .xcconfig, що використовуються в Info.plist, мають бути публічними — вони потрапляють у бінарник і видимі в декомпільованому застосунку. Для секретних значень (токенів, паролів) не використовуйте .xcconfig — використовуйте сервіси на кшталт Firebase Remote Config, що запускаються на сервері. .xcconfig для Info.plist підходить для: URL серверів, назв сутностей, ідентифікаторів трекерів, feature flags.

Доступ до значень Info.plist у коді: Bundle.main.object(forInfoDictionaryKey: «ApiBaseUrl») для Objective-C/Swift. Якщо значення задано через .xcconfig, воно буде підставлено та доступне в Bundle main.infoDictionary. Цей метод є кращим за BuildConfigField (як в Android), оскільки Info.plist — стандартний механізм iOS, і його значення доступні всім компонентам системи, включаючи extensions, widget'и та Siri Intents.

Часті запитання

Чим .xcconfig відрізняється від User-Defined Setting в Xcode?

User-Defined Setting — це кастомний параметр, доданий через UI Build Settings. Він працює так само, як .xcconfig, але його не можна версіонувати, коментувати та перевикористовувати між проектами. .xcconfig — файл на диску, User-Defined Setting — запис у project.pbxproj.

Чи можна використовувати .xcconfig для CocoaPods?

Так, CocoaPods генерує Pods-*.xcconfig файли для кожної конфігурації. Ці файли містять налаштування для підключення подів. Pods.xcconfig автоматично підключається до вашого .xcconfig через #include у файлі-генераторі. Не редагуйте Pods.xcconfig вручну — він перезаписується під час pod install.

Як отримати значення .xcconfig у коді Swift?

Через Info.plist: визначте параметр у .xcconfig та використовуйте $(PARAM) в Info.plist. У коді: Bundle.main.infoDictionary[«PARAM»]. Для препроцесорних прапорців використовуйте SWIFT_ACTIVE_COMPILATION_CONDITIONS та #if CONDITION.

Чому .xcconfig не застосовується?

Причини: ви змінили значення в UI Build Settings (UI перевизначає .xcconfig); файл не підключено до конфігурації (перевірте Project → Info → Configurations); неправильний шлях #include; помилка в імені параметра. Діагностика: xcodebuild -showBuildSettings покаже всі активні параметри.

Чи потрібен .xcconfig для SwiftUI проектів?

Так, .xcconfig не залежить від фреймворку UI. Для SwiftUI проектів .xcconfig так само корисний: керування bundle ID, версіями, конфігураціями середовища, SWIFT_ACTIVE_COMPILATION_CONDITIONS для фіча-флагів. SwiftUI не надає альтернативи .xcconfig, тому рекомендується використовувати його з будь-якими проектами.

Підсумки

  • .xcconfig — текстовий файл Build Settings для версіонованого керування конфігураціями Xcode.
  • Успадкування через #include дозволяє будувати ієрархію конфігурацій від Base до Production.
  • Синтаксис включає змінні $(VAR), умовні директиви [sdk=ios*] та коментарі // і #.
  • Підключення виконується в Project Info → Configurations для кожної Build Configuration.
  • Середовища Dev/Staging/Production відрізняються bundle ID, сертифікатами та API URL.
  • Info.plist отримує значення з .xcconfig через $(PARAM), роблячи їх доступними в runtime.
  • Рекомендація: повністю переходьте на .xcconfig та не використовуйте UI Build Settings для уникнення конфліктів.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також