Google

2014年9月13日土曜日

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

前回の続き。

パスが追加されてて削除されないというのは解ったので、じゃあ具体的にどうするか。
元々やりたいことは以下でした。
  • 実機でもシミュレータでもリンクエラーを出さない
  • 可能な限り切り替えの手間を掛けたくない
  • 静的ライブラリを添付し直すとかは絶対無理
なんかXCodeの操作基礎勉強みたいになっちゃってますが、勉強不足だったので仕方なし。
昔のコンパイラと違ってXCodeのようなIDE構造が戸惑わせる部分は、ライブラリへの参照について以下の2つがあるという点じゃないでしょうかね。
  • 設定にサーチパスを指定する(伝統的)
  • プロジェクトにライブラリを追加する(D&D、近代的?)
XCodeプロジェクトはコマンドでビルドでき、その際にはビルドパスを指定したり直指定したりする点を考えると、後者はあくまでGUI上の便宜で存在しているはず。
それが前回のサーチパス自動追加という設計になっていると思われ。

と、ここまで来てふと気づいたことが。

パスが指定できるならビルドターゲットをもう一個作ってしまえいいのでは?
XCodeはスキームやターゲットを複数作って管理できるし、あ、それで即終わりかも。

という事で実験開始。

 やること:
  • プロジェクトのターゲットを複製
  • それぞれ、実機用とシミュレータ用とする
  • 前回設定したサーチパスは目的に合わせたパスを設定する
  • 切り替えてビルドテスト
まず最初にターゲットを複製します。
プロジェクト設定に行き、ターゲットの名前を右クリック。

Duplicateを選択します
一覧からDuplicateを選択すると"(元のターゲット名) copy"っていうターゲットが作成されます。
例えばTestProjectという名前の場合、TestProject copyがコピー時の名称です。
これは設定から後で修正も可能ですがテストなんでそのままにしてます。

コピーされました。
コピーすると、XCodeの最上部にあるスキーム設定から選択が可能になります。
これを切り替えるだけで簡単に使い分けができるという、、、要はXCodeの基礎の基礎でした。

ここの選択にcopyが追加され、選択可能になります。
今回は元々のものをiOS実機用、コピーした方をシミュレータデバッグ用としました。
で、それぞれにライブラリのサーチパスを設定します。

これらは前回の画像です。
元々の方は実機用ライブラリのパスを(例:Debug-iphoneosとあるパス)
シミュレータはそちらのパスになります。(例:Ddebug-iphonesimuratorとあるパス)
やり方は前回のようにグリっと*.aファイルをGUIに持って行っても構いません。
しかし静的ライブラリがそのままプロジェクトのGUIに存在したり混在していれば、XCodeはそれを参照してしまうため、どちらかのビルドは失敗します。
なので、もしD&Dでパスを自動設定するなら、設定し終わった後はプロジェクト階層にある*.aファイルは消去(または参照を解除)しましょう。

9/16追記:
大事なことを書き忘れていたので追記。
要はぐりっと持って行くことで、TARGETSのライブラリがこうなる訳です。



各ターゲット別に正しい静的ライブラリがRequiredになっているので、正常にリンクが通る訳ですね。
XCodeのバージョン相違による仕様ややり方によってはここに追加されない可能性があるかも知れませんので注意を。(未確認ですが)
追記終わり:

終わったら2つのターゲットをビルド実験します。
私の環境では、元々のターゲットはiOS実機用としました。

画像がでかくてすみません。実機ターゲットビルド結果です。
成功しました。
続いてコピーしたシミュレータのターゲット。

コピー側。ターゲットがシミュレータになっているのが左上で解るかと。
こちらも成功。
他にも方法はあるかと思いますが、とりあえず目的達成。
やっとこさ、デバッグ中の手間を緩和できそうです。

 まとめ:

  • ターゲットを増やしてそれぞれのライブラリパスを設定
  • プロジェクトのGUI上には*.aファイルは存在させない
  • あとは切り替えてビルドするだけ

よくよく考えてみればXCodeの元々の機能だし、サーチパス設定は当たり前だしで、やっぱり今更な結果。
ちゃんと機能を理解しないと以外なとこで足を引っ張られるものだと反省しました。

今回はこんなとこで。

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の使い方を読めば書いてあるのでしょうが、全然気づいていなかったのが情けない、、、。

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

2014年6月5日木曜日

田代島の牡蠣が到着

田代島の記事で書いた牡蠣が届きました。
とても良い品物なのでご紹介。


小さめの発泡スチロールで到着。


中身は牡蠣の潮煮(うしおに)でした。
これはたまりません。


パンフレットもついてます。


原材料は牡蠣のみ。
保存料も含め添加物が無いため冷凍でも9月が賞味期限です。
いい商品である証拠。


では早速調理して頂いてみたいと思います。
まずは常温解凍して使いやすくしておきます。



