クロスコンパイルしてwindows用のOpenCVライブラリを作る

# 背景

mruby-cliやcgoでクロスコンパイルしてWindowsのバイナリを簡単に作れるが、今回取り上げたOpenCVなど
サードパーティのライブラリを呼び出すコードを含むようなコードはたぶんビルドが難しいのではと
感じていた。

この問題解決の第一歩として、自前で、Linux上で、Windows向けのOpenCVライブラリのビルドを試みた。
最終的にワンバイナリを目標としているので、DLLではなく、.aの静的ライブラリを作成するようにしている。


# 前提

以下の、Dockerコンテナーを用意して、mingw-w64が動くLinux環境を用意した。

- https://github.com/kjunichi/docker-mingw-w64-32

# クロスコンパイル向けの.cmakeファイルの用意

```cmake
set(CMAKE_SYSTEM_NAME Windows)

# specify the cross compiler
set(CMAKE_C_COMPILER   /usr/bin/i686-w64-mingw32-gcc)
set(CMAKE_CXX_COMPILER /usr/bin/i686-w64-mingw32-g++)

# set PKG_CONFIG_PATH for MinGW Cross Compile Environment
set(ENV{PKG_CONFIG_PATH} /usr/i686-w64-mingw32/lib/pkgconfig)

# where is the target environment 
set(CMAKE_FIND_ROOT_PATH /usr/i686-w64-mingw32/)
```

# コンパイラオプションの変更

-Werror=non-virtual-dtorを無効化する

```diff
--- a/cmake/OpenCVCompilerOptions.cmake
+++ b/cmake/OpenCVCompilerOptions.cmake
@@ -64,7 +64,7 @@ if(CMAKE_COMPILER_IS_GNUCXX)
   add_extra_compiler_option(-W)
   add_extra_compiler_option(-Wall)
   add_extra_compiler_option(-Werror=return-type)
-  add_extra_compiler_option(-Werror=non-virtual-dtor)
+  #add_extra_compiler_option(-Werror=non-virtual-dtor)
   add_extra_compiler_option(-Werror=address)
   add_extra_compiler_option(-Werror=sequence-point)
   add_extra_compiler_option(-Wformat)
```

## 参考資料

- [OpenCV - Bug #4107: 'struct IUnknown' has accessible non-virtual destructor for MinGW 4.9.2 - OpenCV DevZone](http://code.opencv.org/issues/4107)

# CMakeによるビルド

```bash
mkdir build
cd  build
cmake -DCMAKE_TOOLCHAIN_FILE=../mytool.cmake -DWITH_IPP=OFF -DBUILD_SHARED_LIBS=OFF  ..
make
make install
cd ..
```

# 使い方

## サンプル

WebCamの画像を表示する

```cpp
#include "opencv2/opencv.hpp"

int main(int, char**)
{
    cv::VideoCapture cap(1); // open the default camera
    if (!cap.isOpened())  // check if we succeeded
        return -1;
    for (;;)
    {
        cv::Mat frame;
        cap >> frame; // get a new frame from camera
        //cvtColor(frame, edges, COLOR_BGR2GRAY);
        //GaussianBlur(edges, edges, Size(7, 7), 1.5, 1.5);
        //Canny(edges, edges, 0, 30, 3);
        cv::imshow("Webcam feed", frame);
        if (cv::waitKey(30) >= 0) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor

    return 0;
}

```

## ビルド方法

.aファイルの指定順番が超大事。

```
i686-w64-mingw32-g++ webcam.cpp -o webcam.exe -I ./install/include/ \
 install/lib/libopencv_highgui300.a \
 install/lib/libopencv_videoio300.a \
 install/lib/libopencv_imgcodecs300.a \
 install/lib/libopencv_imgproc300.a \
 install/lib/libopencv_core300.a \
 install/lib/libopencv_hal300.a \
 3rdparty/lib/libIlmImf.a \
 3rdparty/lib/libzlib.a \
 3rdparty/lib/liblibjasper.a \
 3rdparty/lib/liblibjpeg.a \
 3rdparty/lib/liblibtiff.a \
 3rdparty/lib/liblibwebp.a \
 3rdparty/lib/liblibpng.a \
 -lvfw32 -lole32 -loleaut32 -lgdi32 -lcomdlg32 -luuid \
 -static-libgcc -static-libstdc++
```

# 知見

BUILD_opencv_worldでライブラリをまとめようとしたら、エラーとなっていまい、NG。

# 関連記事


- [RustでFaceTime HDカメラやWebカメラを使う](http://abrakatabura.hatenablog.com/entry/2014/10/23/063643)
- [GoでFaceTime HDカメラやWebカメラを使う](http://abrakatabura.hatenablog.com/entry/2014/10/24/065607)
- [Node.jsでFaceTime HDカメラを使う](http://abrakatabura.hatenablog.com/entry/2014/11/24/192128)
- [OpenCVをEmscriptenでJS化して動かせた](http://abrakatabura.hatenablog.com/entry/2015/08/22/095842)
- [外部のライブラリに依存するmrbgemを使ってもmruby-cliでワンバイナリを作成できるようにした](http://abrakatabura.hatenablog.com/entry/2016/02/14/144922)
- [mrubyでWebカメラを黒い画面にそのまま表示できるようにした](http://abrakatabura.hatenablog.com/entry/2017/02/25/080830)
- [WindowsでmrubyからGoで作ったライブラリを呼び出して、Webカメラの画像をコマンドプロンプトに表示した](http://abrakatabura.hatenablog.com/entry/2017/09/01/072123)
- [RustでWebカメラの映像をコマンドプロンプトに出すコマンドを作った](http://abrakatabura.hatenablog.com/entry/2017/09/21/064630)

## Windowsでのビルド記事

- [Windows 10でFirefoxをソースからビルドして動かしてみた](https://abrakatabura.hatenablog.com/entry/2017/05/10/071020)
- [WindowsでPostgreSQLをソースからビルドした](https://abrakatabura.hatenablog.com/entry/2017/05/18/071705)