Posted at

Ubuntu 16.04 で MinGW を使い C++11 プログラムの Windows バイナリをクロスコンパイルする

More than 1 year has passed since last update.

漢なら Ubuntu で C++11 プログラムをクロスコンパイルし, Windows バイナリを作りたいですね!

やりましょう!


目的


  • Unix 系と Windows で動く C++11 プログラムを作りたい.

  • Windows を起動せずとも windows バイナリをビルドしたい.

  • Wine で動かし Linux 上で動作確認したい(継続ビルド&テストとかで Windows インスタンス立てるのめんどい).


MinGW のインストール

64bit 版を仮定します.

https://kakurasan.blogspot.jp/2015/07/debianubuntu-mingw-crosscompile.html

を参考に apt でインストールできます. Ubuntu 16.04 ではバージョン 5.3 が最新でした.


C++11 スレッド実装

MinGW で C++11 プログラムをコンパイルするときは, std::thread 周りに注意が必要です.

STL(runtime?)実装まわりの関係で C++11 スレッド周りの実装は posix 実装と win32 実装の二種類があります.

(MinGW コンパイラのサフィックスで -posix, -win32 があります)

win32 実装が理想な気がしますが, 現状の C++11 プログラムを改変せずそのまま使いたい場合(サードパーティ OSS ライブラリを使うなど)は -posix でコンパイルする必要があります.

-win32(デフォルト) だと mutex が定義されていないなどとコンパイルエラーが出ます.

ソースコードを修正することができる場合, 以下の mingw-std-threads を使うことで, win32 ネイティブスレッドが使えると思われます.

https://github.com/meganz/mingw-std-threads

MinGW ですと __MINGW32__, __MINGW64__ マクロが定義されますので, これで判別して C++11 ヘッダを読むのか, mingw std threads ヘッダを読むのかの切り分けをするとよさそうです.


CMake

toolchain ファイルを作ると便利です.

https://cmake.org/Wiki/CMake_Cross_Compiling

SET(CMAKE_SYSTEM_NAME Windows)

SET(CMAKE_C_COMPILER x86_64-w64-mingw32-gcc-posix)
SET(CMAKE_CXX_COMPILER x86_64-w64-mingw32-g++-posix)
SET(CMAKE_RC_COMPILER x86_64-w64-mingw32-windres)

SET(CMAKE_FIND_ROOT_PATH /usr/x86_64-w64-mingw32)

SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
SET(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

以下のように CMAKE_TOOLCHAIN_FILE でファイルを指定します.

$ cmake -DCMAKE_TOOLCHAIN_FILE=mingw-cross.cmake ...


TODO


  • 静的リンクを試す.

  • clang で cross-compile を極める.(より msvc に近いバイナリ生成とか)