Cross Compile to Windows From Linux

Gallagher Pryor ArrayFire, C/C++ 7 Comments

Why did I not know about this? It's like I just discovered the screw driver!

On Debian and variants (from tinc's windows cross-compilation page),

sudo apt-get install mingw-w64

# C
i686-w64-mingw32-gcc hello.c -o hello32.exe      # 32-bit
x86_64-w64-mingw32-gcc hello.c -o hello64.exe    # 64-bit

# C++
i686-w64-mingw32-g++ hello.cc -o hello32.exe     # 32-bit
x86_64-w64-mingw32-g++ hello.cc -o hello64.exe   # 64-bit

blown

Granted, this isn't a silver bullet, but rather a quick way to get a Windows build of platform independent code that you might already have running in Linux. I've found that this approach makes it easy to get binaries out the door in a hurry when it's hard to get a project building with Visual Studio or even on the Windows platform itself (due to, say, a complex build system).

I cover some quick solutions to the most common caveats I've run into, below.

Caveats

MinGW GCC vc GCC: Not as Smart with Templates

Whatever the reason, the Debian-packaged mingw flavor of gcc has a tendency to omit the instantiation of templates in many cases leading to missing symbols when linking. For instance, something like the following might sometimes complain that variants of scale can't be found on link,

template  void scale(ty a, ty *X, unsigned n) {
  for (int i = 0; i < n; i++) X[i] = a * X[i];
}
void scale_ALL_the_things(float *A, int *B, unsigned n) {
  scale(2.0, A, n);
  scale(  3, B, n);
}

A horrible (but effective) solution I've found is to push the compile along with a dead function containing references to the template instantiations that you need,

void __force_compile() {
  scale(0, 0, NULL);
  scale(0, 0, NULL);
}

C/C++ Standard Library Dependencies

When compiling C projects, use {i686,x86_64}-w64-mingw32-gcc. The resulting binary will depend on at least KERNEL32.DLL and whatever MSVCRT.DLL is on clients' systems. Therefore, you'll need to make sure clients have the Microsoft C Runtime installed to use your software.

When compiling a C++ project, you must use {i686,x86_64}-w64-mingw32-g++ to at least link. Otherwise, you'll find you are missing LIBSTDC++-6.DLL and/or LIBGCC_S_SJLJ-1.DLL.

When shipping a C++ project, you'll need to include LIBSTDC++-6.DLL and/or LIBGCC_S_SJLJ-1.DLL with your install. You can grab these from your Linux install where you're performing the build in the associated MinGW directory, e.g., /usr/lib/gcc/x86_64-w64-mingw32/4.6/. Note that you can have gcc include these libraries statically by including the flags, -static-libgcc and -static-libstdc++.

External Dependencies

If your project depends on external libraries, you'll need them available on your Linux machine during your build. I give some quick notes for the case where you'd like to use a pre-built (mingw) windows library and specific notes for Boost.

Note that except for purely C external libraries, the libraries themselves must have been built with MinGW. The naming conventions of C++ symbols differ between MingGW and Visual Studio.

Getting a MinGW build going for each project you might want to use is different. tinc's cross compilation page gives instructions for a few libraries that it requires. You'll need to consult the documentation on a project-by-project basis for each of your dependencies.

Using a Prebuilt DLL From Windows (libpng)

LibPNG provides pre-built windows binaries (albeit ancient). To build with the library, download both the binary and developer packages and extract into the same directory. Do the same for zlib since LibPNG depends on it, as well.

To build, give the compiler access to the appropriate include directories and link to the seemingly static .dll.a files. Do not attempt to link to the .dll files. Recall that linking to DLL's on Windows requires a .lib file at build-time; by convention (at least for GNU projects), these are named with a .dll.a extension,

i686-w64-mingw32-gcc -Ilibpng/include -Izlib/include -o pngwriter.exe pngwriter.cc -Llibpng/lib -lpng -Lzlib/lib -lz

MinGW and Boost

I give notes on Boost, here, as it's a popular library and - since much of it is header-based - does not require a build before use in many instances.

If on Debian, you'll need a fresh copy of Boost. When building with Debian's stock version of Boost, MinGW complains of missing headers. Once you've obtained Boost, you're ready to go,

wget 'http://sourceforge.net/projects/boost/files/latest/download?source=files' -O boost.tar.gz
tar xzfp boost.tar.gz
x86_64-w64-mingw32-g++ -Iboost hello.cc -o hello64.exe

Comments 7

  1. Pingback: "easy to get binaries out the door in a hurry"

  2. Pingback: Cross-compilation Ubuntu-Win7 using a custom Makefile instead of qmake - BlogoSfera

  3. Pingback: Cross-compilation Ubuntu-Win7 using a custom Makefile instead of qmake - DexPage

  4. I was wondering if you guys have looked into c++11/c++14 on this at all. I've installed mingw32 on my debian box and, while it works great in most cases, because it is based on gcc 4.6.3 it does not have support for some of the newer features. Do you know if there's a different build based on a newer version of gcc?

    1. You should be able to get a much more up to date mingw by following instructions at, http://win-builds.org/doku.php.

      The instructions at http://win-builds.org/doku.php/download_and_installation_from_linux yielded what I remember as a gcc 4.9 for a linux -> windows cross compiler.

      Judging from the success there, I suspect the windows instructions at http://win-builds.org/doku.php/download_and_installation_from_windows will work. (linked from http://win-builds.org/doku.php/download)

      Indeed, the gcc should be even newer by now.

  5. Neato! I'm really glad you used libpng as an example as that's just the library I'm currently having difficulty with using in Windows builds on Linux - Must be my lucky day!

  6. I have used OPENGL in my program. It is giving error saying that

    alpha.cpp:1:20: fatal error: GL/glut.h: No such file or directory
    #include

    What to do now?

Leave a Reply

Your email address will not be published. Required fields are marked *