Cross Compiling Python For Windows With Mingw32

Oct
2011
18

Programming, Python

No comments

If you are interested in cross compiling Python 2.7.2 for use in Windows using the Mingw32 cross compiling tools I’ll suggest that you first read my post on how to cross compile it for Android as much of the instructions are the same.

Again, this instructions are tested under Ubuntu 11.04 (Natty) 64 bits . The patch that you’ll need is based on the Android patch, and several other pieces from around the web (including several proposed patches in the Python tracker).

Instead of repeating the instructions all over again, I’ll just point out the differences in the process. Assuming you’ve already downloaded Python’s 2.7.2 source, the patch, created a host version of the Python interpreter and applied the patch for cross compilation, you’ll then need to install the Mingw32 toolset (if you haven’t already):

sudo apt-get install mingw32 mingw32-binutils mingw32-runtime

Prepare the environment:

export ARCH="win32"
export CFLAGS=""
export CXXFLAGS=""
export CC="i586-mingw32msvc-gcc"
export CXX="i586-mingw32msvc-g++"
export AR="i586-mingw32msvc-ar"
export RANLIB="i586-mingw32msvc-ranlib"
export STRIP="i586-mingw32msvc-strip --strip-unneeded"
export LD="i586-mingw32msvc-ld"
export AS="i586-mingw32msvc-as"
export NM="i586-mingw32msvc-nm"
export DLLTOOL="i586-mingw32msvc-dlltool"
export OBJDUMP="i586-mingw32msvc-objdump"
export RESCOMP="i586-mingw32msvc-windres"
export MAKE="make -k -j4 HOSTPYTHON=[PATH TO HOST PYTHON] HOSTPGEN=[PATH TO HOST PGEN]  CROSS_COMPILE=mingw32msvc CROSS_COMPILE_TARGET=yes"
export EXTRALIBS="-lstdc++ -lgcc -lodbc32 -lwsock32 -lwinspool -lwinmm -lshell32 -lcomctl32 -lctl3d32 -lodbc32 -ladvapi32 -lopengl32 -lglu32 -lole32 -loleaut32 -luuid"

Then configure the build:

./configure LDFLAGS="-Wl,--no-export-dynamic -static-libgcc -static $EXTRALIBS" CFLAGS="-DMS_WIN32 -DMS_WINDOWS -DHAVE_USABLE_WCHAR_T" CPPFLAGS="-static" LINKFORSHARED=" " LIBOBJS="import_nt.o dl_nt.o getpathp.o" THREADOBJ="Python/thread.o" DYNLOADFILE="dynload_win.o" --disable-shared HOSTPYTHON=[PATH TO HOST PYTHON] HOSTPGEN=[PATH TO HOST PGEN] --host=i586-mingw32msvc --build=i686-pc-linux-gnu  --prefix="[WHERE YOU WANT TO PUT THE GENERATED PYTHON STUFF]"

You may have noticed that there’s a few static compilation related switches in there. I think it’s possible to compile Python without them, but as I’m building a monolithic app with all the modules compiled in the same exe file, I haven’t really tested the shared library building part of the process. If you do test with shared libraries enabled, then feel free to leave feedback in the comments and I’ll update the article with whatever caveats there might be.

Now comes the hacky stuff…not everything that should be fixed for the cross compilation to succeed is fixed in the patch, so we need to do some manual repairs after the config process is finished.

sed -i "s|\${LIBOBJDIR}fileblocks\$U\.o||g" Makefile
# Enable NT Threads
sed -i "s|.*NT_THREADS.*|#define NT_THREADS|g" pyconfig.h
# Disable PTY stuff that gets activated because of errors in the configure script
sed -i "s|.*HAVE_OPENPTY.*|#undef HAVE_OPENPTY|g" pyconfig.h
sed -i "s|.*HAVE__GETPTY.*|#undef HAVE__GETPTY|g" pyconfig.h
sed -i "s|.*HAVE_DEV_PTMX.*|#undef HAVE_DEV_PTMX|g" pyconfig.h

Finally:

$MAKE

Hopefully you’ll get a static python binary (.exe) and also a static library that you can link against other files. The interactive console seems to work as well (if you copy the generated files to Windows and run python.exe)