Active Compilation Conditions no desenvolvimento de aplicações: conceitos-chave e aplicação

Autor: IT Sectr Publicado: 2026-06-01 Tempo de leitura: 8 min

Active Compilation Conditions são flags que são passadas ao compilador durante a fase de compilação e permitem incluir ou excluir blocos de código específicos do ficheiro binário final. De acordo com a Documentação do Apple Developer (2026), o Swift suporta Active Compilation Conditions através da chave OTHER_SWIFT_FLAGS e da diretiva #if. Active Compilation Conditions dão aos programadores a capacidade de compilar diferentes versões de código para depuração, teste e produção sem verificações em tempo de execução.

Pontos principais

  • Active Compilation Conditions — flags de compilação personalizadas que determinam quais blocos de código são compilados no binário final.
  • Swift usa a chave OTHER_SWIFT_FLAGS nas Definições de Compilação do Xcode para definir flags com o prefixo -D.
  • A diretiva #if verifica a presença de uma flag: o código dentro de #if DEBUG compila apenas em compilações de depuração.
  • Android tem uma capacidade análoga — campos BuildConfig e productFlavors no Gradle.
  • Desempenho — a compilação condicional não deixa vestígios no binário de lançamento, ao contrário das flags em tempo de execução.

O que são Active Compilation Conditions

Active Compilation Conditions são flags de compilação que determinam o conjunto de diretivas de pré-processador ativas durante a compilação. Ao contrário das flags em tempo de execução (verificação if (isDebug)), as condições de compilação excluem fisicamente o código inativo do ficheiro binário, proporcionando ganhos de desempenho e reduzindo o tamanho da aplicação.

O mecanismo opera ao nível do pré-processador ou fases iniciais de compilação: o compilador recebe uma lista de nomes ativos e, ao encontrar a diretiva #if NAME, verifica se NAME está nessa lista. Se o nome não estiver presente, o código dentro do bloco é ignorado e não compilado.

De acordo com o Blog do Swift.org (2025), usar Active Compilation Conditions em vez de flags em tempo de execução reduz o tamanho do binário de lançamento numa média de 12-18% para projetos com um sistema extenso de registo e ferramentas de depuração. Isto é especialmente crítico para aplicações móveis com limitações de tamanho de ficheiro de instalação.

A principal diferença da compilação condicional ao nível do pré-processador C/C++ é que as Active Compilation Conditions em Swift e Kotlin operam ao nível da AST (Árvore de Sintaxe Abstrata) do compilador, não ao nível de substituição de texto. Isto torna-as mais seguras e previsíveis: qualquer erro de sintaxe num ramo #if inativo será detetado durante a análise, não se manifestará em tempo de execução.

Outra diferença importante é que em Swift, a condição #if os(iOS) || os(macOS) é verificada em tempo de compilação e funciona com nomes de plataforma, não com macros de pré-processador. Isto elimina toda uma classe de erros relacionados com a inserção incorreta de texto através de #define, que são possíveis no pré-processador C/C++. O compilador Swift vê a AST, não o texto substituído, tornando a depuração da compilação condicional significativamente mais fácil.

Active Compilation Conditions em Swift

O Swift suporta Active Compilation Conditions através da diretiva #if, que aceita uma lista de nomes de flags combinados com operadores lógicos &&, || e !. O compilador inclui o código dentro de #if ... #endif apenas se a condição for verdadeira.

Condições incorporadas do Swift

O Swift fornece várias condições incorporadas: DEBUG (ativo automaticamente em compilações de depuração), swift(>=5.0) (verificação de versão do compilador), canImport(UIKit) (verificação de disponibilidade do módulo) e targetEnvironment(simulator) (verificação de ambiente). Estas condições não requerem configuração adicional.

swift
// Condições incorporadas do Swift
#if DEBUG
    print("Compilação de depuração — registo ativo")
#endif

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

Flags personalizadas no Xcode

Os programadores podem adicionar as suas próprias flags através da Definição de Compilação OTHER_SWIFT_FLAGS no Xcode. A flag é especificada com o prefixo -D, por exemplo -DBETA ou -DANALYTICS_ENABLED. Podem ser configurados diferentes conjuntos de flags para diferentes configurações (Debug, Release, Staging).

swift
// Manipulação da flag personalizada 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
}

Condições de plataforma #if os()

O Swift suporta condições de plataforma: os(iOS), os(macOS), os(tvOS), os(watchOS), os(Linux), os(Windows). Estas condições verificam a plataforma de compilação alvo e permitem escrever código partilhado entre várias plataformas Apple com blocos específicos de plataforma.

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
}

Alternativas em Android e Kotlin

No ecossistema Android, as Active Compilation Conditions são implementadas através do sistema BuildConfig, productFlavors e flags em build.gradle.kts. O Kotlin não tem um equivalente direto da diretiva #if ao nível da linguagem, mas fornece mecanismos alternativos.

Campos BuildConfig como flags

A abordagem mais comum é adicionar um buildConfigField para cada flag: buildConfigField("boolean", "BETA", "true"). Estes campos são gerados na classe BuildConfig para cada Variante de Compilação separadamente. O campo DEBUG já está incorporado e é automaticamente verdadeiro para compilações de depuração.

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

// Uso em código Kotlin
if (BuildConfig.BETA) {
    enableBetaFeatures()
}

Source Sets e productFlavors

O Gradle permite criar diretórios sourceSets separados para cada sabor. Por exemplo, src/demo/ e src/full/. Classes com o mesmo nome em diferentes sourceSets substituem-se mutuamente ao compilar o sabor correspondente. Este é um mecanismo mais poderoso do que flags porque classes inteiras podem ser sobrescritas.

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
}

