みなさん、姉(ANE)ってますか?
さて、aneファイルを制作するときにADTを使用してパッケージングを行うことはご存知かと思いますが、その際にコンパイル環境の構築の仕方に困惑したことがあると思います。主に、「SWCを用意して、そのSWFを取り出して、なんか両方必要らしいから、library.swfを全プラットフォームにコピーして、ADTに両方関連させて」のところです。この手順がややこしい上になかなか説明もややこしく、非常にあいまいな状態なので「なんでこんな抽出手順が必要なんだろう?SWCがあるんだから、そこだけでやればいいじゃない」という疑問を抱くことは当然です。
というわけで、今回はそんな話を自分的に纏めたいと思います。最後には、前回の疑問だった「なんでdefaultプラットフォームという名前が使われているのか」の答えも出てきます。
なお、今回の話は、有川さんのADCの記事を一度目を通しておいたほうがいいかと思います。この記事の「何故swcからlibrary.swfを抽出して全platformフォルダに入れるか」を考えてみたいと思います。
ネイティブ拡張(Native Extensions)入門
第3回 ネイティブ拡張の開発方法 後編
http://www.adobe.com/jp/joc/devnet/air/articles/native_extensions_part3.html
まずは
Adobe公式ドキュメントから抜粋した、下記の文章を見てみましょう。これが一番コンパクトにまとまっているかと思います。
ネイティブ拡張をパッケージ化する際には、SWC ファイルと個別の library.swf ファイルの両方が必要になります。library.swf ファイルは SWC ファイルから抽出します。SWC ファイルには、オーサリングとコンパイルのための ActionScript 定義が含まれています。library.swf には、特定のプラットフォームで使用される ActionScript 実装が含まれています。拡張のターゲットプラットフォームごとに別々の ActionScript 実装が必要な場合は、複数の SWC ライブラリを作成し、プラットフォームごとに個別に library.swf を抽出します。ただし、ベストプラクティスは、すべての ActionScript 実装で同じパブリックインターフェイスを使用することです(ANE パッケージに含めることのできる SWC ファイルは 1 つだけです)。
http://help.adobe.com/ja_JP/air/extensions/WS99209310cacd98cc2d13931c1300f2c84c7-8000.html
さて、ではこれで意味がわかるかというと、なかなか判らないですね。「パッケージ化にはANE-SWCと、その中身のANE-SWFが必要(ANE-SWF はANE-SWCを解凍して抽出する)」っていうことくらいは、参考サイトとかでレクチャーされてるので判ると思いますが。
では
ここから解説に入りますが、その前に。SWCからlibrary.swfを抽出とかしてコンパイルとかそういう手順は一旦忘れましょう。このlibrary.swfはどれを指すのかとか、絶対混乱するので。
さて、こんな図を作ってみました。多分厳密に言うと、これはADLによるデバッグ時の図になるかと思いますが、まぁそれは置いておいて。あ、図が致命的にダサいのは勘弁してください。

