Package Manager C/C++ Language Standard Support
01 何が問題だったのか
Swift Package Manager では C/C++ のターゲットもビルドできますが、C/C++ のコンパイルにおいては どの言語標準(C89, C99, C11, C++98, C++11, C++14 など)を使うか の指定が非常に重要です。言語標準が違えば使える構文やライブラリ機能が変わり、同じソースでもコンパイルが通ったり通らなかったりします。
しかし従来の SwiftPM の Package.swift には、C や C++ の言語標準を指定する仕組みがありませんでした。そのため、特定の C++ バージョン(たとえば C++11 以降)を前提に書かれた C/C++ ソースを含むパッケージを、SwiftPM だけで素直にビルドすることができません。
本来はより汎用的な build settings 機能によってこの種の設定を扱うことが想定されていましたが、その機能は Swift 4 のスコープから外されました。そこで、build settings が入るまでのつなぎとして、C/C++ の言語標準だけでも先に指定できるようにする ことが求められました。
02 どのように解決されるのか
Package.swift の Package イニシャライザに、C 用と C++ 用の言語標準を指定するための二つのパラメータ cLanguageStandard と cxxLanguageStandard が追加されました。どちらもパッケージ全体の C/C++ ターゲットに一括で適用される設定です。
使い方
たとえば C++11 を標準として使いたい場合、次のように書きます。
let package = Package(
name: "CHTTP",
// ...
cLanguageStandard: .c89,
cxxLanguageStandard: .cxx11
)
既定値はどちらも nil で、何も指定しなければ従来どおり言語標準フラグを付けずにコンパイラが呼び出されます。既存のパッケージの挙動は変わりません。
指定できる言語標準
CLanguageStandard と CXXLanguageStandard は enum として定義されていて、Clang がサポートする標準名がそのまま列挙されています。
public enum CLanguageStandard {
case c89
case c90
case iso9899_1990
case iso9899_199409
case gnu89
case gnu90
case c99
case iso9899_1999
case gnu99
case c11
case iso9899_2011
case gnu11
}
public enum CXXLanguageStandard {
case cxx98
case cxx03
case gnucxx98
case gnucxx03
case cxx11
case gnucxx11
case cxx14
case gnucxx14
case cxx1z
case gnucxx1z
}
cxx1z は当時の C++17 ドラフト(-std=c++1z)に相当し、GNU 拡張付きのバリアントには gnu プレフィックスが付きます。これらの列挙子は Clang 側の対応状況に合わせて今後も更新されます。
今後の位置づけ
この API はあくまで本格的な build settings 機能が入るまでの暫定的な手段として導入されたものであり、将来 build settings が利用可能になった時点で cLanguageStandard / cxxLanguageStandard プロパティは deprecated にする予定であるとされています。