Active Compilation Conditions у развоју апликација: кључни појмови и примена

Аутор: IT Sectr Објављено: 2026-06-01 Време читања: 8 мин

Active Compilation Conditions су заставице које се прослеђују компајлеру у фази изградње и омогућавају укључивање или искључивање одређених блокова кода из финалне бинарне датотеке. Према Apple Developer Documentation (2026), Swift подржава Active Compilation Conditions кроз кључ OTHER_SWIFT_FLAGS и директиву #if. Active Compilation Conditions омогућавају програмерима да праве различите верзије кода за отклањање грешака, тестирање и продукцију без провера у време извршавања.

Главно

  • Active Compilation Conditions — корисничке заставице компајлирања које одређују који блокови кода се компајлирају у финални бинарни фајл.
  • Swift користи кључ OTHER_SWIFT_FLAGS у Xcode Build Settings за постављање заставица са префиксом -D.
  • Директива #if проверава присуство заставице: код унутар #if DEBUG се компајлира само у debug изградњи.
  • Android — аналогна могућност: BuildConfig поља и productFlavors у Gradle.
  • Перформансе — условно компајлирање не оставља трагове у release бинарном фајлу, за разлику од runtime заставица.

Шта су Active Compilation Conditions

Active Compilation Conditions су заставице компајлирања које одређују скуп активних директива препроцесора у фази изградње. За разлику од runtime заставица (провера if (isDebug)), услови компајлирања физички искључују неактивни код из бинарног фајла, што повећава перформансе и смањује величину апликације.

Механизам ради на нивоу препроцесора или раних фаза компајлирања: компајлер добија листу активних имена и када наиђе на директиву #if NAME проверава да ли се NAME налази на тој листи. Ако име не постоји — код унутар блока се игнорише и не компајлира.

Према Swift.org Blog (2025), коришћење Active Compilation Conditions уместо runtime заставица смањује величину release бинарног фајла у просеку за 12-18% у пројектима са развијеним системом логирања и алаткама за отклањање грешака. Ово је посебно критично за мобилне апликације са ограничењима величине инсталационог фајла.

Главна разлика у односу на условно компајлирање на нивоу препроцесора C/C++ — Active Compilation Conditions у Swift и Kotlin раде на нивоу AST (Abstract Syntax Tree) компајлера, а не на нивоу текстуалне замене. То их чини сигурнијим и предвидљивијим: било која синтаксна грешка у неактивној грани #if биће откривена у фази парсирања, а неће се појавити у рантајму.

Још једна важна разлика — у Swift услов #if os(iOS) || os(macOS) се проверава у фази компајлирања и ради са именима платформи, а не са макроима препроцесора. Ово елиминише читаву класу грешака везаних за неправилно уметање текста путем #define, које су могуће у C/C++ препроцесору. Swift компајлер види AST, а не замењени текст, што чини отклањање грешака условног компајлирања знатно лакшим.

Active Compilation Conditions у Swift

Swift подржава Active Compilation Conditions кроз директиву #if, која прихвата листу имена заставица повезаних логичким операторима &&, || и !. Компајлер укључује код унутар #if ... #endif само ако је услов испуњен.

Уграђени услови Swift

Swift пружа неколико уграђених услова: DEBUG (аутоматски активан у debug изградњи), swift(>=5.0) (провера верзије компајлера), canImport(UIKit) (провера доступности модула) и targetEnvironment(simulator) (провера окружења). Ови услови не захтевају додатно подешавање.

swift
// Уграђени услови Swift
#if DEBUG
    print("Debug изградња — логирање активно")
#endif

#if canImport(UIKit)
    import UIKit
    let screen = UIScreen.main.bounds
#elseif canImport(AppKit)
    import AppKit
    let screen = NSScreen.main?.frame
#endif

Корисничке заставице у Xcode

Програмер може додавати своје заставице кроз Build Setting OTHER_SWIFT_FLAGS у Xcode. Заставица се наводи са префиксом -D, на пример -DBETA или -DANALYTICS_ENABLED. За различите конфигурације (Debug, Release, Staging) могу се поставити различити скупови заставица.

