[Work/TechInfo/other]

MinGW+MSYSもしくはMinGW+CMD.EXEでのOpenCVのコンパイル / 2015-01-15 (木)

概要

OpenCVをWindows環境でコンパイルしようと思った時に,標準パッケージではVisual Studio用のライブラリしかついてこない.
ソースコードも付いてくる,そしてCMake用のListも付いてくるので,サクッとMinGW用にコンパイルした……はずなのだが,ハマった.
理由を推測するに,どうやら,cmd.exeで実行する場合とMSYSで実行する場合とで,cmakeで生成される設定が異なり(つまり違うバイナリが生成され),これが自分のプログラムのコンパイル時のリンカの挙動に影響するようだ.(パスの渡し方とかだろうか?).

というわけでこの記事には,

  1. MSYSからコマンドを叩いてコンパイルする場合
  2. cmd.exeからコマンドを叩いてコンパイルする場合

の2通りを書く.

必要なもの

  • cmake Installerでもいいし,zipでもよい.環境変数でパスを通しておく.
  • OpenCVのWindowsパッケージ この記事では2.4.10で行っている.
  • MinGWとMSYSのセットアップが終わっていること

この際注意すべきは,cmakeはWindows Vista以降のシンボリックリンクをどうやら認識してくれない,ということ.
環境変数にパスを設定する場合には,シンボリックリンクを含まないパスで記述する.

OpenCVのWinパックは,自己解凍exeになっているので,展開するとこんな感じ.
Visual Studioならそのまま使えるライブラリが,build/x86/vc10,vc11,vc12に入っているが,VisualStudioを使うなんて当然却下である.

OpenCVのWindowsパッケージを展開したところ.

OpenCVそのもののビルド

cmake-gui.exeを起動する.
「Where is the source code:」に,opencvを展開したディレクトリのsourceディレクトリを指定.

「Where to build the binaries:」に,opencvを展開したディレクトリのbuild/x86以下に,buildする先を書く.
ここではC:\Users\daichi\Downloads\opencv\build\x86以下となる.

CMD.EXEから叩きたい場合は「cmd_exe_mingw」みたいな感じで指定.

cmake-guiのSourceディレクトリとbuild先ディレクトリの指定 CMD.EXEの場合

MSYSのbashから叩きたい場合は「msys_bash_mingw」みたいな感じで指定.

cmake-guiのSourceディレクトリとbuild先ディレクトリの指定 MSYSの場合

「Configure」ボタンを押すと,ディレクトリを作っていいかの確認が行われ,

ディレクトリを作っていいかの確認.CMD.EXEの場合 ディレクトリを作っていいかの確認.MSYSの場合

その後に生成するMakefileのターゲットを訊いてくる.

CMD.EXEから叩きたい場合は「MinGW Makefiles」を指定.

cmake-guiの生成するMakefileの指定.CMD.EXEの場合

MSYSから叩きたい場合は「MSYS Makefiles」を指定.

cmake-guiの生成するMakefileの指定.MSYSの場合

「Use default native compilers」を選択して「Finish」

何回か止まることがあるが,その度ごとにConfigureを押していけば問題がない.

ただし,特にCMD.EXEを使う場合,上記のシンボリックリンクを含んだパスに注意すること.
これは何度押しても解決しないか,あとのmakeの時にエラーを吐く.
なので,Configureが通っても,Valueで検出されたパスがシンボリックリンクを含んでいるパスになった場合,「Configureで一度検出された後,Generateを押す前」に,「Value」の欄のパスを適切に修正する必要がある.
(正確には./configureがもう一度やり直されるのだが)

CMD.EXEの場合,シンボリックリンクを含んだパスは修正する.

Configureが終わったら「Generate」を押すと,Makefileが生成される.

Makefileができたら,CMD.EXEかMSYSのbashで,指定したbuild先にMakefileがあることを確認したら,makeを実行する.

この時,CMD.EXEを使っている場合にはmingw32-makeコマンドを,MSYSの場合はmakeコマンドを叩く.

mingw32-makeコマンドを実行.CMD.EXEの場合 makeコマンドを実行.MSYSの場合

こんな感じでビルドが進行していく.

ビルドの進行状況.CMD.EXEの場合 ビルドの進行状況.MSYSの場合

自分のソースコードファイルのコンパイル

上でビルドした場所からインクルードファイルやライブラリファイルを動かしてないとして,

CMD.EXEから叩く場合は以下のように.

mingw32-g++ CPPファイル名 ^
-Ic:\Users\daichi\Downloads\opencv\build\include ^
-Lc:\Users\daichi\Downloads\opencv\build\x86\cmd_exe_mingw ^
-lopencv_(ライブラリディレクトリにある限りのライブラリ名)2410 ^
-o 出力ファイル名 -static-libgcc -static-libstdc++

MSYSから叩く場合は以下のように.

g++ CPPファイル名 \
-I/c/Users/daichi/Downloads/opencv/build/include \
-L/c/Users/daichi/Downloads/opencv/build/x86/msys_bash_mingw \
-lopencv_(ライブラリディレクトリにある限りのライブラリ名)2410 \
-o 出力ファイル名 -static-libgcc -static-libstdc++

*.dll.aなるライブラリファイルができているのでスタティックリングができるのかと思いきや,安藤が今の所確認している限りできないので,素直にダイナミックリンクのみにすべきである.
つまり,-staticオプションは絶対につけない.
ダイナミックリンクなので,当然実行ファイルと同じ場所かパスが通っている場所に,ビルドされたlibopencv_*.dllを全部コピーする必要がある.

「(ライブラリディレクトリにある限りのライブラリ名)」というのは,OpenCVはライブラリが細かく分かれているので,どれを指定したらいいのか,インクルードしているヘッダファイルからは判別がつかないことがあるから(特にVer.1系の機能を使うと).
具体的には,

-lopencv_core2410 -lopencv_highgui2410 -lopencv_*2410 -lopencv_*2410 ...

と全部列挙する感じである.
面倒くさいので,Makefileを書いた方が精神的にもよっぽど良いだろう.

[ ツッコミの受付は終了しています ]
この記事のリンク元