[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を書いた方が精神的にもよっぽど良いだろう.

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

[Work/TechInfo/other]

MinGW+Code::BlocksでOpenCLのコンパイル / 2015-01-06 (火)

追記: その後MSYSのbashから以下のオプション順でgccを叩くことで,コンパイル可能なことを確認しました.これでCode::Blocksもいらなくなるぜヒャッハー!
そもそもWindowsの場合スタティックリンクが想定されていないだけでなく,OpenCLそのものもダイナミックリンクの運用を前提としているようで……なので.aファイルは作らないで,シェアードオブジェクトの形でコンパイルするようにしておいたほうがよさそう.
(Intel SDKの場合)

gcc Cのファイル名 \
-I"/c/Program Files (x86)/Intel/OpenCL SDK/4.6/include" \
-L"/c/Program Files (x86)/Intel/OpenCL SDK/4.6/lib/x86" \
-lOpenCL -static-libgcc -o 出力ファイル名

MinGWでコンパイルできない!

*.clという形でカーネルプログラムをただのテキストファイルとして配置しておいて実行時ビルドする形にしておくのと,C言語のコード側に,

#ifdef __APPLE__
#include <OpenCL/opencl.h>
#else
#include <CL/cl.h>
#endif

を書いておけば,基本的にどのOS,どのプラットフォーム,どのSDKでも動作するコードができるはずなのだが,OSXやLinuxではgccコマンド一発やmakeでコンパイルできていたものが,cmd.exeからコマンドを叩いたMinGWではリンクエラーを起こしてしまう.
(cmd.exeだとLD_LIBRARY_PATHが通らないからか?)

なので,MinGW環境のみ,Code::Blocksをmakeの代わりとして用いてビルドする.

WindowsでのコンパイルにVisual Studioを使う方法なんて当然却下である.
俺はEmacsでコードを書いて(幸い今はOSX, Linux, Windowsすべてで同じEmacsが使える),
Linuxで計算を実行させたいのだ.
計算マシンがWindowsの場合のみ同じコードから実行バイナリを生成したいだけなのである.

Intel OpenCL SDKやAMD APP SDK(Ver.2.9.1まで)だと最初からCode::Blocks+MinGWの環境で使えるlib(OpenCL.lib)が存在するので,SDKとしてはそちらをお勧めする.(ただしAMD APP SDKは3.0.0-Betaからは存在しない模様)

*.dllのみしか存在しない場合には,mingw-utilsのdlltoolを使って作っておく.
dlltoolを使ってlibOpenCL.aを作っておくとスタティックリンクもできる.

このテキストは,OpenCL™ with Code::Blocks tutorialこちらのページを参考にしたものである.

OpenCL用の「Compilerセッティング」

Code::Blocksをインストールしたら,Settings→Compiler.

最初から存在する「GNU GCC Compiler」というCompilerセッティングを「Copy」して,「OpenCL」なり,「OpenCL_Intel_SDK」なり,「OpenCL_NVidia_SDK」なり,「OpenCL_AMD_APP_SDK」なりのCompilerセッティングを作る.

Toolchain executableタブの「Compiler’s installation directory」にMinGWをインストールしてあるパスを指定.

普通にMinGWをインストールするとC:\MinGWに配置されているので,デフォルト設定(もしくはAuto-detect)で問題はないが,ユーザのホームディレクトリの下などにMinGWを配置している場合は,ここで明示的に指定する必要がある.

Linker settingタブのOther linker options欄に,「-lOpenCL」と書き込む.

Search directionsタブのCompilerタブ,「Add」して,使っているOpenCL SDKのincludeディレクトリを入れる.

同じくSearch directionsタブのLinkerタブ,「Add」して,使っているOpenCL SDKのlibディレクトリを入れる.64bitWindows用のSDKを落とした場合,x86_64とx86の二つがあるので,MinGW32の場合はlibディレクトリの中のx86ディレクトリを指定.

プロジェクトを作って既存コードを取り込む

File→New→Projectで,新規プロジェクトを作り,

ここではConsoleアプリを選択して,Go.

Skipはしないで,Next.

CかC++の言語を選択,Next.

プロジェクトの名前と配置する場所を設定して,Next.

先ほど作ったOpenCL用のコンパイラセッティングを選択.

新規プロジェクトができたら,Sourcesの中にある空のmain.cは「Remove file from project」しておく.(プロジェクトから外したら,プロジェクトディレクトリの中から消しても良い)

プロジェクトを右クリック→Add files.

ファイル選択ダイアログが開くので,既に作ってあるOpenCLの「C言語」のファイル一式を選択して開く.
ここではtest6というOSXとLinuxで既に動作実績がある既存のOpenCLプログラムのディレクトリから選択した.

適当にOK.

そうすると,パスなどは適当に処理されて,ソースコードファイル本体もコピーされることなく参照扱いとなり,既存のソースコードファイルをプロジェクトとして扱える.

つまりこの方法では,Code::Blocksのプロジェクトディレクトリは,プロジェクト設定ファイルとBuildセッティングファイル(あとビルド後のexe)を格納する為だけに使われることになる.
(感覚的にはMakefileのターゲットが一つ増えるだけ?)
当然他のマシン,他のOS,他のエディタなどで元のファイルを修正したりすれば,それが反映される.

OSXやLinuxでは同じファイルをmakeやgccコマンドを直接叩いてコンパイルしているしているので,そちらに変更を加えないでよく,かつDropboxなどに放り込んでおけば完全に同期が取れていることになるので,複数のマシン,OSで開発している人間にとっては非常に美しい形となる.

ビルドの設定(Build options)とビルド

プロジェクトを右クリック→Build options.

なぜかここでも,「Compilerセッティング」をした時と同じ,includeとlibの場所,linker optionを指定してやる必要がある.

例によって,Search directionsタブのCompilerタブで「Add」して,SDKのincludeディレクトリを追加.ここでは相対パスで読まれるようだ.

同様にSearch directionタブのLinkerタブで,「Add」して,SDKのlibのディレクトリを指定.

さらに同様に,Linker settingsのOther linker options欄に「-lOpenCL」を追加.

この欄に「-static-libgcc」と「-staticlibstdc++」も加えておくと,MinGWで提供されるCとC++の基本ライブラリがスタティックリンクされるので,MinGWがインストールされていないコンピュータでも動作するようになる.
ただし,C++の基本ライブラリをスタティックリンクすると生成される実行exeファイルが非常に大きくなるので,C言語の機能のみしか使ってない場合は-static-libgccのみで問題ない.

(MinGW独自の.dllが必要な時代って……MinGWの思想に反するんじゃ……)

ここまでできたら,プロジェクトを右クリック→Build.

プロジェクトディレクトリ/bin/Debugの中に,MSYSで実行可能なexeファイルができている.

当然,cmd.exeでも実行可能である.

外部カーネルプログラムファイル*.clを使っているコードの場合は,Buildされたexeファイルを,カーネルプログラムファイルが存在するディレクトリにコピーして実行するか,逆にカーネルプログラムをこのディレクトリに持ってきて実行する.

まとめ

MSYSから,gccコマンド一発でコンパイルできないのは気にくわないが,これで一応,複数のマシン,複数のOSで,エディタを問わず開発できるので,よしとしよう.

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

[Work/TechInfo/other]

Sambaが使用可能なユーザの設定 / 2014-11-24 (月)

久々にSambaを構築したら変わってた

NIS環境.
久々にSambaサーバを構築してみたら,どうしても自分以外のユーザがアクセスできない.
最近のSambaは全然知らなかったのでハマったのでメモ.

解決法

sudo pdbedit -a "ユーザ名"

smbpasswdでのNISのシンク

ついでに,パスワードのシンク周り.
NIS環境で普通に「passwd」コマンド使うとyppasswdに置き換えられるのだが,「smbpasswd」からだと適切には置き換えられない模様.
smb.confの中身を以下に.

unix password sync = yes
passwd program = /usr/bin/yppasswd %u

で大丈夫の模様. ついでに,/usr/bin/passwdを/usr/bin/smbpasswdへのシンボリックリンクに置き換えておけば,もっと問題なくなるか?

[ ツッコミの受付は終了しています ]
トラックバック (2)

[Work/TechInfo/other]

NTEmacsのTwittering-mode-3.0.0とcURL / 2014-10-26 (日)

NTEmacsとTwittering-mode-3.0.0の同梱cURLで認証が通らない

NTEmacsにTwittering-mode-3.0.0を入れると,GnuPGPでの認証時にcurlがabortする問題.
基本的には同梱のwin-curlディレクトリの中に入ってるcurl.exeとcertディレクトリの中に入ってる認証ファイルを使おうとするが,これがいかんようだ.

解決法

Win32用のcURLバイナリを配っているサイトから,「Download SSH, SSL, SSPI version」をダウンロードし,中身(exeやdll)をパスが通っているディレクトリにぶち込む.(例では,「ホームディレクトリ(hoge)/Utils/bin」)

cURL用の認証ファイルを配っているページから,「cacert.pem」をダウンロードし,「curl-ca-bundle.crt」に名前を変更,適当な場所にぶち込む.(例では「ホームディレクトリ(hoge)/Utils/share」)

以下のコードを,.emacsなり,.emacs.d/init.elに記述.

(setq twittering-curl-program "/Users/hoge/Utils/bin/curl.exe")
(setq twittering-cert-file "/Users/hoge/Utils/share/curl-ca-bundle.crt")

で,動くようになる.

[ ツッコミの受付は終了しています ]
トラックバック (2)

[Work/TechInfo/other]

TeXでカウンタを.auxに書き込む方法 / 2011-01-23 (日)

概要

TeXのdocument中でカウントして行ったものを,documentの冒頭などで合計数を表示するためには,sectionなどのカウンタと同様にauxファイルに書き込む必要がある.
その方法は以下の通り.
http://rakasaka.fc2web.com/tex/tex.html を参考に.

サンプルコード

\documentstyle{jarticle}
\newcounter{example}

\makeatletter
\def\exlabel#1{\@bsphack
  \protected@write\@auxout{}%
         {\string\newlabel{#1}{{\arabic{example}}{\thepage}}}%
  \@esphack}
\makeatother

\begin{document}

stepcounterは合計で\ref{last_ex}回実行されています.

\section{Introduction}
\stepcounter{example}

\section{Material Method}
\stepcounter{example}

\section{Experimental Results}
\stepcounter{example}

\section{Discussion}
\stepcounter{example}

\section{Conclusion}
\stepcounter{example}
\stepcounter{example}
\exlabel{last_ex}

\end{document}
[ ツッコミの受付は終了しています ]
この記事のリンク元 | 10 | 1 | 1 |