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 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.
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.
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.
// 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
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).
// 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
}
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.
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
}
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.
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.
// build.gradle.kts
android {
buildTypes {
debug {
buildConfigField("boolean", "BETA", "true")
}
release {
buildConfigField("boolean", "BETA", "false")
}
}
}
// Uso em código Kotlin
if (BuildConfig.BETA) {
enableBetaFeatures()
}
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.
// 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.
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).
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.
func logRequest(_ url: URL, _ statusCode: Int) {
#if DEBUG
Logger.debug("Request to \(url.absoluteString) returned \(statusCode)")
#endif
}
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.
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.
Perguntas frequentes
#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.
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.
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.
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.
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
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.
Leia também