漢なら Ubuntu で C++11 プログラムをクロスコンパイルし, Windows バイナリを作りたいですね!
やりましょう!
目的
- Unix 系と Windows で動く C++11 プログラムを作りたい.
- Windows を起動せずとも windows バイナリをビルドしたい.
- Wine で動かし Linux 上で動作確認したい(継続ビルド&テストとかで Windows インスタンス立てるのめんどい).
MinGW のインストール
64bit 版を仮定します.
を参考に 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
ネイティブスレッドが使えると思われます.
MinGW ですと __MINGW32__
, __MINGW64__
マクロが定義されますので, これで判別して C++11 ヘッダを読むのか, mingw std threads ヘッダを読むのかの切り分けをするとよさそうです.
CMake
toolchain ファイルを作ると便利です.
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)
Win7 以降で導入された Win32 API を使うときなどは, _WIN32_WINNT
バージョンを指定する必要があります.
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_WIN32_WINNT=0x601")
のようにして CMAKE_CXX_FLAGS
に追加しておきましょう.
あとは, cmake bootstrap 時, 以下のように CMAKE_TOOLCHAIN_FILE
でファイルを指定します.
$ cmake -DCMAKE_TOOLCHAIN_FILE=mingw-cross.cmake ...
TODO
- 静的リンクを試す.
-
clang で cross-compile を極める.(より msvc に近いバイナリ生成とか)
- llvm-mingw(clang)