要するに「自分でビルドしてスタティックリンクしろ」だけなんですけどね……。以下の件の続き(解決編)です。
ソースコードビューア GlassDolphin for iPad/iPhone 本当に完成!(しかしreject) - tagomorisのメモ置き場
iOS SDKに入ってるのに使うと意味不明なrejectメールで怒られる libarchive ですが、結局どうしたかというと、以下のようにしました。
- libarchive および(それが依存する) bzlib をダウンロードして展開
- libarchive は configure も実行
- Xcodeで新規プロジェクトを作成し、そこに libarchive/bzlib を取り込んでビルド
- i386(Simulator)およびarmv7(Device)の両方でビルド
- コマンドで結合してユニバーサルバイナリ化
- これやんないと、アプリ側のシミュレータ/実機の両方で動くバイナリにならない
- 使用するプロジェクトの側で取り込む
こんな感じ。手順は後で詳述。上記エントリのコメント欄で「移植とかしなくてもそのままビルドすればいけるかも?」というコメントをいただきましたし、Twitterでも英語で「シンボル名だけ変えてコンパイルし直せばいけるんじゃない?」みたいなことが書いてあるリンク先を紹介していただいたりしました。
正直、真相がどうなのかはよくわかりませんが、今回は元のライブラリのコードには一切手を入れず、呼び出し側も変えることなく、ビルドし直してリンクの仕方を変えるだけでAppStoreの機械式チェックは通るようになりました。
可能性としては以下のどれかみたいな感じかなーと思います。
- Appleは使われたときにチェックできるよう、SDKには特殊な目印のついたシンボルのダイナミックリンクライブラリを添付していた
- ダイナミックリンクライブラリとしてビルドしてたら自前でもダメだった
- 「SDKのダイナミックリンクライブラリにリンク」しているのを検出する他の方法がなにかある
ちなみに最初はSDKに含まれる libarchive2.6.2.dylib をリンクしてましたが、いちおう他のもの(バージョン番号が省略されたもの)も試しました。ダメでした。
iOSアプリ用にlibarchiveをビルドする手順
他のライブラリでもほぼ同じように行けるんじゃないかなと思う。ちょっとヘッダまわりの癖にあわせて手間がいるかな? 以下のエントリを激しく参考にさせていただきました。多謝!
PostgreSQL Client Library (libpq) for iPhone/iPad - jakago
なお手順では、やれるところはXcodeでやる、という感じ。ではれっつごー。
ライブラリのビルド用プロジェクトを作る
ライブラリのビルド用プロジェクトをアプリとは別に新規作成。今回は "archivelib" という名前で作った。なんでわざわざlibarchiveという名前を避けたのかは、お察しください。
なお作成時にはXcodeで "iPhone OS" → "Library" → "Cocoa Touch Static Library" を選んでおく。これ重要。
ダウンロード、展開、準備
ネットから libarchive-2.6.2.tar.gz および bzip2-1.0.5.tar.gz を適当な場所にダウンロード。それから以下のコマンドを叩いて展開と configure。
~$ cd path/to/archivelib archivelib$ tar xzf ~/Download/libarchive-2.6.2.tar.gz archivelib$ tar xzf ~/Download/bzip2-1.0.5.tar.gz archivelib$ cd libarchive-2.6.2 libarchive-2.6.2$ ./configure --with-gnu-ld # やらないと config.h が生成されない! libarchive-2.6.2$ mkdir c; cp libarchive/*.c c/ # Xcodeでプロジェクトに加えるときに楽ができるように libarchive-2.6.2$ cd ../bzip2-1.0.5 bzip2-1.0.5$ mkdir c; cp libarchive/*.c c/
ライブラリのビルド準備
Xcodeのプロジェクト archivelib に戻る。"Other Sources" に適当に各ライブラリ用のグループを作り(bzip2/libarchive)、それぞれの中に各ライブラリディレクトリの c/ の中のものを全部放り込む。選べば選べるんだろうけど(Windows用のとかあるし)、まあ面倒なのでまとめて。別にエラーになったりしないし。
あとはプロジェクト設定のビルド設定のうち「ユーザヘッダ検索パス」にプロジェクト用ディレクトリのパスを加え、「再帰的」にチェックを入れる。設定変更を Device/Release どっちかだけ忘れたりしないようにね! もう面倒だし「すべての構成」でやるといいと思うよ!
ここからは多分ライブラリの都合にあわせての部分。
まず libarchive はビルド時に HAVE_CONFIG_H というフラグを必要とするので、これを PROJECTNAME_Prefix.pch に加える。
#define HAVE_CONFIG_H 1
また libarchive のソースコードには bzlib がシステムのincludeパスにあると思っているように書かれているが、今回はいっしょに落としてきてプロジェクトフォルダの中にあるので、以下のように修正する。これは archive_read_support_compression_bzip2.c と archive_write_set_compression_bzip2.c の2ファイルの先頭付近にある。
#ifdef HAVE_BZLIB_H - #include <bzlib.h> + #include "bzlib.h" #endif
これで準備完了! (自分が忘れてなければ)*1
ライブラリのビルドとユニバーサルバイナリ化
これはもう参考にしたページの通り。Xcodeのターゲット指定で "Simulator" および "Device" の両方で「ビルド」を実行。警告はもりもりと出力されるが、無視。エラーは無視できないので出たら頑張る。多分ヘッダまわりでフラグが何か足りてないとかだと思う。必要なら Prefix.pch に加えるとか、あとは configure するところまで戻って、なにかオプションを変えてやりなおすとかね。*2
ビルドが終了したらターミナルを開き、ユニバーサルバイナリを作成するために以下のコマンドを実行する。
$ cd archivelib archivelib$ lipo -create build/Release-iphone*/libarchivelib.a -output ./libarchivelib.a
これでお望みのものができました!
アプリのプロジェクトで取り込み、使用する
できあがった *.a ファイルはアプリのプロジェクト上で "Frameworks" から "追加" → "既存のファイル" で追加すると、ビルド時のリンク対象にしてくれる。もちろん使用する側のソースコードには参照するときの定義が必要なので、必要な各ライブラリの *.h ファイルはプロジェクトに取り込んで適当な場所に放り込んでおくといい。
シミュレータで動作し、実機でも動作すれば、見事にユニバーサルバイナリのビルドの完成が確認できます!
ぶっちゃけ
初めてやると面倒なんだけど、一度作っちゃえばあとはあまり気にしなくていいので、そこを乗り越えられるかどうかがキモだと思います。一度やっちゃうと、これでどんなライブラリでも使えるかなーという気分になるので、精神的にラクにはなりました。バイナリのアップロード後の2時間はいまだにドキドキものですが。
また zip だけを扱うなら、多分SDKのzlibを直接リンクしても弾かれない*3ので、そっちを使う方がラクだとは思います。libarchive って実は gz/bzip2 以外にもあれこれ対応してるらしいんだよね。あんまり使う予定もないんだけどさ。
以上、もしここまで実際にやった人がいたら、お疲れさまでした!