アプリ開発におけるActive Compilation Conditions:主要な概念と応用

著者: IT Sectr 公開日: 2026-06-01 読了時間: 8 分

Active Compilation Conditionsは、ビルド時にコンパイラに渡されるフラグであり、最終的なバイナリファイルから特定のコードブロックを含めたり除外したりすることができます。Apple Developer Documentation(2026)によると、SwiftはOTHER_SWIFT_FLAGSキーと#ifディレクティブを通じてActive Compilation Conditionsをサポートしています。Active Compilation Conditionsにより、開発者はランタイムチェックなしで、デバッグ、テスト、本番用に異なるバージョンのコードをビルドできます。

重要なポイント

  • Active Compilation Conditions — 最終的なバイナリにどのコードブロックをコンパイルするかを決定するカスタムコンパイルフラグ。
  • SwiftはXcodeのBuild SettingsでOTHER_SWIFT_FLAGSキーを使用して、-Dプレフィックス付きのフラグを設定します。
  • #ifディレクティブはフラグの存在を確認します。#if DEBUG内のコードはデバッグビルドでのみコンパイルされます。
  • Androidにも同様の機能があります — GradleのBuildConfigフィールドとproductFlavors。
  • パフォーマンス — 条件付きコンパイルは、ランタイムフラグとは異なり、リリースバイナリに痕跡を残しません。

Active Compilation Conditionsとは

Active Compilation Conditionsは、ビルド時にアクティブなプリプロセッサディレクティブのセットを決定するコンパイルフラグです。ランタイムフラグ(if (isDebug)チェック)とは異なり、コンパイル条件はバイナリファイルから非アクティブなコードを物理的に除外するため、パフォーマンスが向上し、アプリケーションのサイズが削減されます。

このメカニズムはプリプロセッサまたはコンパイルの初期段階で動作します。コンパイラはアクティブな名前のリストを受け取り、#if NAMEディレクティブに遭遇すると、NAMEがそのリストにあるかどうかを確認します。名前が存在しない場合、ブロック内のコードは無視され、コンパイルされません。

Swift.org Blog(2025)によると、ランタイムフラグの代わりにActive Compilation Conditionsを使用すると、ログ記録とデバッグツールが充実したプロジェクトでは、リリースバイナリのサイズが平均12〜18%削減されます。これは、インストールファイルサイズに制限があるモバイルアプリケーションにとって特に重要です。

C / C ++ プリプロセッサレベルの条件付きコンパイルとの主な違いは、SwiftとKotlinのActive Compilation Conditionsが、テキスト置換レベルではなく、コンパイラのAST(抽象構文木)レベルで動作することです。これにより、より安全で予測可能になります。非アクティブな#ifブランチの構文エラーは、パース中に検出され、実行時に現れることはありません。

もう1つの重要な違いは、Swiftでは条件#if os(iOS) || os(macOS)がコンパイル時にチェックされ、プリプロセッサマクロではなくプラットフォーム名で動作することです。これにより、C / C ++ プリプロセッサで発生する可能性のある、#defineによる誤ったテキスト挿入に関連するバグのクラス全体が排除されます。Swiftコンパイラは置換されたテキストではなくASTを認識するため、条件付きコンパイルのデバッグが大幅に容易になります。

SwiftのActive Compilation Conditions

Swiftは#ifディレクティブを通じてActive Compilation Conditionsをサポートしており、論理演算子&&||!で組み合わせたフラグ名のリストを受け入れます。コンパイラは、条件がtrueの場合にのみ#if ... #endif内のコードを含めます。

Swiftの組み込み条件

Swiftにはいくつかの組み込み条件があります。DEBUG(デバッグビルドで自動的にアクティブ)、swift(>=5.0)(コンパイラバージョンチェック)、canImport(UIKit)(モジュールの利用可能性チェック)、targetEnvironment(simulator)(環境チェック)です。これらの条件は追加の設定を必要としません。

swift
// Swiftの組み込み条件
#if DEBUG
    print("デバッグビルド — ログ記録アクティブ")
#endif

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

Xcodeのカスタムフラグ

開発者は、XcodeのBuild Setting OTHER_SWIFT_FLAGSを介して独自のフラグを追加できます。フラグはプレフィックス-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システム、productFlavors、build.gradle.ktsのフラグを通じて実装されています。Kotlinには言語レベルで#ifディレクティブの直接的な同等物はありませんが、代替メカニズムを提供しています。

BuildConfigフィールドをフラグとして

最も一般的な方法は、各フラグにbuildConfigFieldを追加することです。buildConfigField("boolean", "BETA", "true")。これらのフィールドは、各Build Variantごとに個別にBuildConfigクラスに生成されます。DEBUGフィールドは組み込み済みで、デバッグビルドでは自動的にtrueになります。

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ディレクトリを作成できます。たとえば、src/demo/src/full/です。異なるsourceSetsの同じ名前のクラスは、対応するフレーバーのビルド時に相互に置き換わります。これはフラグよりも強力なメカニズムであり、クラス全体をオーバーライドできます。

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は、主に4つのシナリオで使用されます。デバッグ(ログ、インスペクタ)、A/Bテスト(機能フラグ)、プラットフォーム適応(iOS/macOS共有コード)、ライセンス(無料版/有料版)です。

