How to create a mingw-w64 cross compiler (targeting Windows) on Linux Grab the latest version of binutils and gcc. If you are running an older distro, you /might/ have trouble compiling gcc and/or binutils. If that is the case, try with the matching version of binutils and gcc of your distribution. You also need to download gmp, mpfr and mpc from a GNU site. Optionally also get isl library. When this guide was written I used binutils-2.32 gcc-8.3.0 gmp-6.1.2 mpfr-4.0.2 mpc-1.1.0 isl-0.21 mingw-w64 v6.x branch from git (ade3f5a from 4th of January 2019) You also may need the following installed on your system: flex, bison, make (gnu make), texinfo Unpack every tarball $ for i in *.tar*; do tar xf $i; done Add gmp, mpfr, mpc and isl to gcc build $ cd gcc-*/ $ for i in gmp mpfr mpc isl; do ln -sf ../$i-*/ $i; done The reason for this is that gcc is dependent on these libraries. IF you have this libraries installed on your system (and the corrosponding -dev/-devel packages) you can skip this step. It's possible to install these libraries by hand, but I've found it easier to get gcc build system to do this step, since it's designed to. GCC and binutils does not like be built from within the source directory, so first order of buisness is to create a top level build directory. To speed up compilation somewhat I would suggest that you do this in /tmp if /tmp is tmpfs. Lets set some variables to make things easier OBJDIR=/tmp/build PREFIX=/tmp/build/cross-mingw-w64 TARGET=x86_64-w64-mingw32 TARGET32=i686-w64-mingw32 export PATH=${PREFIX}/bin:$PATH mkdir -p ${OBJDIR} cd ${OBJDIR} First binutils mkdir -p ${OBJDIR}/binutils.${TARGET} cd ${OBJDIR}/binutils.${TARGET} ${HOME}/binutils-*/configure --prefix=${PREFIX} --target=${TARGET} && \ sed -i 's/\-g /-pipe /' Makefile && \ make -j$(nproc) && make install-strip -j4 mingw-w64 headers Now, you don't *really* need to install them now. We can wait until the first pass of gcc is complete. But in order for gcc to compile, gcc needs the directory ${PREFIX}/mingw/include to exist. Which is funny, because we're going to set sysroot to $PREFIX. What this means for a mingw-w64 cross compiler (but not other cross compilers!) is that gcc looks for libraries and headers into ${PREFIX}/mingw when *installing* gcc. After gcc is installed, it does not care about ${PREFIX}/mingw at all. It won't even look for the headers or libraries there. It will rather look for the headers and libraries in ${PREFIX}/${TARGET}, so therefore we must trick gcc a bit here. You can remove the symlink after all this, if you wish. mkdir -p ${OBJDIR}/mingw-w64-headers cd ${OBJDIR}/mingw-w64-headers ${HOME}/mingw-w64-*/mingw-w64-headers/configure --prefix=${PREFIX}/${TARGET} make && make install ln -s ${PREFIX}/${TARGET} ${PREFIX}/mingw Next up is gcc - gcc is done in two steps. First we install the compiler only, which will be only used to compile mingw-w64 C library. After that, we compile the rest of gcc. mkdir ${OBJDIR}/gcc.${TARGET} cd ${OBJDIR}/gcc.${TARGET} ${HOME}/gcc-*/configure --prefix=${PREFIX} --libexecdir=${PREFIX}/lib --target=${TARGET} --enable-languages=c,c++ \ --disable-libstdcxx-pch --enable-libgomp --enable-threads=posix --with-sysroot=${PREFIX} && \ sed -i 's/\-g /-pipe /' Makefile && \ make all-gcc -j$(nproc) && make install-strip-gcc -j4 --libexecdir= I personally have having a libexec directory in $PREFIX. With this we put those files into ${PREFIX}/lib instead --enable-languages= This guide only covers C and C++, which is the only compilers I use. --disable-libstdcxx-pch - Gcc uses something called pre-compiled headers. I've never seen them used, and they eat of disk space and it takes long to compile them. Therefore I skip it. --enable-libgomp - this is for the threading library which we will install later on. Without the external (from GCC's point of view, the library is from mingw-x64 project) library libgomp is not available, therefore we must "force" it. The default is enabled on linux systems. --enable-threads=posix - same explenation as --enble-libgomp --with-sysroot - For some reason this is mandatory when building a multilib compiler. Perhaps it's a bug, I don't know. But without it, the build will fail. if you rather build a non-multilib compiler, you can skip this. mingw-w64-crt (C runtime library) mkdir -p ${OBJDIR}/mingw-w64-crt && \ cd ${OBJDIR}/mingw-w64-crt && \ ${HOME}/mingw-w64-*/mingw-w64-crt/configure --prefix=${PREFIX}/${TARGET} --host=${TARGET} --enable-wildcard && \ sed -i 's/\-g /-pipe /' Makefile && \ make -j$(nproc) && make install -j4 #--enable-wildcard - not quite sure I understand what this does, but a lot of other people have this enabled. So I'll keep it enabled to. Here comes some of the tricky part winpthreads winpthreads is not multilib aware, so we must install it twice manually. One for 64bit (the default target) and one for 32bit. I've done that like so: mkdir -p ${OBJDIR}/winpthreads.${TARGET} cd ${OBJDIR}/winpthreads.${TARGET} ${HOME}/mingw-w64-*/mingw-w64-libraries/winpthreads/configure --prefix=${PREFIX}/${TARGET} --host=${TARGET} sed -i 's/\-g /-pipe /' Makefile && \ make -j$(nproc) && make install-strip -j4 mv ${PREFIX}/${TARGET}/bin/libwinpthread-1.dll ${PREFIX}/${TARGET}/lib #if we do not move the dll it will be overwritten when we install the 32bit version mkdir -p ${OBJDIR}/winpthreads.${TARGET32} cd ${OBJDIR}/winpthreads.${TARGET32} ${HOME}/mingw-w64-*/mingw-w64-libraries/winpthreads/configure --prefix=${PREFIX}/${TARGET} --host=${TARGET} CC="${TARGET}-gcc -m32" CCAS="${TARGET}-gcc -m32" DLLTOOL="${TARGET}-dlltool -m i386" RC="${TARGET}-windres -F pe-i386" && \ sed -i 's/\-g /-pipe /' Makefile && \ make -j$(nproc) && make install-strip DESTDIR=$(pwd)/dest && \ mv dest/${PREFIX}/${TARGET}/bin/*.dll dest/${PREFIX}/${TARGET}/lib/ && \ cp -a dest/${PREFIX}/${TARGET}/lib/* ${PREFIX}/${TARGET}/lib32/ Now, we can continue with gcc cd ${OBJDIR}/gcc.${TARGET} make -j$(nproc) && make install-strip -j4 Almost finished, just some small cleanup left (very optional) rm -rf ${PREFIX}/lib/libcc* ${PREFIX}/{include,share,mingw} find ${PREFIX} \( -name '*.la' -o -name '*.py' -o -name '*.spec' \) -delete find ${PREFIX} -name '*.dll' | cut -f 1 -d : | xargs ${TARGET}-strip -s find ${PREFIX}/${TARGET} \( -name '*.a' -o -name '*.o' \) | xargs ${TARGET}-strip -g find ${PREFIX}/lib/gcc/${TARGET} \( -name '*.a' -o -name '*.o' \) | xargs ${TARGET}-strip -g Now if you like you can move ${PREFIX} to wherever you want. Perhaps you want to move it into /opt. The only variable that you need to think about is ${PATH} - if you moved the install location, you must add the new ${PREFIX}/bin to ${PATH}