今回はパンフレットに書いてあったパスタをそのまま作成。
3人前のレシピです。


バター、にんにく、鷹の爪を炒めます。


忘れてましたがパッケージとパンフレットにはおヌコ様が鎮座。
いいデザインです。


バターが溶けて炒まったら汁と一緒に牡蠣を投入。
このゆで汁が牡蠣エキスたっぷりで、ほんのり塩味が付いています。
このまま酒のつまみとして使いたい位。

が、やや薄めなのでパスタに入れる塩以外にも味付けが必要です。
個人的には良い粗塩で牡蠣本来の旨味を味わうのがお勧め。


パスタが茹で上がったら和えます。
蒸発に注意しないとパサつきがちになるので手早く進めましょう。


できあがり。胡椒やオリーブオイル、マリーシャープス等でアレンジ。
牡蠣は12個入っていたので、3人前でも4個ずつ食べられます。

しかしなんといっても風味が良い上に牡蠣が丸々と太っているのが最高でした。
島の復興を感じられるかのような良い商品で何よりです。
次は普通に購入させて頂きます。ごちそうさまでした。

2014年5月31日土曜日

ChromeCast:セットアップ

ChromeCastを動かすためにセットアップをしてみました。
簡単なフェーズを書くと、以下になります。

 ・実機をTVへ接続
 ・iPhone(PC等)で直接ChromeCastに接続
 ・ChromeCastがWifiに繋げられるようiPhoneから設定
 ・iPhone側もChromeCastと同じWifiに接続しなおし
 ・後はiPhoneから操作

ChromeCastは外部操作デバイスを持たないため、最初にPCやiPhone等から直接こいつに繋ぎ、そこから家庭内Wifi設定をしてあげるという点がキモです。
その後の操作は直接ではなく、Wifi経由で行うため一度ChromeCastに接続した後はもう必要なく、あとは家庭内Wifiポイント経由で操作を行います。

テレビのHDMIに本体を差し込みます。
電源を差し込むとこのように光るので通電確認できます。
TVをChromeCastの入力に切り替えるといきなりセットアップの指示。
今回はiPhoneでここに書かれているアドレスに行ってみましょう。
chromecast.com/setupです。
Safariで開くとさらにAppStoreに行けとの指示が。

無料の専用アプリが必要です。
さくっとダウンロードして設定を開始しましよう。

開始すると本体をスキャンし始めます。
見つかりました。

起動画面

まずiPhoneとChromeCastをWifiで繋ぎます。
まだChromeCastは外部に接続できないのでこれが必要です。
ちなみにこのXXXXは数字。

一旦Wifi設定に行って、テレビに出ているChromeCastXXXXと
同じWifiアドレスを探して接続します。

接続すると何桁かの英数字が表示されます。
iPhoneとテレビが同じならOK。
続いてChromeCastが外部にアクセス可能になるよう設定をします。

自宅のWifiの設定を入れ込みます。
遠隔操作状態なので、正しく入れることでChromeCastがネットにつながります。
詳細画面がありますが、特別なものではないので割愛。
名前は最終的に好きなものに変更可能です。

設定するとChromeCast本体がWifiへアクセスを試みます。
失敗するとこうでるのでやり直し。

接続が成功すると、iPhoneはChromeCastから強制排除されてしまいます。
正しい動きなので慌てないように。
先程ChomeCastに教えたWifiへ改めて繋ぎ直しましょう。
 本体は向上出荷状態からのアップデートが必要ですが、勝手にやるようです。

アップデートは光契約なら5分も掛かりません。
さあかんりょ、、、ちょ、文字が消えてますけど。
まあ、動きには問題ないようなので次へ。
 
接続状態はこんなふうにでます。

では早速実験開始。
Youtube開いてchromeCastへ飛ばしてみます。

ガンダムUC冒頭7分をテレビに表示。
問題なく見れます。
PCの場合、chrome拡張を入れると簡単です。
ブラウザのタブを画面に割り当てられます。
Wifiからの操作なので遅延はありますが、プロジェクター代わりにはいいかも。
MacBookProと同期表示。
高いプロジェクターが無くても使えます。
画面の横幅が足りないと黒枠になる模様。
幅を広げたらテレビも横長になりました。
スクロール等も遅延しつつちゃんと出てくれます。
ようつべタブを画面に表示。
しかしWifi回線の混雑等で途切れる事が。
iOSアプリから同期すると綺麗に見れます。
バンダイチャネル等も出してみましたが途切れてしまいました。
まじめにPCから飛ばす構造だと仕方ありません。
Youtube等の専用アプリなら問題なく表示できています。
また、AppleTVのような画面共有機能は問題無く使えました。
個人的にはAppleの方が使いやすさもあるかと思いますが、この小ささは良いかと。

普段の使い方は、、、多分家族で動画を見るのが中心でしょうかね。