デバッグログ

最も一般的なシナリオは、条件付きログ記録です。デバッグビルドでは、すべてのログがコンソールに書き込まれます。リリースビルドでは、何も記録されません。#if DEBUGまたはBuildConfig.DEBUGを使用すると、リリースバイナリにインライン化されたものでも、ロガーの呼び出しが1つも含まれていないことが保証されます。

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

ビルド時の機能フラグ

新しい機能がまだ本番環境の準備ができていないが、コードにすでに存在する場合は、コンパイルフラグの背後に隠すことができます。ランタイム機能フラグとは異なり、コンパイルフラグはチェックでアプリケーションに負荷をかけず、ユーザーが有効にすることもできません。

  • 新機能 — コードを削除せずに、次のリリースまで未完成の機能を非表示にする
  • 分析 — ベータテスターのみに追加のメトリクス収集を有効にする
  • サードパーティSDK — アプリケーションの無料版から重いライブラリを除外する
  • UIコンポーネント — ステージングビルドでのみ実験的な画面を表示する

ベストプラクティス

Active Compilation Conditionsは控えめに使用する必要があります。フラグが多すぎると、コードが理解しにくくなります。開発者は、どのブランチが現時点でコンパイルされるかを確信できません。各フラグはREADMEまたは専用のCONFIG.mdファイルに文書化することをお勧めします。

分散チームを持つ大規模プロジェクトでは、CIでの自動フラグ検証を実装することが有用です。各プルリクエストは、Active Compilation Conditionsの可能なすべての組み合わせでビルドを通過する必要があります。これにより、非アクティブなフラグの下のコードがリファクタリングによって壊れておらず、リリースまで条件付きコンパイルブランチがテストされないままになっていないことが保証されます。xcresulttool(iOS用)やGradle Build Scan(Android用)などのツールは、このプロセスを自動化するのに役立ちます。

  • 最小限のフラグ — プロジェクトあたり5〜7個以下のアクティブな条件。各フラグは複雑性のポイントです。
  • 命名規則 — すべてのフラグは大文字で、プロジェクトのプレフィックスを付けます:MYAPP_BETA、MYAPP_ANALYTICS。
  • コードレビュー — #ifまたはbuildConfigFieldの追加はすべて、個別のレビューを通過する必要があります。
  • テスト — CIは少なくとも1日1回、すべての可能なフラグの組み合わせをビルドする必要があります。

よくある質問

Swiftの#if DEBUGとif(isDebug)の違いは何ですか?

#if DEBUGはコンパイルディレクティブです。DEBUGがアクティブでない場合、ブロック内のコードはバイナリに含まれません。if (isDebug)はランタイムチェックです。コードは常にコンパイルされ、条件は実行時にチェックされます。#ifはリリースビルドに痕跡を残しません。

Xcodeでカスタムフラグを追加するにはどうすればいいですか?

プロジェクトのBuild Settingsで、Other Swift Flags(OTHER_SWIFT_FLAGS)を見つけ、フラグを指定して新しい行を追加します:-DMY_FLAG。フラグは#if MY_FLAGディレクティブから認識できるようになります。Debug構成とRelease構成で異なるフラグを設定できます。

Swift #ifに相当するKotlinの機能はありますか?

Kotlin/JVMには直接的な同等物はありません。代わりに、BuildConfigフィールドが使用されます(ランタイムチェックですが、ProGuardが未使用コードを削除する可能性があります)。Kotlin Multiplatformでは、宣言レベルでexpect/actualディレクティブがあります。

1つの#ifで複数のフラグを組み合わせられますか?

はい、Swiftは論理演算子をサポートしています。#if DEBUG && BETA#if os(iOS) || os(tvOS)#if !RELEASE。複雑なロジックの場合は、条件を括弧でグループ化できます。ANDとORは標準的なショートサーキットルールで動作します。

SwiftUIプレビューで#if DEBUGが機能しないのはなぜですか?

SwiftUIプレビューは、メインターゲットとは異なるフラグを持つ別のプロセスでビルドされます。DEBUGがアクティブでない可能性があります。解決策:プレビューコードにはtargetEnvironment(simulator)を使用するか、条件付きロジックを別のメソッドに抽出します。

まとめ

  • Active Compilation Conditions — ランタイムチェックなしでバイナリから非アクティブなコードを物理的に除外するコンパイルフラグ。
  • Swiftは組み込み条件(DEBUG、os、canImport)とOTHER_SWIFT_FLAGSを介したカスタムフラグで#ifをサポートします。
  • AndroidとKotlinはBuildConfigフィールド、productFlavors、KMPのexpect/actualメカニズムを使用します。
  • パフォーマンス — 条件付きコンパイルにより、ログ記録が充実したプロジェクトではバイナリサイズが12〜18%削減されます。
  • 機能フラグはコンパイル時にアプリケーションにチェックの負荷をかけず、ユーザーが有効にすることもできません。
  • 推奨事項 — プロジェクトあたり5〜7個以下のフラグ、プレフィックス付きの命名規則、CIでのすべての組み合わせの必須テスト。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください