Introduction
以前、C言語ライブラリを使うにはCoreFoundationをimportすれば良いと書いたが、これはSwift 3.0.xまでの話だったらしい。usr/lib/swift/CoreFoundation/module.modulemap が変更されたためである。
Swift 3.0.x以下
module CoreFoundation [extern_c] [system] {
umbrella header "CoreFoundation.h"
explicit module CFPlugInCOM { header "CFPlugInCOM.h" }
export *
module * {
export *
}
}
Swift 3.1以上
module CoreFoundation [extern_c] [system] {
umbrella header "CoreFoundation.h"
explicit module CFPlugInCOM { header "CFPlugInCOM.h" }
}
Method / Result
Foundation
というわけでimport方法を変更する必要があるのだが、Universalなやり方をなるべくなら使いたいもの。
Swift 3.0以上であればFoundationが使えるようだ。
import Foundation
ただし、Swift 2.xを考慮するなら分岐が必要(3.0はCoreFoundationも使えるので、以下では3.1としてある)。
#if swift(>=3.1)
import Foundation
#else
import CoreFoundation
#endif
ただ、Swiftはライブラリ依存がただでさえ激しいようなので(so.*が違うのをsymlinkを張り替えて解決する例が散見される)、同じ分岐を要するならライブラリ依存を減らす方向にしたい。
_runtime
DarwinとGlibcの別だけで良ければ、_runtimeを使うのが簡便か。
定義は https://github.com/apple/swift/blob/swift-4.2-branch/lib/Basic/LangOptions.cpp#L261 にある。
#if _runtime(_ObjC)
import Darwin
#else
import Glibc
#endif
os
https://github.com/apple/swift/blob/swift-4.2-branch/lib/Basic/LangOptions.cpp#L29 によると、OSX, tvOS, watchOS, iOS
などが識別子として使えるらしい(4.2の段階では他に、Linux, FreeBSD, Windows, Android, PS4, Cygwin, Haiku
)。Swift 3.1以降はmacOSがOSXの別名として使えるようだ。
#if os(OSX)||os(tvOS)||os(watchOS)||os(iOS)
import Darwin
#elseif os(Windows)
import MinGWCrt
#else
import Glibc
#endif
canImport
Swift 4.1以降であればcanImport statementが使えるようだ。実は上のWindowsはSwiftForWindows派生版を対象にしていて、純正版では正しくインポートできない(純正版はまだバイナリリリースがないのである意味しかたない)のだが、その問題も含めてまとめて解決できる。
ただ、4.1未満を切り捨てることにはなってしまう(swift(>=4.1)
の場合だけcanImport節を読むと言ったことはできない)。
#if canImport(Darwin)
import Darwin
#elseif canImport(MinGWCrt)
import MinGWCrt
#elseif canImport(MSVCRT)
import MSVCRT
#else
import Glibc
#endif