Google

2014年9月12日金曜日

XCodeで静的ライブラリのリンクエラー:前編

今更感丸出しですが、しばらく別の仕事してるとすぐ忘れるので備忘録メモ。
似たような記事を探してはみたものの、微妙過ぎて誰も書いてないようなんで。

今回のお題:
  • XCode5で自前の静的ライブラリを作成
    • デバッグ中で、実機用とシミュレータ用に2種ビルド
  • ライブラリを使う別のプロジェクトを作成しインポート
  • 実機ビルド:OK
  • iOSシミュレータビルド:失敗←ココ
静的ライブラリ作成方法とかはあちこちで記事が上がってるので割愛。
この話は静的ライブラリプロジェクトのテストコードで良いとかという話でもなく、以下の様な目的がありました。

 目的:
  1. ある独自のミドルレイヤ機能を持ったiOSアプリが元々あった
  2. ミドルレイヤを使いまわしたくなったので静的ライブラリ化を決定
  3. 分割してビルドし、結合テスト
なので、通常とは微妙に違うケースではあるかと。
ちなみに最初のうち、静的ライブラリの適用方法はこうしてました。


静的ライブラリを使う方にとってはお馴染み、*.aファイルとヘッダの*.h群をぐりっとD&Dで持ってくる方法です。
ヘッダ諸共これで適用されるので簡単といえば簡単。
サードパーティ製の実機用ライブラリの場合は特に迷うことも無いかと。

しかしミドルとGUIの両方を一緒にデバッグする今回のケースではちょっと事情が。
ここに持ってくるライブラリファイルは、「実機ビルド版」と「シミュレータビルド版」のどっちを持ってくるか?という事。

環境に合わせたものを持ってくるのは当たり前ですが、D&Dではどっちか片方しかできません。
かといって何かにつけファイルを入れ直しとか面倒すぎてやりたくありません。
デバイス依存や特殊操作でも無い限りシミュレータでデバッグした方が楽ですし。
なんかやり方あったはずなんですが、ど忘れ。

ちなみに失敗してるシミュレータビルドで出てくる画面はこう。

よくあるケースで、i386用の関数とかクラスがないよ、というメッセージ
XCodeの操作ミスかと思い、*.aファイルを確認して差し替え直しても一緒。
うーん、XCodeの細かい挙動を忘れてしまっている、、、、、

仕方なく、まずはファイル自体の確認として実機用とシミュレータ用両方のライブラリのターゲットに問題がないかを見てみることに。
ターゲット等の情報を確認するにはxcrunを使います。

静的ライブラリの出力先は通常のアプリ同様デフォルトで/Users/(ユーザ名)/Library/Developper/XCode/DerivedData/(プロジェクト名)/...の先にあって、iphoneosとiphonesimuratorでディレクトリが分かれています。
Macのターミナルを起動して、上記のパスに移動して、その中にある*.aファイルに対して、以下のコマンドでターゲットを確認します。

 xcrun -sdk iphoneos lipo -detailed_info (ファイル名)

シミュレータ版の情報

実機版の情報

オプション多めで無駄に情報が多いですが、ちゃんと実機用はarmシリーズ、シミュレータ用はx86系なのを確認。
特に間違ってませんね、、、、、

しかし私はエラーメッセージを適当に読み流す悪い癖があるので、再度ちゃんとエラーメッセージを見てふと気づいた事が。
ライブラリをリンクする-LDの処理に、実機用とシミュレータ用の両方のライブラリパスから読み込んだ形跡が、、、、。
あれれ、そんなはずはと思ってプロジェクト設定を開き、TARGETS→Build Settings→Search Paths→Library Search Pathsを選択。

見ると、2個のパスが追加されていました。

実機ビルドしたライブラリのパス

こっちはシミュレータのパス

静的ライブラリはどちらか片方しか入れていないのに、ビルド設定では両方のパスを見てしまっているようです。
ファイル名も同じなので読み込んでしまっていたのかと。
しかし自分で設定した記憶はない、、、、

そこで、素のプロジェクトを準備して、静的ライブラリをD&Dでインポートし、ここの設定がどうなるのかを確かめて見ることに。

 実験:
  1. 素のXCodeプロジェクト作成
  2. 先程の検索パスになにも記載が無いことを確認
  3. 実機用ライブラリをプロジェクトにインポート(D&D)
  4. 実機のパスがあることを確認
  5. さらにシミュレータ用ライブラリをプロジェクトにインポート(D&D)
  6. 追加でこちらも同様にパスが追加されたことを確認
  7. 2つのパスが同時に存在、現象も一緒なのを確認

まあ、上記まではいいとして、問題はこの後。
プロジェクトから静的ライブラリを削除しても、ライブラリパス設定には何も変化がありませんでした。
同じパスの場合は更なる追加はしないようですが、削除もしないようです。

 今回の結論:
  • XCodeはライブラリインポート時にパスを追加していた
  • 自分で両方のライブラリをインポートしていたorz

うーん、隅から隅までちゃんとXCodeの使い方を読めば書いてあるのでしょうが、全然気づいていなかったのが情けない、、、。

しかしまだ根本問題解決には至ってないので次回に続きます。

0 件のコメント:

コメントを投稿