はじめに
Swift歴5ヶ月の新米プログラマーのメモ。
コンパイルディレクティブとは
プログラミングにおいて、
コンパイル1は、プログラミング言語(高水準言語)で書かれたプログラムを、それより低水準な言語や、コンピューターが理解できる言語(機械語)に変換すること。
また、コンパイルするソフトウェアのことを、コンパイラーと呼ぶ。
ディレクティブ2は、コンパイル時にコンパイラーに指示や命令をするために、プログラム中に記述される要素のこと。
つまり、そのコンパイル時に特定の処理を行わせるための指示・命令をするために使用するのが、コンパイルディレクティブである。
コンパイルディレクティブの種類
Swiftで使用可能なコンパイルディレクティブは、主に以下の3つにカテゴライズがある。
- 条件付きコンパイル
- デバッグ・エラー処理
- メタ情報
その他、カスタムコンパイルフラグを作ることもできる。
1. 条件付きコンパイル
その名の通り、条件に応じてコンパイルするかどうかを決めるために使うもの。
#if
, #else
, #elseif
, #endif
の4つと、制御したい条件のコンパイルフラグを使って記述する。
#if DEBUG
#if DEBUG
print("デバッグ用")
#else
print("リリース用")
#endif
ビルドごとに異なるコードを実行したいときに使うコンパイルディレクティブ。
#if os()
#if os(macOS)
print("macOS用")
#elseif os(iOS)
print("iOS用")
#elseif os(watchOS)
print("watchOS用")
#elseif os(tvOS)
print("tvOS用")
#elseif os(visionOS)
print("visionOS用")
#elseif os(Linux)
print("Linux用")
#elseif os(Windows)
print("Windows用")
#endif
プラットフォームごとに異なるコードを実行したいときに使うコンパイルディレクティブ。
#if arch()
#if arch(i386)
print("32ビットのx86アーキテクチャ")
#elseif arch(x86_64)
print("64ビットアーキテクチャ")
#elseif arch(arm)
print("RISCアーキテクチャ")
#elseif arch(arm64)
print("ARM64アーキテクチャ")
#endif
CPUアーキテクチャごとに異なるコードを実行したいときに使うコンパイルディレクティブ。
#if swift()
#if swift(>=4.2)
print("Swift 4.2以降")
#endif
特定のSwiftのバージョンでのみコンパイルしたいときに使うコンパイルディレクティブ。
#if compiler()
#if compiler(>=5)
print("コンパイラー 5以降")
#endif
#if canImport(UIKit)
import UIKit
print("UIKitが利用可能")
#endif
特定のSwiftコンパイラーのバージョンでのみコンパイルしたいときに使うコンパイルディレクティブ。
#if targetEnvironment()
#if targetEnvironment(simulator)
print("シミュレータで実行")
#elseif targetEnvironment(macCatalyst)
print("macCatalystで実行")
#else
print("実機で実行")
#endif
シュミレーターや実機で異なるコードを実行したいときに使うコンパイルディレクティブ。
#if available()
if #available(iOS 15, *) {
print("iOS15以降でのみ実行")
}
特定のバージョンのOSでのみ実行されるコードを書くために使うコンパイルディレクティブ。
2. デバッグ・エラー処理
Swift 5.9以降での変更
Swift 5.9から、#warning
や#error
といったコンパイルディレクティブの機能が、新しいマクロとして提供されるようになったため、将来的にはマクロ方式(warning(_:)
やerror(_:)
)に移行していくことが推奨される可能性がある。
下記、新しいマクロ方式のドキュメント
warning(_:) error(_:)
#warning
, #error
#warning("警告")
#error("エラー")
コンパイル時に警告やエラーを表示させるために使うもの。
3. メタ情報
コード内でファイル名や関数名などの情報を取得したり、メソッドやプロパティを指定するために使うもの。
#file
, #line
, #function
print("ファイル名:\(#file)")
print("行番号:\(#line)")
print("関数名:\(#function)")
現在のソースコードのファイル名、行番号、関数名などを取得したい時に使うコンパイルディレクティブ。
#sourceLocation
#sourceLocation(file: "CompileDirective.swift", line: 10)
#sourceLocation()
そのコードが書かれている行番号とファイル名とは異なる行番号とファイル名に偽装したい時に使うコンパイルディレクティブ。
参考