はい。SWCとlibrary.swfでは、明確に役割が違います。先ほどのドキュメント抜粋の文で書くと、
- SWC・・・オーサリングとコンパイルのための ActionScript 定義
- library.swf・・・特定のプラットフォームで使用される ActionScript 実装
となります。SWCはいわば「パブリックインターフェイス」の役割を持っていて、AIRアプリのオーサリング時とコンパイル時に使用されます。その「パブリックインターフェイス」を通じて、実装部分である各プラットフォームのlibrary.swfを読みに行くわけです。ここらへんはAS3のインターフェイスクラスと通常の実装クラスを想像すればいいかと。
さて、ここからは、図にあるSWCは「コンパイル用SWC」、library.swfは「実装library.swf」と書きます。
では本題。
「何故コンパイル用SWCから実装library.swfを取り出して、そのプラットフォームに配置して云々っていうことを行うか」ということですが。だって、どうせSWCの中身とlibrary.swfが同じであれば、わざわざそんなことする必要ないですよね。SWCだけ指定して、ADTがそこらへん勝手にやってくれればいい。そしたら、SWCだけ作って指定すればいいから楽!
実は、必ずしもlibrary.swfは全プラットフォームで同じというわけではないのです。
はい、まずドキュメントのこの部分を見てみましょう。
拡張のターゲットプラットフォームごとに別々の ActionScript 実装が必要な場合は、複数の SWC ライブラリを作成し、プラットフォームごとに個別に library.swf を抽出します。
どういうことか。つまり、一般的な手法として解説されている「コンパイル用SWC」から必ずしもlibrary.swfを抜きだす必要はなく、「コンパイル用SWCはそのままに、別途実装用SWCを作って、そっちの実装用library.swfを抽出して配置してもいい」わけです。それぞれのプラットフォームに合った実装が出来るよー、というわけですね。
ただし、
ただし、ベストプラクティスは、すべての ActionScript 実装で同じパブリックインターフェイスを使用することです(ANE パッケージに含めることのできる SWC ファイルは 1 つだけです)。
という文にも注意です。つまり、「実装を別々に作ってもらってもいいけど、その実装はSWCファイルで設定してあるパブリックインターフェイスの内容に沿った実装を行うべきだよね」ということだと思います。SWCではgetHelloWorld()だけ定義してるのに、とあるプラットフォームの実装にはsetHelloWorld() が定義されているとかはNGってことではないかと。あとパッケージ名が違うとかクラス名が違うとかもNGかと思います。
まぁそんなわけで、「折角、他から抽出したlibrary.swfでも使えるような仕組みになってるんだから、「コンパイル用SWCだけでいいじゃん」とか横着せずに、それぞれのプラットフォームに適切なlibrary.swfを置いてくださいね」ということでした。
では、何故
一般的な解説サイトでは、コンパイル用SWCから実装library.swfを抜き出して全プラットフォームに配置するのでしょう?先ほどの話からいえば、コンパイル用ならコンパイル用、実装用なら実装用で分けた方が役割分担が出来てて判りやすいですよね。
まず、コンパイル用SWCの方は先ほども書いたとおり「パブリックインターフェイス」なので、どんな実装をされていようが問題ありません。予想では、どんなパッケージのどんなクラスにどのようなメソッドを定義しているかとか、そういう情報さえあればいいということになるかと思います。
んで、各プラットフォームのlibrary.swfは実装ファイルとなるので、ExtensionContext.call()なりフォールバックなり、ちゃんと実装された内容を記述してるものである必要がありますね。
ということは、前回の記事のように普通にコンパイル用SWCに定義と実装がされていれば、同じファイル(コンパイル用SWCと、それに由来する実装library.swf)を使っても大丈夫、ということに気付くと思います。しかも、同じパッケージ、同じクラス、同じメソッドを必ず実装出来てるので、仕様が統一化できるわけですね。
まぁあと、いちいちプラットフォーム毎に実装分ける必要があるのか、っていうのも疑問ではありますが。それすらもコンパイル用SWCの方でCapabilities.OSによる切り替えとかやればいいわけで。
よく判らん方は、最初の図を見ながら読んでみると、判りやすいかもしれません。
Defaultプラットフォームとはなんだったのか
ここまで読めば、なんとなく予想がつくでしょう。つまり、用意しているプラットフォームの何処にも属さなかった場合、defaultとして指定された実装library.swfファイルを読みに行く、ということになります。で、これがコンパイル用SWCから抽出されている場合、コンパイルSWC作成時にOSで処理を分けてフォールバックを行う作りをしておけば、defaultプラットフォームの時はそのフォールバックが機能しますよ、っていうことですね。なので、「プラットフォーム」という言葉の意味合いは確かに妥当ですし、コンパイル用SWCでフォールバックを行うことも妥当でした。この二つの意味に気付いてやっと、defaultプラットフォームの真意が判る感じですね。
あ、ちなみに
library.swfという名前ですが、変えたらだめです。固定です。
というわけで
なんかグダグダと書いてきて、正直判らない人がたくさんいるのではないかと思いますので、そんな人は、Adobe公式ドキュメントの「ネイティブ拡張のパッケージ化」の部分を熟読しましょう。
ANEttyではどうなっているか
コンパイル用SWCから実装library.swfを自動抽出して全てのプラットフォームで同じ実装をするようにしています。まぁ正直、途中でも書いたようにプラットフォーム毎に実装をバラバラにする意味はあんまりないかなーと思いますので、このままで行きたいと。どうしてもバラバラの実装をしたい方は、コンパイル環境一式を書き出したうえで、それをベースに各自作っていただく方式にしたいと思います。
で、結局何が書きたかったかというと、コンパイルSWCだけで済むから楽だよ!っていう宣伝でした。