swift
// Обрада сопствене заставице BETA
#if BETA
    let apiEndpoint = "https://beta.api.com"
    let isLoggingEnabled = true
#else
    let apiEndpoint = "https://api.com"
    let isLoggingEnabled = false
#endif

func trackEvent(_ name: String) {
    #if ANALYTICS_ENABLED
        Analytics.log(name)
    #endif
}

Платформски услови #if os()

Swift подржава платформске услове: os(iOS), os(macOS), os(tvOS), os(watchOS), os(Linux), os(Windows). Ови услови проверавају циљану платформу изградње и омогућавају писање кода заједничког за више Apple платформи са платформски специфичним блоковима.

swift
import Foundation

func getDeviceName() -> String {
    #if os(iOS)
        return UIDevice.current.name
    #elseif os(macOS)
        return Host.current.name ?? "Unknown"
    #else
        return "Other platform"
    #endif
}

Аналоги у Android и Kotlin

У Android екосистему Active Compilation Conditions су имплементиране кроз систем BuildConfig, продукт flavor-е и заставице у build.gradle.kts. Kotlin нема директан аналог директиве #if на нивоу језика, али пружа алтернативне механизме.

BuildConfig поља као заставице

Најчешћи начин — додати buildConfigField за сваку заставицу: buildConfigField("boolean", "BETA", "true"). Ова поља се генеришу у класи BuildConfig за сваки Build Variant посебно. Поље DEBUG је већ уграђено и аутоматски true за debug изградње.

kotlin
// build.gradle.kts
android {
    buildTypes {
        debug {
            buildConfigField("boolean", "BETA", "true")
        }
        release {
            buildConfigField("boolean", "BETA", "false")
        }
    }
}

// Коришћење у Kotlin коду
if (BuildConfig.BETA) {
    enableBetaFeatures()
}

Source Sets и productFlavors

Gradle омогућава креирање одвојених директоријума sourceSets за сваки flavor. На пример, src/demo/ и src/full/. Класе са истим именом у различитим sourceSets замењују једна другу приликом изградње одговарајућег flavor-а. Ово је моћнији механизам од заставица, јер се могу прегазити читаве класе.

kotlin
// src/demo/java/com/example/Config.kt
object Config {
    const val API_URL = "http://demo.api.com"
    const val IS_BETA = true
}

// src/full/java/com/example/Config.kt
object Config {
    const val API_URL = "https://full.api.com"
    const val IS_BETA = false
}

За Kotlin Multiplatform (KMP) доступна је директива expect/actual, која омогућава декларисање очекиваних декларација у заједничком коду и пружање платформских имплементација. Ово је механизам на нивоу компајлирања, аналоган Active Compilation Conditions по ефекту — неактивни код се не компајлира за неодговарајуће платформе.

Сценарији употребе и најбоље праксе

Active Compilation Conditions се примењују у четири основна сценарија: отклањање грешака (логови, инспектори), A/B тестирање (заставице функција), платформска адаптација (iOS/macOS заједнички код) и лиценцирање (бесплатне/плаћене верзије).

Логирање отклањања грешака

Најчешћи сценарио — условно логирање. У debug изградњи сви логови се пишу у конзолу, у release — ниједан. Коришћење #if DEBUG или BuildConfig.DEBUG гарантује да release бинарни фајл не садржи ниједан позив логера, чак ни инлајновани.

swift
func logRequest(_ url: URL, _ statusCode: Int) {
    #if DEBUG
        Logger.debug("Request to \(url.absoluteString) returned \(statusCode)")
    #endif
}

Feature Flags у фази изградње