Para Kotlin Multiplatform (KMP), está disponível a diretiva expect/actual, que permite declarar declarações esperadas em código comum e fornecer implementações específicas de plataforma. Este é um mecanismo ao nível do compilador semelhante em efeito às Active Compilation Conditions — o código inativo não é compilado para plataformas não adequadas.

Casos de uso e melhores práticas

As Active Compilation Conditions são usadas em quatro cenários principais: depuração (registos, inspetores), testes A/B (flags de funcionalidades), adaptação de plataforma (código partilhado iOS/macOS) e licenciamento (versões gratuitas/pagas).

Registo de depuração

O cenário mais comum é o registo condicional. Em compilações de depuração, todos os registos são escritos na consola; em compilações de lançamento, nada é registado. Usar #if DEBUG ou BuildConfig.DEBUG garante que o binário de lançamento não contém nenhuma chamada de logger, mesmo as inlineadas.

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

Flags de funcionalidades em tempo de compilação

Se uma nova funcionalidade ainda não está pronta para produção mas já existe no código, pode ser ocultada atrás de uma flag de compilação. Ao contrário das flags de funcionalidades em tempo de execução, as flags de compilação não sobrecarregam a aplicação com verificações e não podem ser ativadas pelo utilizador.

  • Novas funcionalidades — ocultar funcionalidade incompleta até ao próximo lançamento sem eliminar código
  • Analítica — ativar a recolha adicional de métricas apenas para testadores beta
  • SDK de terceiros — excluir bibliotecas pesadas da versão gratuita da aplicação
  • Componentes de UI — mostrar ecrãs experimentais apenas em compilações de staging

Melhores práticas

As Active Compilation Conditions devem ser usadas com moderação. Um número excessivo de flags torna o código difícil de entender: o programador não pode ter a certeza de que ramos serão compilados num dado momento. Recomenda-se documentar cada flag no README ou num ficheiro CONFIG.md dedicado.

Em grandes projetos com equipas distribuídas, é útil implementar validação automática de flags no CI. Cada solicitação de pull deve passar pela compilação com todas as combinações possíveis de Active Compilation Conditions. Isto garante que o código sob uma flag inativa não se quebrou devido a refatoração, e que nenhum ramo de compilação condicional permanece não testado até ao lançamento. Ferramentas como xcresulttool (para iOS) e Gradle Build Scan (para Android) ajudam a automatizar este processo.

  • Mínimo de flags — não mais de 5-7 condições ativas por projeto. Cada flag é um ponto de complexidade.
  • Convenção de nomes — todas as flags em MAIÚSCULAS, com prefixo do projeto: MYAPP_BETA, MYAPP_ANALYTICS.
  • Revisão de código — cada adição de #if ou buildConfigField deve passar por uma revisão separada.
  • Testes — o CI deve compilar todas as combinações possíveis de flags pelo menos uma vez por dia.

Perguntas frequentes

Qual é a diferença entre #if DEBUG e if (isDebug) em Swift?

#if DEBUG é uma diretiva de compilação: se DEBUG não estiver ativo, o código dentro do bloco não entra no binário. if (isDebug) é uma verificação em tempo de execução: o código é sempre compilado, a condição é verificada durante a execução. #if não deixa vestígios na compilação de lançamento.

Como adiciono uma flag personalizada no Xcode?

Nas Definições de Compilação do projeto, encontre Other Swift Flags (OTHER_SWIFT_FLAGS) e adicione uma nova linha com a flag: -DMY_FLAG. A flag será visível para a diretiva #if MY_FLAG. Podem ser definidas flags diferentes para as configurações Debug e Release.

Existe um equivalente em Kotlin do Swift #if?

Kotlin/JVM não tem um equivalente direto. Em vez disso, são usados campos BuildConfig (verificação em tempo de execução, mas o ProGuard pode remover código não utilizado). Em Kotlin Multiplatform — a diretiva expect/actual ao nível das declarações.

Podem combinar-se várias flags num único #if?

Sim, o Swift suporta operadores lógicos: #if DEBUG && BETA, #if os(iOS) || os(tvOS), #if !RELEASE. As condições podem ser agrupadas com parênteses para lógica complexa. AND e OR funcionam pelas regras padrão de curto-circuito.

Porque é que #if DEBUG não funciona nas pré-visualizações do SwiftUI?

As pré-visualizações do SwiftUI são compiladas num processo separado com flags diferentes do alvo principal. O DEBUG pode não estar ativo. Solução: use targetEnvironment(simulator) para código de pré-visualização ou extraia a lógica condicional para métodos separados.

Resumo

  • Active Compilation Conditions — flags de compilação que excluem fisicamente o código inativo do binário sem verificações em tempo de execução.
  • Swift suporta #if com condições incorporadas (DEBUG, os, canImport) e flags personalizadas via OTHER_SWIFT_FLAGS.
  • Android e Kotlin usam campos BuildConfig, productFlavors e o mecanismo expect/actual no KMP.
  • Desempenho — a compilação condicional reduz o tamanho do binário em 12-18% em projetos com registo extenso.
  • Flags de funcionalidades em tempo de compilação não sobrecarregam a aplicação com verificações e não podem ser ativadas pelo utilizador.
  • Recomendações — não mais de 5-7 flags por projeto, convenção de nomes com prefixo, testes obrigatórios de todas as combinações no CI.

Vamos desenvolver um aplicativo móvel chave na mão

A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.

Discutir o projeto

Leia também