OpenCVをMacでビルドしてHaskellから使う

OpenCVの32ビット版をHaskellからForeign Function Interface (FFI)で使いたかったのでやってみた。手動でインストールしたところ、MacPortsで入れるよりも多少手間はかかるが所要時間は遙かに短かかった(正味のビルド時間は15分もかからない。MacPortsだと一晩かかる)。忘れないうちに覚え書き。使用環境はMountain Lion on iMac Mid 2010。

手順は基本的にはここに書いてあるのに従えばよい。
http://opencv.willowgarage.com/wiki/InstallGuide

作業の流れ

  1. App StoreからXcodeをインストールし、そこからCommand Line Tools(gccやmakeが入っている)をインストールする。
  2. MacPortsからcmakeとpkgconfigの二つのパッケージを入れる。
  3. OpenCVのソースをダウンロードして展開し、cmakeでconfigureする。
    1. バイナリ作成用のフォルダ(今回は /opt/local/share/opencv-2.4.2 としておく)を作成してそこにカレントディレクトリを移動し、cmake <ソースのフォルダ>を実行する。
  4. 32ビットでビルドするため、CMakeCache.txtの書き換え、makeでビルド。
    1. cmakeが生成したCMakeCache.txtにCMAKE_C_FLAGS:STRING=という行とCMAKE_CXX_FLAGSという行があるので、それぞれ末尾に-m32を加える。
    2. make -j 4 とすると4スレッド並行でビルドしてくれる。iMac Mid 2010でものの10分もかからなかった。
  5. binディレクトリに必要に応じて手動でパスを通す。あるいはmake installする(上のガイドだと、共通のフォルダが散らかるので非推奨とのことだが、やってしまった)。
  6. pkg-config用のファイルであるopencv.pc(unix-installフォルダにある)を/usr/lib/pkgconfigの下にコピーし、chmod 644で読み取り可能に設定する。場合によっては(make installを使わなかったときなど)opencv.pcの内容を調整する必要があるかもしれない。

HaskellからC++を呼ぶときのビルドのスクリプトは以下のようになる。lib1.cpp, lib2.cppがcppでのソースコードで、main.hsがmainを含むHaskellソースファイル。

#!/bin/sh

g++ -c lib1.cpp lib2.cpp -m32 `pkg-config --cflags opencv`
ghc --make main.hs -lstdc++ lib1.o lib2.o `pkg-config --libs opencv`

GHCは32ビットコードしか出力できないとのことなので、OpenCVのライブラリ自体、そしてOpenCVとHaskellをつなぐC++のグルーコード(上のlib1.cpp、lib2.cpp)もHaskellからリンクするためには32ビットでビルドしておく必要がある。
できあがった実行ファイルは1.4MB。悪くない。

OpenCVをXcodeから使う方法については、ここにも記事があった。僕はXcode上でコーディング(リアルタイムでエラーが表示されるので便利)して、ビルドは上記のスクリプトで行っている。
Mac OSX Snow LeopardにOpenCVを入れてXCodeから使えるようにする手順
http://d.hatena.ne.jp/konisimple/20100811/1281526832

それと、OpenCVはC++で書かれているので、HaskellからFFIで呼ぶには、以下の記事にあるようにextern "C"を使うなどの工夫が必要。
[Haskell]FFI使ってC++バインディングに入門
http://mymo.blog8.fc2.com/blog-entry-52.html

これらを使って、HaskellでOpenCVのバインディングを書けることが分かった。その詳細はまた気が向いたときにでも記す。
今回の作業で初めてcmakeやpkg-configの存在を知ることができたのも良かった。