Swift や Objective-C のフレームワークは Clang モジュールをベースとした同じモジュールシステムを共有しています。ライブラリのインターフェースとやりとりすることでヘッダファイルを置き換えますが、それぞれにエッジケースが存在します。Clang モジュールの
#import
文の置き換え方、モジュールを使うことによる影響、Clagnモジュールの設計がSwiftのライブラリにどう影響してきたかを調べてみます。
Clang モジュールの探検
おはようございます
Clang モジュールをみていきます
Squareのモバイルエクスペリエンスチームでデベロッパーが楽しく精算的に仕事をできるようにするのが仕事です
モジュールの前はヘッダがありました
ヘッダーをインポートすると利用できます
Cは単一ファイルの言語です Cプロセッサがヘッダサーチパスにあるものを見つけて#includeからコンテンツをペーストする
マクロが関与するとヘッダのincludeの順番で変化が生じる
相互に矛盾する関数の宣言が起きたらどうなるでしょう
include ガードという仕組みで問題を回避しています
Objective-Cでは状況が良くなります。
importがあるおかげで
2回めにでてきた#imortはincludeしないのでぶつからない
コンパイラはインポートしたものの意味論的理解を深めます ヘッダからテキストでコピーするのではなく、モジュールで意味的なコンテンツにアクセスすることができます。
プリコンパイルヘッダに変わる働きをします
このために頻繁にクリーンビルドする必要がありました
モジュールのヘッダ、構成、依存性などを教えてくれるのでモジュールにモジュールマップがあれば透過的なモジュールのインポートマップに変換される
.frameworkをみていきましょう
標準的なモジュールマップでビルドするとXcodeが生成するものです
名前の付いたモジュールを宣言しています
モジュールないすべてのヘッダファイルをインポートしてそれを出力します
最後にモジュールはUsefulFrameworkをインポートできるようになります ファイルがモジュールのどのパーツに依存しているのか明確になります
UsefulFrameworkがSwiftでもObjCでも利用できるようになりました
私のフラストレーションは何か
SwiftStaticLibraryをCocoaPodsライブラリで利用できるようにしたい
モジュールはFrameworkを想定していますがユーザーの作るライブラリは後付でデザインされている
課題です
こういったところが痛みでした
ディレクトリの中のヘッダをすべて利用したい
CocoaPodsがパブリックヘッダを直接渡してくれる わざわざカスタムUnbrellaヘッダを作らなくて良い
Explicit Submodules これはGitSubmoduleよりマシです
セミプライベートファンクショナリティがあるがメインインターフェースには入らない
他のモジュールからはインポートされない CocoaPodsにAddしようとしたがうまくいかなかった。もとに戻すこともできなかった マクロがある場合
textualでやればいいのかなと考えましたが ファイルにマクロが定義されて、Assertと言うかたちで定義されていればつかえる
いくつかのフィーチャーを指定してモジュールからコンパイラをサポートできるようにします ObjCやC++の幾つかのバージョンで
こうして隠す事ができます
互換性がないことも表現できます
カバーするヘッダはモジュールの一部として扱われます
私が考える一番の文句をとっておきました
回避する方法が見つかっていません
モジュールマップがストアされたディレクトリに関連するものとして扱われます。モジュールマップでもフラグでも、他のディレクトリを使うように支持できないのです。絶対パスか同じディレクトリに入れておく必要があります
これによってCocoaPodsでフラストレーションが
任意のディレクトリのヘッダに対応させたい時に、できない。
Clangはフレームワークバンドル内に発見されたヘッダとプライベートのディレクトリに特別な扱いをしている気がします。
ここからみなさん聴きたいことではないでしょうか
ClangモジュールはSwiftがObjCのヘッダをインポートするのをサポートします
import Foundationが機能するわけです。
他にも方法があります。ブリッジングヘッダなどの方法です。 みなさん、モジュールはヘッダを解決するだけなのかと思うと思います
Swiftのよいところはヘッダがないところだと思います Swiftとモジュールはどのような関係にあるのでしょうか
@objecと書かれたすべてのヘッダ SwiftのXcodeのフレームワーク、 Swiftコンパイラに渡してヘッダの生成を矯正することができます。 コンパイラはバイナリSwiftファイルをどう扱えばいいのか分かっています モジュールが同じ名前だったら Objective-CとSwiftの中のファイルなら可能ということです。
Mixed Framework
モジュールマップを拡張
そして.mのコンパイル
自動で構築されます
Static Libraryを構築するには手作業が必要
Static LibraryでCocoaPodsをサポートするのに必要
Clangモジュールについて知りたければご参照下さい
思い通りに動かない、記述が不十分ならソースを見ます
requires objc_arc, blocks なんてのも書けるのか #tryswiftconf
— いけしょー@本書きました (@ikesyo) 2018年3月1日
modulemap何者だ、と思ってたけどだいぶ勉強になった #tryswiftconf
— ぎぎにゃーん (@giginet) 2018年3月1日
こんなマニアックな話できるようになりたいなー#tryswiftconf
— ありぜ (@a_aryzae) 2018年3月1日