An open source development environment is preferred by many developers because of its powerful and effective tools. Additionally, it is desireable to avoid the expense of compiler licenses, proprietary operating systems, and hardware when possible. In the age of cloud-based testing and deployment, the ability to work from an open source, Linux stack means services like Travis-CI, etc can be leveraged.
In this post, we will walk through the steps to build and test C/C++-based code (ITK) for Windows from Linux or Mac OSX. This requires current ITK Git master, to be released in 4.8.0, and current CMake Git master, to be released in 3.3.0. By the end of the post, we will be able to easily build and test Windows executables from a completely open source stack.
Get the Cross-Compiler
The MXE project provides access to the GCC-based MinGW compiler for Windows. It even includes a CMake toolchain file, the configuration file that tells CMake all the information it needs to know about a cross-compiler. First, clone the MXE repository:
cd ~/src git clone https://github.com/mxe/mxe.git cd mxe
Next, make sure we have all the build dependencies for MXE. A typical Linux development system will already have the dependencies installed. Some dependencies may need to be installed on OSX. On Debian, for example:
apt-get install \ autoconf automake autopoint bash bison bzip2 cmake flex gettext \ git g++ gperf intltool libffi-dev libtool-bin libltdl-dev \ libssl-dev libxml-parser-perl make openssl patch perl \ pkg-config python ruby scons sed unzip wget xz-utils
After the dependencies are installed, optionally tell MXE what we want to build by default and how we want to build it. This is specified with options in a settings.mk file. We instruct MXE to build a compiler for both 32-bit and 64-bit Windows. To build faster, we can set the number of parallel jobs to the number of cores on our build host. Lastly, MXE can cross-compile a number of packages, but we will just build the cross-compiler itself by default:
cat << EOF > settings.mk MXE_TARGETS := x86_64-w64-mingw32.static i686-w64-mingw32.static JOBS := 8 LOCAL_PKG_LIST := gcc .DEFAULT local-pkg-list: local-pkg-list: $(LOCAL_PKG_LIST) EOF
Get the Emulator
We will use an emulator to find information about the target system and test our executables. Even though the WINE project's name stands for Wine is Not an Emulator, we can utilize this fantastic, mature tool to emulate Windows. Install it on Debian with:
apt-get install wine
Build and Test
To download ITK and create a build directory:
cd ~/src/ git clone http://itk.org/ITK.git cd ~/bin mkdir ITK-MXE32 cd ITK-MXE32
To build and test ITK for 32-bit Windows:
cmake -DCMAKE_BUILD_TYPE=Release \ -DCMAKE_TOOLCHAIN_FILE=~/src/mxe/usr/i686-w64-mingw32.static/share/cmake/mxe-conf.cmake \ -DCMAKE_CROSSCOMPILING_EMULATOR=wine \ ~/src/ITK ctest -j8 -D Experimental
The CMAKE_TOOLCHAIN_FILE variable tells CMake about the cross-compiler toolchain we want to use. The CMAKE_CROSSCOMPILING_EMULATOR variables tells CMake what command can be used to emulate the target system. The ctest command will build and test our software and upload the results to CDash so we can visualize the results.
In this post we went through the steps to develop for 32-bit or 64-bit Windows from an x86_64 Linux host. We demonstrated how both build executables and obtain testing results by only specifying two variables in our CMake configuration, CMAKE_TOOLCHAIN_FILE and CMAKE_CROSSCOMPILING_EMULATOR. The reliability of these testing results depend on the quality of the target system emulator, but the presence of testing results on a dashboard is a big step towards better cross-compilation development.
3 comments to C/C++ Development for Windows Sans Windows
Thanks for the good article.
How would I change the MinGW version used in the build environment mxe? Like using the latest MinGW version with posix threading and dwarf exception handling, that is available from sourceforge?
To use a different version of MinGW, create the appropriate CMake toolchain file  that points to the version of MinGW desired. You could start with the MXE toolchain file as a starting point. A few points of note:
MXE is currently based of MinGW-w64 , which is a more actively maintained fork of MinGW that provides both 32-bit and 64-bit cross compilers.
Dwarf-2 exception handling does not work under 64-bit Windows applications .
Posix threading is slower than the Windows threads .
Hi. Thanks for your post. Really useful. Right now I’m working on a C++ programming contest. I thought it may be interesting for you. It’s about to discover Sprout SDK and try to win a Sprout computer. Here is the website sprout.coderpower.com. Would be great to have your feedback. Cheers