Ако нова функционалност још није спремна за продукцију, али већ постоји у коду, може се сакрити иза заставице компајлирања. За разлику од runtime feature flags, заставице компајлирања не оптерећују апликацију проверама и не могу бити укључене од стране корисника.

  • Нове функције — сакриј недовршену функционалност до следећег издања без брисања кода
  • Аналитика — укључи додатно прикупљање метрика само за beta тестере
  • SDK трећих страна — искључи тешке библиотеке из бесплатне верзије апликације
  • UI компоненте — приказуј експерименталне екране само у staging изградњи

Најбоље праксе

Active Compilation Conditions треба користити умерено. Превелики број заставица чини код тешким за разумевање: програмер не може бити сигуран које гране ће се компајлирати у датом тренутку. Препоручује се документовање сваке заставице у README или посебном CONFIG.md фајлу.

У великим пројектима са дистрибуираним тимом, корисно је имплементирати аутоматску валидацију заставица у CI. Сваки pull request мора проћи изградњу са свим могућим комбинацијама Active Compilation Conditions. Ово гарантује да се код под неактивном заставицом није покварио због рефакторисања и да ниједна грана условног компајлирања није остала непроверена до тренутка издања. Алатке попут xcresulttool (за iOS) и Gradle Build Scan (за Android) помажу у аутоматизацији овог процеса.

  • Минимум заставица — не више од 5-7 активних услова по пројекту. Свака заставица је тачка сложености.
  • Конвенција именовања — све заставице у UPPER_CASE, са префиксом пројекта: MYAPP_BETA, MYAPP_ANALYTICS.
  • Code review — свако додавање #if или buildConfigField мора проћи одвојену ревизију.
  • Тестирање — CI треба да компајлира све могуће комбинације заставица бар једном дневно.

Често постављана питања

Која је разлика између #if DEBUG и if (isDebug) у Swift?

#if DEBUG — ово је директива компајлирања: ако DEBUG није активан, код унутар блока не улази у бинарни фајл. if (isDebug) — провера у време извршавања: код се увек компајлира, услов се проверава током извршавања. #if не оставља трагове у release изградњи.

Како додати своју заставицу у Xcode?

У Build Settings пројекта пронађите Other Swift Flags (OTHER_SWIFT_FLAGS) и додајте нови ред са заставицом: -DMY_FLAG. Заставица ће бити видљива директиви #if MY_FLAG. Можете поставити различите заставице за Debug и Release конфигурације.

Да ли у Kotlin постоји аналог Swift #if?

У Kotlin/JVM нема директног аналога. Уместо тога користе се BuildConfig поља (провера у време извршавања, али ProGuard може уклонити неискоришћени код). У Kotlin Multiplatform — директива expect/actual на нивоу декларација.

Могу ли се комбиновати више заставица у једном #if?

Да, Swift подржава логичке операторе: #if DEBUG && BETA, #if os(iOS) || os(tvOS), #if !RELEASE. Услови се могу груписати заградама за сложену логику. AND и OR раде по стандардним правилима кратког споја.

Зашто #if DEBUG не ради у SwiftUI прегледу?

SwiftUI преглед се компајлира у одвојеном процесу са заставицама различитим од главног target-а. DEBUG можда није активан. Решење: користите targetEnvironment(simulator) за код прегледа или извуците условну логику у одвојене методе.

Резиме

  • Active Compilation Conditions — заставице компајлирања које физички искључују неактивни код из бинарног фајла без runtime провера.
  • Swift подржава #if са уграђеним условима (DEBUG, os, canImport) и корисничким заставицама кроз OTHER_SWIFT_FLAGS.
  • Android и Kotlin користе BuildConfig поља, productFlavors и механизам expect/actual у KMP.
  • Перформансе — условно компајлирање смањује величину бинарног фајла за 12-18% у пројектима са развијеним системом логирања.
  • Feature flags у фази компајлирања не оптерећују апликацију проверама и не могу бити укључени од стране корисника.
  • Препоруке — не више од 5-7 заставица по пројекту, конвенција именовања са префиксом, обавезно тестирање свих комбинација у CI.

Развићемо мобилну апликацију под кључ

IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.

Разговарајте о пројекту

Прочитајте такође