Cross-Compiling Windows Applications in Linux with MXE

About a year ago, I started looking into ways to cross-compile Windows applications from within Linux. This brought me to a cool project called MXE (short for M Cross Environment). With MXE, you can use your Linux machine to generate Windows binaries without having to install any virtual machines or compatibility layers. In this post, I’ll walk you through the process of setting up MXE and turning your source code into a Windows program.

What is MXE, and Why is it Useful?

MXE—or the M Cross Environment—is a tool for compiling cross-platform software in Linux. It works for normal applications and also supports a number of free libraries including GTK, Qt, and SDL. It can also target 32-bit or 64-bit platforms. It uses MinGW, an open source development environment for creating Windows applications. And of course, MXE and all of its components are fully open source.

With MXE, software created in Linux can be effortlessly cross-compiled for Windows systems. This makes it significantly easier for developers to port their software to different platforms. Best of all, the software (for the most part) behaves exactly the same on Windows as it does on Linux.

My experience with MXE came when porting a Qt-based desktop application to Windows. Qt is a framework for building graphical applications written in C++ and other languages. Qt runs on Linux and Windows, and the framework handles most idiosyncrasies between the two platforms.

Compiling a Qt application is very straightforward, especially when using Qt Creator, the official IDE for developing Qt-based software. Qt Creator auto-detects any Qt installations on your local system, letting you quickly build and run executables for your current platform. To get an executable for a different platform like Windows, you either need to compile your application in a Windows environment, or use a tool like MXE.

Using MXE is a very straightforward process consisting of downloading MXE, building the required tools, then using those tools to cross-compile your application.

Step 1: Install MXE

The first step is to download MXE. You can either build MXE from source, or download pre-compiled binaries. For the purposes of this post, let’s build it form source.

First, open a terminal and clone the MXE Git repository to your computer. You’ll want to install Git if you don’t already have it installed.

git clone https://github.com/mxe/mxe.git

Next, change into the directory:

cd mxe/

From here, we’ll need to build the tools necessary to cross-compile our projects. Depending on what your project uses, you might need to build one or more of the packages listed on the MXE homepage. Since we’re cross-compiling a Qt project, we’ll focus on the Qt libraries.

Qt is modular by nature, and splits different functionality into different packages. The core functionality is provided by the qtbase package, although you can build other packages if your application requires it. Alternatively, you can build all of Qt using the qt5 package, but this will take much longer to complete than if you had chosen specific packages.

To build the minimum tools required, run:

make qtbase

Or, to build all of Qt, run:

make qt5

This starts the process of downloading and building the cross-compiler along with all of its dependencies. By default, this builds a cross-compiler for 32-bit applications, but you can specify the target (32 or 64-bit) using the MXE_TARGETS environment variable:

make MXE_TARGETS=x86_64-w64-mingw32.static qtbase

This will take some time, so grab a cup of coffee or catch up on the latest news. Once the build is done, you’ll have a new tool for generating Makefiles called qmake, which you’ll use to build your Windows executable.

Step 2: Compile Using MXE

The last step installed the qmake tool under the MXE directory as <MXE directory>/usr/i686-w64-mingw32.static/qt5/bin/qmake. Open your terminal and change your working directory to that of your Qt project. Then, run the following commands:

$ <MXE directory>/usr/i686-w64-mingw32.static/qt5/bin/qmake
$ make

And that’s it! When the build is finished, you can find the Windows executable in the release/ folder. Although you compiled it for 32-bit targets, it will run just as well in 64-bit environments. And since it’s a static executable, you can run it on a system that doesn’t already have Qt installed.

If you choose, you can test your executable by using Wine, a compatibility layer for running Windows programs in Linux:

$ wine release/my-program.exe

(Optional) Step 3: Configure Qt Creator

Qt Creator is a fully-featured IDE for developing Qt applications. If you choose, you can build a Windows executable from within Qt Creator simply by calling your cross-compiled qmake tool instead of the default qmake tool.

Open the Build Settings panel for your project and add a new Release configuration. Under Build Steps, remove the qmake step and replace it with a Custom Process Step. Add the following parameters:

  • Command: Path to the qmake tool generated by MXE (<MXE directory>/usr/i686-w64-mingw32.static/qt5/bin/qmake)
  • Arguments: Path to your project’s main file (%{CurrentProject:FilePath})
  • Working directory: Where to place the executable (I use %{buildDir})

Make sure to change the Build directory and rename the configuration to something meaningful. Now, press Ctrl-B to try building your project. Congratulations, you can now build Windows applications in Linux!

Share your thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.