2012年4月7日土曜日

Macでのlibjpegとかlibpngとか

凄まじくハマったので、忘れないように(AND 追加の問題発生時の対応用に)メモ。
試行錯誤しながらやったので、細かい部分は曖昧です。

(2012/07/25追記)
下記の内容をまとめました→(続・Macでのlibjpegとかlibpngとか
お急ぎの方ははまとめをご覧下さい。


何をしようとしたか

そもそもの発端は、前回までの続きとしてミクさんをプログラム的に呼び出す方法を調べていたことでした。
んで、工学ナビさんが急募してたのでMacでGLMetaseqを使ってみたとか、「ARToolKitで初音ミク」をやってみようといったエントリを参考に、環境構築をしていたわけです。
最初は順調だったんですが、工学ナビさんが急募してたのでMacでGLMetaseqを使ってみた(続き)に書かれているpng対応などを追加したあたりから雲行きが怪しく…。

最初作っていた環境はMacports経由で色々インストールしていたので、状況は全く同じはずだったんですが、なぜか実行時に"symbol not found"などと怒られ、一切実行できなくなってしまいました。

libjpeg.dylibとかlibpng.dylibのあるディレクトリにはパス通してました*1し、原因が一切思いつかないので、とりあえず最近流行りらしいし、パッケージ管理をMacportsからhomebrewに変えようと思い、一式アンインストールして入れなおすという暴挙に。

続く迷走

暴挙に出た結果としては、そもそもコンパイルすら通らなくなる有様*2…。
この辺からよく分からなくなって、brewがインストールするときに張るシンボリックリンクをImageIO.frameworkの下にいるlibjpeg.dylibとかに張り替えるとか、挙句OSのクリーンインストールまでやる始末。
また、OpenCVの中でlibjpegとか呼んでるのが悪いんじゃないかと考えて、ImageIO.frameworkの配下にいるライブラリを叩くように修正しようかと、訳のわからないことをやろうとしたりで、大迷走。

ライブラリの読み込み順

たださすがにOpenCV自体をいじるのはコスト的に美味しくないので、どうにかならないかと調べていたら、以下のエントリがまさに答えを示していました。

MacPorts のために DYLD_LIBRARY_PATH を使ってはいけない理由

曰く、
Macではランタイムライブラリの検索順序について、「man 1 dyld」 で確認することができます。
曰く、以下の順序で検索されます。
1. DYLD_LIBRARY_PATH
If it still can’t find the library, it then searches DYLD_FALLBACK_FRAMEWORK_PATH and DYLD_FALLBACK_LIBRARY_PATH in turn.
2. DYLD_FALLBACK_FRAMEWORK_PATH
By default, it is set to /Library/Frameworks:/Network/Library/Frameworks:/System/Library/Frameworks
3. DYLD_FALLBACK_LIBRARY_PATH
By default, it is set to $(HOME)/lib:/usr/local/lib:/lib:/usr/lib.
とのこと。

デフォルト状態ではDYLD_LIBRARY_PATHは設定されていないので、IDEなどで明示的に設定しない場合のライブラリ検索順序は、

  1. /Library/Frameworks:/Network/Library/Frameworks:/System/Library/Frameworks
  2. $(HOME)/lib:/usr/local/lib:/lib:/usr/lib

となるはず。
Macportsを使っていたときは、/opt/local/libの下にライブラリ一式がいたので意味がなかったのですけど、homebrewは/usr/local/libにライブラリ一式を追加してくれてます。

…ということで、これまで自力でライブラリパスを通していたのが実は裏目に出ていたようです。
これで、libjpegまわりのエラーはなくなりました。

で、libpngについてですが、homebrewの管理から外れているということは承知の上で、brew search libpngを実行したところ、こんなメッセージが。
Apple distributes libpng with OS X, you can find it in /usr/X11/lib. However not all build scripts look here, so you may need to call ENV.x11 in your formula's install function.
…おや?
そう、なにもサードパーティのlibpngを入れるまでもなく、最初から入ってたんですね。
もちろんヘッダファイルも/usr/X11/includeにしっかりいました。

で、/usr/X11/libはどこにもパス指定されていないので、コンパイル時には指定しないとダメなはずですが、今回はNetBeansがよしなに計らってくれているようで*3、うまいことできてました。
自分のために、ライブラリパスを明示的に設定しない場合と設定した場合に実行されたコマンドを貼っておきます。


  • 設定しない場合(うまく実行できる)
gcc     -framework GLUT -framework OpenGL -L/usr/X11/lib -o dist/Debug/GNU-MacOSX/glmetaseq_test build/Debug/GNU-MacOSX/_ext/2091976640/GLMetaseq.o build/Debug/GNU-MacOSX/_ext/2091976640/main.o -ljpeg -lpng
  • 設定した場合(実行できない)
gcc     -framework GLUT -framework OpenGL -L/usr/X11/lib -o dist/Debug/GNU-MacOSX/glmetaseq_test build/Debug/GNU-MacOSX/_ext/2091976640/GLMetaseq.o build/Debug/GNU-MacOSX/_ext/2091976640/main.o -L/usr/X11/lib -ljpeg -lpng
オブジェクトファイルの後ろで-Lオプションつけると何が変わるんでしたっけ…?


(2012/4/8追記)
上記/usr/X11/libへのパスですが、自分で強引に設定していたのを忘れていました…。
プロジェクトのプロパティー→構築→リンカーとたどって、普通は「追加のライブラリディレクトリ」としてパスを設定すると思いますが、今回は「追加のオプション」に -L/usr/X11/lib を追加することでうまくいっていました。(=明示的に設定している)
ただ、やっぱりオブジェクトファイルのあとで-Lオプションつけるのと何が違うのか、さっぱりです。

…動いたからよしとしましょう。

結論

今回の結論としては、

  1. デフォルトで検索されるライブラリパスはいじらないほうが吉
  2. いじる必要がある場合、他のものに出る影響を最小化するために、DYLD_FALLBACK_LIBRARY_PATHへ追加する

といったところでしょうか。
本来ならもっとスマートに解決できそうに思いますが、どうもこのへんが限界です

先のエントリの結論にも書かれてますが、こういうのは「既存ソフトウェアに影響があるので、新規ライブラリ (ports で入れたライブラリ等) はデフォルトライブラリの後で読み込むようにしましょう。」この一言につきますね。



…しかしOpenCVと組み合わせたらまた問題が出そうな気がしますね、コレ。

  • *1:これがそもそもの間違い
  • *2:こっちもシンボル見つからない系のエラーを吐いてた
  • *3:こういう姿勢がもう色々とダメ

0 件のコメント:

コメントを投稿