[AS3 / ANE] Dropbox Sync APIのiOSのANEを作ろうとしてplatform.xmlでハマったところ

2014/03/18

こんにちは。きんくまです。

仕事で、ANE作りは何個か作ったことがあってなんとなくわかったつもりだったんだけど、やっぱりわかってなくてすごく時間がかかった件についてです。
ANE作っている人はネットで検索してもあんまりいないけど、作る人は情報が合った方が助かると思うので書きます。

Dropbox Snyc APIのANEを作ろうとしたときのことです。

>> iOS Sync API – Dropbox

こういう外部のライブラリを使うときは、adtコマンドに組み込むplatform-options.xmlみたいなxmlを作る必要があります。

>> ネイティブライブラリの構築

細かい説明に入る前に、コンパイル、リンクなどを前に買ってあった入門書などで読み直してみました。

>> 猫でもわかるC++プログラミング 第2版 (猫でもわかるプログラミング) [単行本]
>> ふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道 [単行本]

実行ファイルができるまで

1. ソースファイル(例えば.c)をマシン語に変換
-> オブジェクトファイル(.o)ができる

2. ただ1でできたオブジェクトファイルはライブラリの部分(文字入出力など、そのプログラム上で使っているライブラリ)がマシン語に変換されていない状態
(UIKitとかもライブラリというかフレームワークというかとにかく外部のプログラム)

3. なので、マシン語に変換済みのライブラリのオブジェクトファイルと1のオブジェクトファイルを結合する必要がある。 -> リンカで行う(リンク作業)

4. リンク済みなので、実行可能なプログラムのできあがり!

という感じの流れです。

ライブラリとのリンクの種類

大きく分けて、静的リンク(static link)と動的リンク(dynamic link)の2種類がある。
(ふつうのlinuxの本にはdynamic loadというのもあったけどここでは置いておく)

静的リンクは、リンク時にライブラリのオブジェクトを自分のプログラムに埋め込む。
-> だからプログラムの大きさはライブラリの分増える

動的リンクは、リンク時にはライブラリのオブジェクトは埋め込まず、実行時に読み込む命令だけを書いておく
-> ほとんどかわらない大きさ

動的リンクはプログラムに埋め込まないので、実行時にそのライブラリが読み込める状態にしておく必要がある

platform optionsの設定

というのをふまえてplatform optionsの各値の説明を見てみる

linkerOptions

この方法でリンクされた依存関係は、ネイティブ拡張をネイティブ拡張自体とは別に使用する開発者に配布される必要があります。これは、iOS に含まれる追加のライブラリを使用する際に最も便利な方法ですが、AIR ではデフォルトではリンクされません。このオプションを使用して、別に提供する静的ライブラリに開発者がリンクできるようにすることもできます。

ANEを作ってもANEの中にはライブラリは埋め込まれないです。動的か静的かはライブラリによると思う、、。(不確か、、)
最終的にAIRのコンパイル時に、静的ライブラリは埋め込まれると思われ。(ここもたぶん、、すんません!!)

packagedDependencies

パッケージ化された依存関係は、.a、.framework または .o のいずれかの拡張子を持つ静的ライブラリである必要があります。ライブラリをデバイス上で使用するには、ライブラリが ARMv7 アーキテクチャをサポートする必要があり、iOS シミュレーターと共に使用するには、i386 アーキテクチャをサポートする必要があります。

と書いてあって、こっちは静的リンクです。ANEを作ったら中に埋め込まれます。
ためしにadtでaneを作ったあと、拡張子をane -> zipにして中をみていくと、ライブラリが見つかりました。

それをふまえてDropbox Syncのplat form optionsを考える

説明ページによると、Sync APIはいくつかライブラリを使う必要がある

・CFNetwork.framework
・Security.framework
・SystemConfiguration.framework
・QuartzCore.framework
・libc++.dylib

で、linkerOptionsのところに、<option>-framework CFNetwork</option>とかって書いていく必要があるのかなって思ったのだけど、adobeの説明文ではいくつかデフォルトでリンクされるやつがあるから大丈夫と書いてあった。

そうすると書く必要があるのは、libc++.dylibだけとわかった。optionに書くときはlibc++だったらlibc++->lc++ とibを抜かして書くので、-lc++と書く必要がある。
それで、できたios_options.xmlはこんな感じになった。
libc++はFinderからひっぱってきてどこかに置く必要はなかったです。

<platform xmlns="http://ns.adobe.com/air/extension/4.0">
    <sdkVersion>5.0.0</sdkVersion>
    <linkerOptions>
	    <option>-ios_version_min 5.0</option>
	    <option>-lc++</option>
        <option>-liconv</option>
    </linkerOptions>
    <packagedDependencies>
    	<packagedDependency>iosLib/Dropbox.framework</packagedDependency>
    </packagedDependencies>
</platform>

packagedDependencyの中のiosLibというフォルダは自分で作ったものです。

adtのコマンドはこんな感じになった。${xxx}とか書いてあるのは、これはaneを作るときのシェルスクリプトの一部だからです。
なのでその部分は変数で、その前にxxx=”foo”とか書いておくと${xxx}が実行時にfooと置き換わるのです。
あと各行末の\は、改行を無効化するために書いてあります。この\をとっぱらって1行でつなげて書いても動きます。でもそうやって書くと、みづらいので\をつけて書いています。

adt -package \
-target ane ${ANEName} extension.xml \
-swc ${ASLibSwcName} \
-platform iPhone-ARM \
  -platformoptions ios_options.xml \
  iosLib/Dropbox.framework \
  -C ${iOSDir} . \
-platform iPhone-x86 \
  -C ${iOSSimDir} . \
-platform default \
  -C default . 

ちなみに、これを作るときにXCode側でこれ用の静的ライブラリ(.aファイル)を作る必要がある。で、そのときのライブラリの設定はlibc++は抜かしておくみたい。
いれてたら、「それ動的ライブラリだから静的ライブラリにひもづけられないよ」という警告がでたのではずしました。

dropbox_xcode_fig1

とりあえずiOS側はなんとかなりそうなんだけど、Android側がなー、、、。

LINEで送る
Pocket

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る